1 package body WFA_HTML as
2 /* $Header: wfhtmb.pls 120.5.12010000.7 2009/12/09 18:47:45 vshanmug ship $ */
3
4 -- Bug# 2236250 exception to handle invalid number
5 invalid_number exception;
6 pragma EXCEPTION_INIT(invalid_number, -6502);
7
8
9 g_priority varchar2(2000);
10 g_newline varchar2(1) := wf_core.newLine;
11 g_wfInstall varchar2(15) := wf_core.translate('WF_INSTALL');
12 g_webAgent varchar2(2000) := wf_core.translate('WF_WEB_AGENT');
13
14 --
15 -- Error (PRIVATE)
16 -- Print a page with an error message.
17 -- Errors are retrieved from these sources in order:
18 -- 1. wf_core errors
19 -- 2. Oracle errors
20 -- 3. Unspecified INTERNAL error
21 --
22 procedure Error
23 as
24
25 begin
26 null;
27 end Error;
28
29
30 --
31 --
32 -- Login
33 -- Generate login page.
34 -- IN
35 -- message - optional login message
36 -- NOTE
37 -- This page is only used to enable access when no external security
38 -- is installed. Normally users are authenticated by the chosen
39 -- security system (IC, WebServer native, etc) and can then access
40 -- the Workflow Notification pages (Worklist, Detail) directly.
41 --
42 procedure Login(
43 message in varchar2,
44 i_direct in varchar2)
45 as
46
47 c_language VARCHAR2(80);
48
49 begin
50
51 -- Get the global language preference since we don't know who the
52 -- user is yet...
53 c_language := NVL(wf_pref.get_pref ('-WF_DEFAULT-', 'LANGUAGE'), 'AMERICAN');
54 c_language := ''''||c_language||'''';
55 dbms_session.set_nls('NLS_LANGUAGE' , c_language);
56
57 -- Set the language to the default language for the system
58
59 htp.htmlOpen;
60 htp.headOpen;
61 htp.title(wf_core.translate('WFA_LOGIN_REQUEST'));
62 wfa_html.create_help_function('wf/links/log.htm?LOGIN');
63 htp.headClose;
64 wfa_sec.Header(background_only=>FALSE, inc_lov_applet=>FALSE);
65
66 htp.p('<FORM NAME="WFA_LOGIN" ACTION="wfa_html.Viewer" TARGET="_top" METHOD="POST">');
67
68 -- bug 1838410
69 if (i_direct is not null) then
70 htp.formHidden('i_direct', i_direct);
71 end if;
72
73
74 if (message is not null) then
75 htp.header(4, wf_core.translate(message));
76 htp.br;
77 end if;
78
79 htp.br;
80 htp.tableOpen(calign=>'CENTER', cattributes=>'summary=""');
81 htp.tableRowOpen;
82 htp.tableData('<LABEL FOR="i_user_id">' ||
83 wf_core.translate('USER_ID') ||
84 '</LABEL>', 'Right',
85 cattributes=>'id=""');
86 htp.tableData(htf.formText('User_ID', 25, cattributes=>'id="i_user_id"'),
87 'Left', cattributes=>'id=""');
88 htp.tableRowClose;
89
90 htp.tableRowOpen;
91 htp.tableData('<LABEL FOR="i_password">' ||
92 wf_core.translate('PASSWORD') ||
93 '</LABEL>', 'Right',
94 cattributes=>'id=""');
95 htp.tableData(htf.formPassword('Password', 25,
96 cattributes=>'id="i_password"'), 'Left',
97 cattributes=>'id=""');
98 htp.tableRowClose;
99
100 htp.tableClose;
101 htp.centerClose;
102 htp.br;
103
104 htp.formClose;
105
106 htp.tableopen (calign=>'CENTER', cattributes=>'summary=""');
107 htp.tableRowOpen;
108
109 htp.p('<TD id="">');
110
111 wfa_html.create_reg_button ('javascript:document.WFA_LOGIN.submit()',
112 wf_core.translate ('LOGIN'),
113 wfa_html.image_loc,
114 'FNDJLFOK.gif',
115 wf_core.translate ('LOGIN'));
116
117 htp.p('</TD>');
118
119 htp.tableRowClose;
120 htp.tableClose;
121
122 wfa_sec.Footer;
123 htp.htmlClose;
124 exception
125 when others then
126 rollback;
127 wf_core.context('Wfa_Html', 'Login');
128 wfa_html.Error;
129 end Login;
130
131 --
132 -- Viewer
133 -- Validate user from Login page, then show worklist.
134 -- IN
135 -- user_id - user name
136 -- password - user password
137 -- NOTE
138 -- This page is only used to enable access when no external security
139 -- is installed. Normally users are authenticated by the chosen
140 -- security system (IC, WebServer native, etc) and can then access
141 -- the Workflow Notification pages (Worklist, Detail) directly.
142 --
143 procedure Viewer(
144 user_id in varchar2,
145 password in varchar2,
146 i_direct in varchar2)
147 as
148 s0 varchar2(320); -- dummy
149 username varchar2(320);
150 realname varchar2(360);
151
152 begin
153 -- Validate the user
154 if (user_id is null) then
155 -- No username entered
156 wfa_html.Login('WFA_ENTER_ID');
157 return;
158 end if;
159 username := upper(user_id);
160
161 begin
162 wfa_sec.CreateSession(username, password);
163 exception
164 when others then
165 if (wf_core.error_name='WFSEC_USER_PASSWORD') then
166 -- Bad username or password
167 wf_core.clear;
168 wfa_html.Login('WFA_ILLEGAL_IDP');
169 return;
170 end if;
171 -- Raise any other error message
172 raise;
173 end;
174
175 if (i_direct is null) then
176
177 -- Go to home page
178 Wfa_Html.Home;
179
180 else
181 -- Fix for bug 1838410
182 -- Instead of navigating to the home page, we will go directly to the URL
183 -- specified in i_direct and the user will now be authenticated. We are
184 -- calling the function within a frame.
185 -- Example: E-mail notifications with send_accesskey=N.
186
187 htp.p('<HTML>');
188 htp.p('<HEAD>');
189 htp.p('<TITLE>');
190 htp.p('</TITLE>');
191 htp.p('</HEAD>');
192 htp.p('<FRAMESET ROWS="100%, *">');
193 htp.p('<FRAME NAME="DirectLogin" MARGINHEIGHT=10 MARGINWIDTH=10 NORESIZE' ||
194 ' src="'||owa_util.get_owa_service_path || i_direct || '">');
195 htp.p('</FRAMESET>');
196 htp.p('</HTML>');
197
198 end if;
199
200 exception
201 when others then
202 rollback;
203 wf_core.context('Wfa_Html', 'Viewer', user_id, password);
204 wfa_html.Error;
205 end Viewer;
206
207
208 --
209 -- Find
210 -- Filter page to find notifications of user
211 --
212 procedure Find
213 is
214 begin
215 null;
216 end Find;
217
218 --
219 -- GetPriorityBounds
220 -- Get the upper bound and lower bound of certain priority
221 -- IN
222 -- priority - Value of priority
223 -- Valid values are HIGH, NORMAL, LOW and *
224 -- IN OUT
225 -- low - lower bound of numeric priority value
226 -- up - upper bound of numeric priority value
227 -- RETURNS
228 -- TRUE - successfully return the boundaries
229 -- FALSE - failed to translate
230 --
231 function GetPriorityBounds(
232 priority in varchar2,
233 low in out nocopy pls_integer,
234 up in out nocopy pls_integer)
235 return boolean
236 as
237 -- minint pls_integer := 0;
238 -- maxint pls_integer := 2147483647; /* 2^31 - 1 */
239
240 --
241 -- Priority Range should be 1 - 99
242 -- For supporting some possible out of range value in the past,
243 -- we set the range a bit higher
244 --
245 minint pls_integer := 0;
246 maxint pls_integer := 1000000;
247 begin
248 if (priority = '*') then
249 low := minint;
250 up := maxint;
251 elsif (priority = 'HIGH') then
252 low := minint;
253 up := 33;
254 elsif (priority = 'NORMAL') then
255 low := 34;
256 up := 66;
257 elsif (priority = 'LOW') then
258 low := 67;
259 up := maxint;
260 else
261 low := -1;
262 up := -1;
263 return FALSE;
264 end if;
265 return TRUE;
266 end GetPriorityBounds;
267
268 --
269 -- GetPriorityIcon
270 -- Get the icon of certain numeric priority
271 -- IN
272 -- priority - Value of priority
273 -- Valid values are minint - maxint
274 -- defined in GetPriorityBounds
275 --
276 -- RETURNS
277 -- Icon - location of an icon
278 --
279 function GetPriorityIcon(
280 priority in pls_integer)
281 return varchar2
282 as
283 begin
284 if (priority < 34) /* HIGH */ then
285 WFA_HTML.g_priority := WF_CORE.Translate('WFJSP_HIGH_PRIORITY');
286 return(wfa_html.image_loc||'high.gif');
287 elsif (priority > 66) /* LOW */ then
288 WFA_HTML.g_priority := WF_CORE.Translate('WFJSP_LOW_PRIORITY');
289 return(wfa_html.image_loc||'low.gif');
290 else /* NORMAL */
291 return null;
292 end if;
293 end GetPriorityIcon;
294
295 --
296 -- WorkList
297 -- Construct the worklist (summary page) for user.
298 -- IN
299 -- orderkey - Key to order by (default PRIORITY)
300 -- Valid values are PRIORITY, MESSAGE_TYPE, SUBJECT, BEGIN_DATE,
301 -- DUE_DATE, END_DATE, STATUS.
302 -- status - Status to query (default OPEN)
303 -- Valid values are OPEN, CLOSED, CANCELED, ERROR, *.
304 -- user - User to query notifications for. If null query user currently
305 -- logged in.
306 -- Note: Only a user in role WF_ADMIN_ROLE can query a user other
307 -- than the current user.
308 -- fromlogin - flag to indicate if coming from apps login screen,
309 -- - if non-zero, force an exception
310 -- - so that cookie value is not being used
311 --
312 procedure WorkList(
313 nid in number,
314 orderkey in varchar2,
315 status in varchar2,
316 owner in varchar2 ,
317 display_owner in varchar2,
318 user in varchar2,
319 display_user in varchar2,
320 fromuser in varchar2,
321 display_fromuser in varchar2,
322 ittype in varchar2,
323 msubject in varchar2,
324 beg_sent in varchar2,
325 end_sent in varchar2,
326 beg_due in varchar2,
327 end_due in varchar2,
328 priority in varchar2,
329 delegatedto in varchar2,
330 display_delegatedto in varchar2,
331 delegated_by_me in number,
332 resetcookie in number,
333 clearbanner in varchar2,
334 fromfindscreen in number,
335 fromlogin in number)
336 as
337 begin
338 null;
339 end Worklist;
340
341 --
342 -- Authenticate (PRIVATE)
343 -- Verify user is allowed access to this notification
344 -- IN
345 -- nid - notification id
346 -- nkey - notification access key (if disconnected)
347 -- RETURNS
348 -- Current user name
349 --
350 function Authenticate(
351 nid in number,
352 nkey in varchar2)
353 return varchar2
354 is
355 usercolon pls_integer;
356 rolecolon pls_integer;
357 origcolon pls_integer;
358 username varchar2(320);
359 recipient varchar2(320);
360 orig_recipient varchar2(320);
361 dummy pls_integer;
362 admin_role varchar2(320);
363 slash pls_integer;
364 wfsession varchar2(240);
365
366 uos varchar2(320);
367 uosid number;
368 ros varchar2(320);
369 rosid number;
370 oos varchar2(320);
371 oosid number;
372 begin
373 if (nkey is null) then
374 -- No nkey passed, means must be connected. Get current user.
375 Wfa_Sec.GetSession(username);
376
377 -- Get recipient and original recipient of this notification
378 begin
379 select RECIPIENT_ROLE, ORIGINAL_RECIPIENT
380 into recipient, orig_recipient
381 from WF_NOTIFICATIONS WN
382 where WN.NOTIFICATION_ID = nid;
383 exception
384 when no_data_found then
385 Wf_Core.Token('NID', nid);
386 Wf_Core.Raise('WFNTF_NID');
387 end;
388
389 -- Verify this notification was sent to this user
390 -- Note that username could be the in the recipient role
391 -- or in the original recipient role.
392 begin
393 usercolon := instr(username, ':');
394 rolecolon := instr(recipient, ':');
395 origcolon := instr(orig_recipient, ':');
396
397 if (usercolon = 0) then
398 -- very costly sql statement, return the first row we find.
399 select ORIG_SYSTEM, ORIG_SYSTEM_ID
400 into uos, uosid
401 from WF_USERS
402 where NAME = username
403 and ORIG_SYSTEM not in ('HZ_PARTY','CUST_CONT')
404 and rownum < 2;
405 else
406 uos := substr(username, 1, usercolon-1);
407 uosid := to_number(substr(username, usercolon+1));
408 end if;
409
410 if (rolecolon = 0) then
411 -- when recipient = username, user is participate in the role of
412 -- the same name, they will have the same orig system and orig
413 -- system id.
414 if (recipient = username) then
415 ros := uos;
416 rosid := uosid;
417 else
418 Wf_Directory.GetRoleOrigSysInfo(recipient,ros,rosid);
419 end if;
420 else
421 ros := substr(recipient, 1, rolecolon-1);
422 rosid := to_number(substr(recipient, rolecolon+1));
423 end if;
424
425 if (origcolon = 0) then
426 -- similarly, don't bother to requery the orig_system and
427 -- orig_system_id if original recipient matches recipient or username.
428 if (orig_recipient = recipient) then
429 oos := ros;
430 oosid := rosid;
431 elsif (orig_recipient = username) then
432 oos := uos;
433 oosid := uosid;
434 else
435 Wf_Directory.GetRoleOrigSysInfo(orig_recipient,oos,oosid);
436 end if;
437 else
438 oos := substr(orig_recipient, 1, origcolon-1);
439 oosid := to_number(substr(orig_recipient, origcolon+1));
440 end if;
441
442 -- rewritten the sql from an or join to union all.
443 -- reduced the query time from >25 sec to <0.5 sec.
444 select 1
445 into dummy
446 from sys.dual
447 where exists (
448 select null
449 from WF_USER_ROLES
450 where USER_ORIG_SYSTEM = uos
451 and USER_ORIG_SYSTEM_ID = uosid
452 and USER_NAME = username
453 and ROLE_ORIG_SYSTEM = ros
454 and ROLE_ORIG_SYSTEM_ID = rosid
455 and ROLE_NAME = recipient
456 union all
457 select null
458 from WF_USER_ROLES
459 where USER_ORIG_SYSTEM = uos
460 and USER_ORIG_SYSTEM_ID = uosid
461 and USER_NAME = username
462 and ROLE_ORIG_SYSTEM = oos
463 and ROLE_ORIG_SYSTEM_ID = oosid
464 and ROLE_NAME = orig_recipient
465 );
466
467 exception
468 when no_data_found then
469 -- Check if current user has WF_ADMIN_ROLE privileges.
470 -- If so, allow access anyway.
471 admin_role := wf_core.translate('WF_ADMIN_ROLE');
472 if (admin_role <> '*' and
473 not Wf_Directory.IsPerformer(username, admin_role)) then
474 Wf_Core.Token('USER', username);
475 Wf_Core.Token('NID', to_char(nid));
476 Wf_Core.Raise('WFNTF_ACCESS_USER');
477 end if;
478 end;
479 else
480 -- Nkey passed, means this must be disconnected (mailed html).
481 -- Check the passed access key against the notification key.
482
483 -- Construct wfsession-style access key as <nid>/<accesskey>.
484 -- First strip <nid> from nkey if present (only for backward
485 -- compatibility, current version only passes <accesskey>),
486 -- then construct full key with current nid.
487 -- Note: Key is reconstructed here instead of passing full
488 -- <nid>/<accesskey> directly to check that the key being passed
489 -- is really for this notification.
490 slash := instr(nkey, '/');
491 if (slash <> 0) then
492 wfsession := to_char(nid)||'/'||substr(nkey, slash+1);
493 else
494 wfsession := to_char(nid)||'/'||nkey;
495 end if;
496
497 username := Wf_Notification.AccessCheck(wfsession);
498 if (username is null) then
499 wf_core.raise('WFNTF_ACCESS_KEY');
500 end if;
501 end if;
502
503 return(username);
504
505 exception
506 when others then
507 wf_core.context('Wfa_Html', 'Authenticate', to_char(nid), nkey);
508 raise;
509 end Authenticate;
510
511 --
512 -- DetailFrame
513 -- generate Detail notification screen
514 -- IN
515 -- nid - notification id
516 -- nkey - notification access key (for mailed html only)
517 -- agent - web agent (OBSOLETE - for back compatibility only)
518 -- showforms - show form attributes
519 --
520 procedure DetailFrame(
521 nid in varchar2,
522 nkey in varchar2,
523 agent in varchar2,
524 showforms in varchar2)
525 as
526 begin
527 -- bug 7314545
528 null;
529 end DetailFrame;
530
531 --
532 -- ResponseFrame
533 -- generate response frame contents
534 -- IN
535 -- nid - notification id
536 -- nkey - notification access key (for mailed html only)
537 -- agent - web agent (OBSOLETE - for back compatibility only)
538 -- showforms - show form attributes
539 --
540 procedure ResponseFrame(
541 nid in varchar2,
542 nkey in varchar2,
543 agent in varchar2,
544 showforms in varchar2)
545 as
546 begin
547 -- bug 7314545
548 null;
549 end ResponseFrame;
550
551 --
552 -- ForwardFrame
553 -- generate forward frame contents
554 -- IN
555 -- nid - notification id
556 -- nkey - notification access key (for mailed html only)
557 --
558 procedure ForwardFrame(
559 nid in varchar2,
560 nkey in varchar2)
561 as
562 begin
563 -- bug 7314545
564 null;
565 end ForwardFrame;
566
567 --
568 -- AttributeInfo
569 -- Generate page with details about a response attribute
570 -- IN
571 -- nid - notification id
572 -- name - attribute name
573 --
574 procedure AttributeInfo(
575 nid in varchar2,
576 name in varchar2)
577 is
578 begin
579 -- bug 7314545
580 null;
581 end AttributeInfo;
582
583 --
584 -- RespFrameSize (RPIVATE)
585 -- Calculate size of response frame using heuristic
586 -- IN
587 -- nid - notification id
588 -- RETURNS
589 -- Size of response frame in pixels
590 --
591 function RespFrameSize(
592 nid in number)
593 return number
594 is
595 respcnt pls_integer;
596 longcnt pls_integer;
597 urlcnt pls_integer;
598 respsize pls_integer;
599
600 begin
601 -- Approximate size of response frame using heuristic:
602 -- The rule of thumb being :
603 -- 1. Each non-result response counts as 40 pixels
604 -- + url and multiline fields count twice
605 -- + 1 for result button line
606 -- 2. Frame must be in range 100 - 250 pixels
607 -- 3. If there is a url respond attributet then go for the max size
608
609 -- Count of multiline response fields
610 select count(1)
611 into urlcnt
612 from WF_MESSAGE_ATTRIBUTES MA,
613 WF_NOTIFICATIONS N
614 where N.NOTIFICATION_ID = nid
615 and MA.MESSAGE_NAME = N.MESSAGE_NAME
616 and MA.MESSAGE_TYPE = N.MESSAGE_TYPE
617 and MA.SUBTYPE = 'RESPOND'
618 and MA.TYPE = 'URL';
619
620 if (urlcnt = 1) then
621 respsize := 250;
622 else
623
624 -- Count of all response fields
625 select count(1)
626 into respcnt
627 from WF_NOTIFICATION_ATTRIBUTES NA,
628 WF_MESSAGE_ATTRIBUTES MA,
629 WF_NOTIFICATIONS N
630 where N.NOTIFICATION_ID = nid
631 and NA.NOTIFICATION_ID = N.NOTIFICATION_ID
632 and MA.MESSAGE_NAME = N.MESSAGE_NAME
633 and MA.MESSAGE_TYPE = N.MESSAGE_TYPE
634 and MA.NAME = NA.NAME
635 and MA.SUBTYPE = 'RESPOND'
636 and MA.TYPE <> 'FORM'
637 and MA.NAME <> 'RESULT';
638
639 -- Count of multiline response fields
640 select count(1)
641 into longcnt
642 from WF_NOTIFICATION_ATTRIBUTES NA,
643 WF_MESSAGE_ATTRIBUTES MA,
644 WF_NOTIFICATIONS N
645 where N.NOTIFICATION_ID = nid
646 and NA.NOTIFICATION_ID = N.NOTIFICATION_ID
647 and MA.MESSAGE_NAME = N.MESSAGE_NAME
648 and MA.MESSAGE_TYPE = N.MESSAGE_TYPE
649 and MA.NAME = NA.NAME
650 and MA.SUBTYPE = 'RESPOND'
651 and MA.TYPE = 'VARCHAR2'
652 and decode(MA.TYPE, 'VARCHAR2', nvl(to_number(MA.FORMAT), 2000), 0) > 80;
653
654
655 respsize := (respcnt + longcnt + 1) * 40;
656 if (respsize < 100) then
657 respsize := 100;
658 elsif (respsize > 250) then
659 respsize := 250;
660 end if;
661 end if;
662
663 return(respsize);
664
665 exception
666 when others then
667 wf_core.context('Wfa_Html', 'RespFrameSize', to_char(nid));
668 raise;
669 end RespFrameSize;
670
671 --
672 -- Detail (PROCEDURE)
673 -- generate detail screen
674 -- IN
675 -- nid - notification id
676 -- NOTE
677 -- Detail is overloaded.
678 -- This version is used by the Web notifications page.
679 --
680 procedure Detail(
681 nid in varchar2)
682 is
683 begin
684 -- bug 7314545
685 null;
686 end Detail;
687
688 --
689 -- Detail (FUNCTION)
690 -- return standalone detail screen text
691 -- IN
692 -- nid - notification id
693 -- nkey - notification key
694 -- agent - web agent URL root
695 -- NOTE
696 -- Detail is overloaded.
697 -- This produces the version used by the mailer.
698 function Detail(
699 nid in number,
700 nkey in varchar2,
701 agent in varchar2)
702 return varchar2
703 as
704 username varchar2(320);
705 status varchar2(8);
706 realname varchar2(360);
707 s0 varchar2(240);
708 result varchar2(32000);
709 respsize pls_integer;
710 key varchar2(255);
711 n_sig_policy varchar2(100);
712 begin
713
714 Wf_Mail.GetSignaturePolicy(nid, n_sig_policy);
715
716 if (wf_mail.send_accesskey and n_sig_policy not in ('PSIG_ONLY')) then
717 key := nkey;
718
719 -- Authenticate the user has access
720 username := Wfa_Html.Authenticate(nid, nkey);
721
722 -- Get notification recipient and status
723 Wf_Notification.GetInfo(nid, username, s0, s0, s0, s0, status);
724 Wf_Directory.GetRoleInfo(username, realname, s0, s0, s0, s0);
725
726 -- Set title
727 result := htf.htmlOpen ||g_newLine;
728 result := result || htf.headOpen||g_newLine;
729 if (status = 'OPEN') then
730 result := result ||
731 htf.title(wf_core.translate('WFA_DTITLE')||' '||realname)||
732 g_newLine;
733 else
734 result := result ||
735 htf.title(wf_core.translate('WFA_CDTITLE')||' '||realname)||
736 g_newLine;
737 end if;
738
739 --tr: dont execute the help function
740 --it calls htp procs which causes session to hang
741 -- wfa_html.create_help_function('wf/links/det.htm?DETNOT');
742
743 result := result || htf.headClose||g_newLine;
744
745 -- Calculate size of response frame
746 respsize := RespFrameSize(nid);
747
748 -- Open frameset.
749 -- NOTE: Do NOT set the focus here, because it is not supported on
750 -- all platforms, and it is unknown at this point what browser will
751 -- be used to display the html returned to the mailer.
752 result := result||'<FRAMESET ROWS="*,'||to_char(respsize)||'" TITLE="' ||
753 WF_CORE.Translate('WFA_DTITLE_TBAR') || '" LONGDESC="' ||
754 agent ||
755 'wfa_html.LongDesc?p_token=WFA_DTITLE_TBAR">'||
756 g_newLine;
757 result := result ||
758 '<FRAME NAME="top" MARGINHEIGHT=10 MARGINWIDTH=10 ' ||
759 'src="'||agent||'/wfa_html.DetailFrame?nid='||to_char(nid)||
760 '&'||'nkey='||key||'" TITLE="' ||
761 WF_CORE.Translate('WFA_DTITLE_TBAR') || '" LONGDESC="' ||
762 agent ||
763 'wfa_html.LongDesc?p_token=WFA_DTITLE_TBAR">'||g_newLine;
764 result := result ||
765 '<FRAME NAME="bottom" MARGINHEIGHT=10 MARGINWIDTH=10 ' ||
766 'src="'||agent||'/wfa_html.ResponseFrame?nid='||to_char(nid)||
767 '&'||'nkey='||key||'" TITLE="' ||
768 WF_CORE.Translate('WFA_DTITLE_TBAR') || '" LONGDESC="' ||
769 agent ||
770 'wfa_html.LongDesc?p_token=WFA_DTITLE_TBAR">'||g_newLine;
771 result := result || '</FRAMESET>'||g_newLine;
772 result := result || htf.htmlClose;
773
774 else
775 -- Send_accesskey is set to N so we will generate a DirectLogin call.
776 -- We do not need to authenticate the user, since the user will have
777 -- to authenticate to view the notification. After authentication,
778 -- DirectLogin will redirect to the Detail (Web-interface) procedure so
779 -- we will then confirm that the user logged in can also view the
780 -- notification.
781 key := NULL;
782
783 result := htf.htmlOpen ||g_newLine;
784 result := result || htf.headOpen||g_newLine;
785 result := result ||
786 htf.title(wf_core.translate('WFA_LOGIN_REQUEST'))||
787 g_newLine;
788 result := result || htf.headClose||g_newLine;
789
790 result := result||'<FRAMESET ROWS="100%, *">'||g_newLine;
791
792 result := result ||
793 '<FRAME NAME="DirectLogin" MARGINHEIGHT=10 MARGINWIDTH=10 NORESIZE' ||
794 ' src="'||agent || '/' || wfa_sec.DirectLogin(nid) || '">'||g_newLine;
795 result := result || '</FRAMESET>'||g_newLine;
796 result := result || htf.htmlClose;
797 end if;
798
799 return(result);
800 exception
801 when others then
802 wf_core.context('Wfa_Html', 'Detail', to_char(nid), nkey, agent);
803 raise;
804 end Detail;
805
806 --
807 -- Detail2 (FUNCTION)
808 -- return standalone detail screen text
809 -- IN
810 -- nid - notification id
811 -- nkey - notification key
812 -- agent - web agent URL root
813 -- NOTE
814 -- Detail is overloaded.
815 -- This produces the version used by the mailer.
816 function Detail2(
817 nid in number,
818 nkey in varchar2,
819 agent in varchar2)
820 return varchar2
821 as
822 username varchar2(320);
823 status varchar2(8);
824 realname varchar2(360);
825 s0 varchar2(240);
826 result varchar2(32000);
827 n_sig_policy varchar2(100);
828 url varchar2(4000);
829 l_function_id number;
830 begin
831
832 Wf_Mail.GetSignaturePolicy(nid, n_sig_policy);
833
834 -- Authenticate the user has access
835 username := Wfa_Html.Authenticate(nid, nkey);
836
837 -- Get notification recipient and status
838 Wf_Notification.GetInfo(nid, username, s0, s0, s0, s0, status);
839 Wf_Directory.GetRoleInfo(username, realname, s0, s0, s0, s0);
840
841 -- Set title
842 result := htf.htmlOpen ||g_newLine;
843 result := result || htf.headOpen||g_newLine;
844 if (status = 'OPEN') then
845 result := result ||
846 htf.title(wf_core.translate('WFA_DTITLE')||' '||realname)||
847 g_newLine;
848 else
849 result := result ||
850 htf.title(wf_core.translate('WFA_CDTITLE')||' '||realname)||
851 g_newLine;
852 end if;
853
854 result := result || htf.headClose||g_newLine;
855
856 -- Open frameset.
857 -- NOTE: Do NOT set the focus here, because it is not supported on
858 -- all platforms, and it is unknown at this point what browser will
859 -- be used to display the html returned to the mailer.
860 if g_wfInstall='EMBEDDED' then
861 result := result || htf.bodyOpen || g_newLine;
862 result := result || '<SCRIPT LANGUAGE="JavaScript">' || g_newLine;
863 result := result || '<!--' || g_newLine;
864
865 url := wf_mail.Get_Ntf_Function_URL(nid => nid,
866 n_key => nkey,
867 n_sig_policy => n_sig_policy,
868 n_override_agent => agent);
869
870 result := result || 'self.location = '''||url||''';' || g_newLine;
871 result := result || '//-->' || g_newLine || '</SCRIPT>' || g_newLine;
872 result := result || htf.bodyClose || g_newLine || htf.htmlClose;
873 else
874 -- While the call is within standalone, continue to
875 -- operate as before.
876 if (agent is null) then
877 result := wfa_html.detail(nid, nkey, g_webAgent);
878 else
879 result := wfa_html.detail(nid, nkey, agent);
880 end if;
881 end if;
882
883 return(result);
884 exception
885 when others then
886 wf_core.context('Wfa_Html', 'Detail', to_char(nid), nkey, agent);
887 raise;
888 end Detail2;
889
890
891 -- DetailLink
892 -- display standalone detail screen text
893 -- IN
894 -- nid - notification id
895 -- nkey - notification key
896 -- agent - web agent URL root
897 -- NOTE
898 -- Detaillink called function Detail above.
899 -- This produces the version used by the mailer.
900 procedure DetailLink(
901 nid in number,
902 nkey in varchar2,
903 agent in varchar2)
904 is
905 begin
906 -- bug 7314545
907 null;
908 exception
909 when others then
910 wf_core.context('Wfa_Html', 'DetailLink', to_char(nid), nkey, agent);
911 raise;
912 end DetailLink;
913
914
915 -- SubmitForward
916 -- Submit notification forward
917 -- IN
918 -- h_nid - notification id
919 -- forwardee - new recipient field
920 -- display_forwardee - display name for the new recipient
921 -- comments - forwarding comments field
922 -- fmode - reassign mode can be:
923 -- transfer - transferring responsibility
924 -- delegate - delegate responsibility
925 -- submit - submit forward button
926 -- cancel - cancel forward button
927 -- nkey - access key for mailed html
928 procedure SubmitForward(
929 h_nid in varchar2,
930 forwardee in varchar2,
931 display_forwardee in varchar2,
932 comments in varchar2,
933 fmode in varchar2,
934 submit in varchar2,
935 cancel in varchar2,
936 nkey in varchar2)
937 is
938 begin
939 -- bug 7314545
940 null;
941 end SubmitForward;
942
943 -- SubmitResponse
944 -- Submit notification response
945 -- IN
946 -- h_nid - notification id
947 -- h_fnames - array of field names
948 -- h_fvalues - array of field values
949 -- h_fdocnames - array of documentnames - a throwaway value from form
950 -- h_counter - number of fields passed in fnames and fvalues
951 -- submit - submit response button
952 -- forward - forward button
953 -- nkey - access key for mailed html
954 procedure SubmitResponse(
955 h_nid in varchar2,
956 h_fnames in Name_Array,
957 h_fvalues in Value_Array,
958 h_fdocnames in Value_Array,
959 h_counter in varchar2,
960 submit in varchar2,
961 forward in varchar2,
962 nkey in varchar2)
963 as
964 begin
965 -- bug 7314545
966 null;
967 end SubmitResponse;
968
969 -- GotoURL
970 -- GotoURL let you open an url in a specify place. This is very useful
971 -- when you need to go from a child frame to the full browser window,
972 -- for instnace.
973 -- So far, this is the only way to break away from a child frame.
974 -- IN
975 -- url - Fully qualified universal resouce location
976 -- location - Where you want to open it. Samples of values are
977 -- _blank - unnamed window
978 -- _self - the current frame
979 -- _parent - the parent frame of the current one
980 -- _top - the full Web browser window
981 -- "myWin" - name of the new window
982 --
983 procedure GotoURL(
984 url in varchar2,
985 location in varchar2,
986 attributes in varchar2
987 )
988 is
989 begin
990 -- bug 7314545
991 null;
992 end GotoURL;
993
994 -- SubmitSelectedResponse
995 -- Submit selected notification response
996 -- IN
997 -- nids - notification ids
998 -- close - submit response button
999 -- forward - forward button
1000 -- showto - display the TO column
1001 -- nkey - access key for mailed html
1002 procedure SubmitSelectedResponse(
1003 nids in Name_Array,
1004 close in varchar2,
1005 forward in varchar2,
1006 showto in varchar2,
1007 nkey in varchar2)
1008 as
1009 begin
1010 null;
1011 end SubmitSelectedResponse;
1012
1013
1014 -- ForwardNids
1015 -- Forward for each notification ids
1016 -- Forward can be Delegating or Transferring
1017 -- Delegating is for notification only.
1018 -- Transferring is reassign the whole responsibility to other
1019 -- IN
1020 -- h_nids - hidden notification ids
1021 -- forwardee - forwardee role specified
1022 -- comments - comments included
1023 -- fmode - reassign mode can be:
1024 -- transfer - transferring responsibility
1025 -- delegate - delegate responsibility
1026 -- cancel - cancel button
1027 procedure ForwardNids(
1028 h_nids in Name_Array,
1029 forwardee in varchar2,
1030 display_forwardee in varchar2,
1031 comments in varchar2,
1032 fmode in varchar2,
1033 submit in varchar2,
1034 cancel in varchar2,
1035 nkey in varchar2)
1036 as
1037 username varchar2(320);
1038 x pls_integer;
1039 nid pls_integer;
1040 l_forwardee varchar2(320);
1041
1042 begin
1043 -- There is always a dummy nid passed in. We will handle it here.
1044 -- Make sure subsequent index start at 2 not 1.
1045 if (to_number(h_nids.count) = 1) then
1046 wf_core.raise('WFNTF_NO_SELECT');
1047 end if;
1048
1049 -- Fully resolve forwardee name
1050 l_forwardee := forwardee;
1051 wfa_html.validate_display_name (display_forwardee, l_forwardee);
1052
1053 -- Otherwise, for each notification, delegate or transfer
1054 for x in 2..h_nids.count loop
1055 -- Authenticate user
1056 nid := to_number(h_nids(x));
1057 username := Wfa_Html.Authenticate(nid, nkey);
1058
1059 -- Delegating to forwardee with comments
1060 if (fmode = 'DELEGATE') then
1061 if (comments is not null) then
1062 -- ### implement this in next release
1063 -- Wf_Notification.Forward(nid, upper(l_forwardee), comments, username);
1064 Wf_Notification.Forward(nid, upper(l_forwardee), comments);
1065 else
1066 -- ### implement this in next release
1067 -- Wf_Notification.Forward(nid, upper(l_forwardee), '', username);
1068 Wf_Notification.Forward(nid, upper(l_forwardee));
1069 end if;
1070 elsif (fmode = 'TRANSFER') then
1071 -- Transferring to fowardee with comments
1072
1073 if (comments is not null) then
1074 -- ### implement this in next release
1075 -- Wf_Notification.Transfer(nid, upper(l_forwardee), comments, username);
1076 Wf_Notification.Transfer(nid, upper(l_forwardee), comments);
1077 else
1078 -- ### implement this in next release
1079 -- Wf_Notification.Transfer(nid, upper(l_forwardee), '', username);
1080 Wf_Notification.Transfer(nid, upper(l_forwardee));
1081 end if;
1082 end if;
1083 end loop;
1084
1085 -- Back to the worklist
1086 <<worklist>>
1087 Wfa_Html.WorkList;
1088 return;
1089 exception
1090 when others then
1091 rollback;
1092 wfa_html.Error;
1093 return;
1094 end ForwardNids;
1095
1096 /*===========================================================================
1097 PROCEDURE NAME: create_help_function
1098
1099 DESCRIPTION:
1100 Create the java script function to support the Help
1101 Icon from the header
1102
1103 Note: The help file parameter must include the subdirectory under
1104 /OA_DOC/lang/ and the actual file name which will either be
1105 wf or wfnew.
1106 ie p_help_file = 'wf/notif16.htm'
1107 p_help_file = 'wfnew/wfnew48.htm'
1108 ============================================================================*/
1109 procedure create_help_function (
1110
1111 p_help_file IN VARCHAR2
1112
1113 ) IS
1114
1115 install_type VARCHAR2(80);
1116 l_help_target VARCHAR2(240) := NULL;
1117 l_lang VARCHAR2(2000);
1118 help_prefix VARCHAR2(2000);
1119
1120 BEGIN
1121
1122 BEGIN
1123
1124 /*
1125 ** Get the language environment variable
1126 ** for this user.
1127 */
1128 SELECT USERENV('LANG')
1129 INTO l_lang
1130 FROM DUAL;
1131
1132 EXCEPTION
1133 WHEN OTHERS THEN
1134 l_lang := 'US';
1135 END;
1136
1137 /*
1138 ** Check the installation type. If it is workflow standalone
1139 ** then use the file prefix method of getting to the help
1140 ** content. Otherwise use the fnd function method to get and
1141 ** display the help content.
1142 */
1143 install_type := wf_core.translate('WF_INSTALL');
1144
1145 if (install_type = 'STANDALONE') THEN
1146
1147 help_prefix := '/OA_DOC/';
1148
1149 htp.p('<!-- Copyright ' || '&' || '#169; 1997 Oracle Corporation, All rights reserved. -->');
1150 htp.p('<SCRIPT LANGUAGE="JavaScript">
1151 <!-- hide the script''s contents from feeble browsers');
1152
1153 htp.p('function help_window(){
1154 help_win = window.open('||''''||help_prefix||
1155 'US/' || p_help_file ||''''||
1156 ', "help_win","resizable=yes,scrollbars=yes,toolbar=yes,width=600,height=500");
1157 help_win = window.open('||''''||help_prefix||
1158 'US/' || p_help_file ||''''||
1159 ', "help_win","resizable=yes,scrollbars=yes,toolbar=yes,width=600,height=500")
1160 }
1161 ');
1162
1163 htp.p('<!-- done hiding from old browsers --></SCRIPT>');
1164
1165 htp.p('<NOSCRIPT>');
1166 htp.p(WF_CORE.Translate('WFA_NOSCRIPT'));
1167 htp.p('</NOSCRIPT>');
1168
1169 else
1170
1171 /*
1172 ** If you're going against apps then strip out everything
1173 ** except the target name
1174 */
1175 IF (INSTR(p_help_file, '?') > 0) THEN
1176
1177 l_help_target := substrb(p_help_file, INSTR(p_help_file, '?') + 1);
1178
1179 ELSE
1180
1181 l_help_target := p_help_file;
1182
1183 END IF;
1184
1185 wfa_sec.create_help_syntax (l_help_target, l_lang);
1186
1187 end if;
1188
1189 exception
1190 when others then
1191 Wf_Core.Context('wfa_html', 'create_help_function',
1192 p_help_file);
1193 wfa_html.Error;
1194
1195 END create_help_function;
1196
1197 /*===========================================================================
1198 FUNCTION NAME: conv_special_url_chars
1199
1200 DESCRIPTION:
1201 Convert all of the ASCII special characters that are
1202 disallowed as a part of a URL. The encoding requires
1203 that we convert the special characters to HEX for
1204 any characters in a URL string that is built
1205 manually outside a form get/post.
1206 This API now also converts multibyte characters
1207 into their HEX equivalent.
1208
1209 NOTE: This api allows double-encoding.
1210
1211 ============================================================================*/
1212 FUNCTION conv_special_url_chars (p_url_token IN VARCHAR2) RETURN VARCHAR2
1213 IS
1214 c_unreserved constant varchar2(72) :=
1215 '-_.!*''()~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1216 c_reserved constant varchar2(72) := '%">^{}<[]`|/#?&=$:;+';
1217 l_tmp varchar2(32767) := '';
1218 l_onechar varchar2(4);
1219 l_byte_len integer;
1220 i integer;
1221 l_str varchar2(48);
1222
1223 BEGIN
1224 if p_url_token is NULL then
1225 return NULL;
1226 end if;
1227 for i in 1 .. length(p_url_token) loop
1228 l_onechar := substr(p_url_token,i,1);
1229 --Extracting out each character to be replaced.
1230 if instr(c_unreserved, l_onechar) > 0 then
1231 --Check if it is part of the ASCII unreserved
1232 --excluded from encoding just append to the URL
1233 --string
1234 l_tmp := l_tmp || l_onechar;
1235
1236 elsif l_onechar = ' ' then
1237 --Space encoded as '%20'
1238 l_tmp := l_tmp || '%20';
1239
1240 elsif instr(c_reserved,l_onechar) >0 then
1241 --If it is any of the reserved characters in ascii
1242 --replace with equivalent HEX
1243 l_onechar := REPLACE(
1244 REPLACE(
1245 REPLACE(
1246 REPLACE(
1247 REPLACE(
1248 REPLACE(
1249 REPLACE(
1250 REPLACE(
1251 REPLACE(
1252 REPLACE(
1253 REPLACE(
1254 REPLACE(
1255 REPLACE(
1256 REPLACE(
1257 REPLACE(
1258 REPLACE(
1259 REPLACE(
1260 REPLACE(
1261 REPLACE(
1262 REPLACE(
1263 REPLACE(
1264 REPLACE(l_onechar,
1265 '%','%25'),
1266 ' ','%20'),
1267 '"','%22'),
1268 '>','%3E'),
1269 '^','%5E'),
1270 '{','%7B'),
1271 '}','%7D'),
1272 '<','%3C'),
1273 '[','%5B'),
1274 ']','%5D'),
1275 '`','%60'),
1276 '|','%7C'),
1277 '/','%2F'),
1278 '#','%23'),
1279 '?','%3F'),
1280 '&','%26'),
1281 '=','%3D'),
1282 '$','%24'),
1283 ':','%3A'),
1284 ';','%3B'),
1285 '+','%2B'),
1286 '''','%27');
1287 l_tmp := l_tmp || l_onechar;
1288 else
1289 --For multibyte
1290 -- 1. Obtain length for each character
1291 -- 2. ascii(l_char)decimal representation in the database
1292 -- character set
1293 -- 3. Change it to the format model :
1294 -- to_char(ascii(l_onechar),'FM0X')
1295 -- 4. Add to the already encoded string.
1296 -- characters
1297 l_byte_len := lengthb(l_onechar);
1298 if l_byte_len = 1 then
1299 l_tmp := l_tmp || '%' ||
1300 substr(to_char(ascii(l_onechar),'FM0X'),1,2);
1301 elsif l_byte_len = 2 then
1302 l_str := to_char(ascii(l_onechar),'FM0XXX');
1303 l_tmp := l_tmp
1304 || '%' || substr(l_str,1,2)
1305 || '%' || substr(l_str,3,2);
1306 elsif l_byte_len = 3 then
1307 l_str := to_char(ascii(l_onechar),'FM0XXXXX');
1308 l_tmp := l_tmp
1309 || '%' || substr(l_str,1,2)
1310 || '%' || substr(l_str,3,2)
1311 || '%' || substr(l_str,5,2);
1312 elsif l_byte_len = 4 then
1313 l_str := to_char(ascii(l_onechar),'FM0XXXXXXX');
1314 l_tmp := l_tmp
1315 || '%' || substr(l_str,1,2)
1316 || '%' || substr(l_str,3,2)
1317 || '%' || substr(l_str,5,2)
1318 || '%' || substr(l_str,7,2);
1319 else -- maximum precision
1320 wf_core.raise('WFENG_PRECESSION_EXCEED');
1321 end if;
1322 end if;
1323 end loop;
1324 return l_tmp;
1325 exception
1326 when others then
1327 Wf_Core.Context('wfa_html', 'conv_special_url_chars',
1328 p_url_token);
1329 wfa_html.Error;
1330 END conv_special_url_chars;
1331
1332 /*===========================================================================
1333 FUNCTION NAME: encode_url (PRIVATE)
1334
1335 DESCRIPTION:
1336 Convert all of the ASCII special characters that are
1337 disallowed as a part of a URL. The encoding requires
1338 that we convert the special characters to HEX for
1339 any characters in a URL string that is built
1340 manually outside a form get/post.
1341 This API now also converts multibyte characters
1342 into their HEX equivalent.
1343
1344 URL encoding was documented in RFC 1738.
1345 We have put some "unsafe" characters in the encode
1346 list for purpose of encoding them.
1347 We took "~" out from this list, because some downstream
1348 consumer (ICX) was looking for "~".
1349
1350 NOTE: This private api does not allow double-encoding.
1351 ============================================================================*/
1352 FUNCTION encode_url (p_url_token IN VARCHAR2) RETURN VARCHAR2
1353 IS
1354 c_noencode constant varchar2(72) :=
1355 '-_.!*''()~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1356 c_encode constant varchar2(72) := '">^{}<[]`|/#?&=$:;+';
1357 c_hex constant varchar2(72) := 'ABCDEFabcdef0123456789';
1358 l_tmp varchar2(32767);
1359 l_onechar varchar2(4);
1360 l_byte_len integer;
1361 i integer;
1362 l_str varchar2(48);
1363
1364 BEGIN
1365 if p_url_token is NULL then
1366 return NULL;
1367 end if;
1368 for i in 1 .. length(p_url_token) loop
1369 l_onechar := substr(p_url_token,i,1);
1370 --Extracting out each character to be replaced.
1371 if instr(c_noencode, l_onechar) > 0 then
1372 --If it is part of the ASCII excluded from encoding,
1373 --just append to the URL string
1374 l_tmp := l_tmp || l_onechar;
1375
1376 elsif l_onechar = ' ' then
1377 --Space encoded as '%20'
1378 l_tmp := l_tmp || '%20';
1379
1380 elsif l_onechar = '%' then
1381 --Do not reencode if it has already been encoded
1382 --Check next two characters to see if they belong to hex number
1383 if (instr(c_hex, substr(p_url_token,i+1,1)) > 0 and
1384 instr(c_hex, substr(p_url_token,i+2,1)) > 0) then
1385 l_tmp := l_tmp || '%';
1386 else
1387 l_tmp := l_tmp || '%25';
1388 end if;
1389
1390 elsif instr(c_encode,l_onechar) >0 then
1391 --If it is any of the to be encoded characters in ascii
1392 --replace with equivalent HEX
1393 l_onechar := REPLACE(
1394 REPLACE(
1395 REPLACE(
1396 REPLACE(
1397 REPLACE(
1398 REPLACE(
1399 REPLACE(
1400 REPLACE(
1401 REPLACE(
1402 REPLACE(
1403 REPLACE(
1404 REPLACE(
1405 REPLACE(
1406 REPLACE(
1407 REPLACE(
1408 REPLACE(
1409 REPLACE(
1410 REPLACE(
1411 REPLACE(
1412 REPLACE(l_onechar,
1413 '"','%22'),
1414 '>','%3E'),
1415 '^','%5E'),
1416 '{','%7B'),
1417 '}','%7D'),
1418 '<','%3C'),
1419 '[','%5B'),
1420 ']','%5D'),
1421 '`','%60'),
1422 '|','%7C'),
1423 '/','%2F'),
1424 '#','%23'),
1425 '?','%3F'),
1426 '&','%26'),
1427 '=','%3D'),
1428 '$','%24'),
1429 ':','%3A'),
1430 ';','%3B'),
1431 '+','%2B'),
1432 '''','%27');
1433 l_tmp := l_tmp || l_onechar;
1434 else
1435 --For multibyte
1436 -- 1. Obtain length for each character
1437 -- 2. ascii(l_char)decimal representation in the database
1438 -- character set
1439 -- 3. Change it to the format model :
1440 -- to_char(ascii(l_onechar),'FM0X')
1441 -- 4. Add to the already encoded string.
1442 -- characters
1443 l_byte_len := lengthb(l_onechar);
1444 if l_byte_len = 1 then
1445 l_tmp := l_tmp || '%' ||
1446 substr(to_char(ascii(l_onechar),'FM0X'),1,2);
1447 elsif l_byte_len = 2 then
1448 l_str := to_char(ascii(l_onechar),'FM0XXX');
1449 l_tmp := l_tmp
1450 || '%' || substr(l_str,1,2)
1451 || '%' || substr(l_str,3,2);
1452 elsif l_byte_len = 3 then
1453 l_str := to_char(ascii(l_onechar),'FM0XXXXX');
1454 l_tmp := l_tmp
1455 || '%' || substr(l_str,1,2)
1456 || '%' || substr(l_str,3,2)
1457 || '%' || substr(l_str,5,2);
1458 elsif l_byte_len = 4 then
1459 l_str := to_char(ascii(l_onechar),'FM0XXXXXXX');
1460 l_tmp := l_tmp
1461 || '%' || substr(l_str,1,2)
1462 || '%' || substr(l_str,3,2)
1463 || '%' || substr(l_str,5,2)
1464 || '%' || substr(l_str,7,2);
1465 else -- maximum precision
1466 wf_core.raise('WFENG_PRECESSION_EXCEED');
1467 end if;
1468 end if;
1469 end loop;
1470 return l_tmp;
1471 exception
1472 when others then
1473 Wf_Core.Context('wfa_html', 'encode_url',
1474 p_url_token);
1475 wfa_html.Error;
1476 END encode_url;
1477
1478 --
1479 -- User_LOV
1480 -- Create the data for the User List of Values
1481 -- NOTE: This is not used by APPS. Otherwise, we will have performance
1482 -- problem with this query against wf_roles.
1483 --
1484 procedure User_LOV (p_titles_only IN VARCHAR2,
1485 p_find_criteria IN VARCHAR2)
1486
1487 IS
1488 BEGIN
1489 -- bug 7314545
1490 null;
1491 end User_Lov;
1492
1493 procedure logout is
1494 begin
1495 -- bug 7314545
1496 null;
1497 end logout;
1498
1499 procedure Home(message in varchar2)
1500 is
1501 begin
1502 -- bug 7314545
1503 null;
1504 end home;
1505
1506 procedure Header
1507 is
1508 begin
1509 -- bug 7314545
1510 null;
1511 end;
1512
1513
1514 procedure home_float
1515 is
1516 begin
1517 -- bug 7314545
1518 null;
1519 end home_float;
1520
1521 -- Homemenu
1522 -- Prints the menu for the home page.
1523 -- May also be called direct to print a regular page.
1524
1525 procedure Homemenu(message in varchar2,
1526 origin in varchar2)
1527 is
1528 begin
1529 -- bug 7314545
1530 null;
1531 end Homemenu;
1532
1533 procedure create_reg_button (
1534 when_pressed_url IN VARCHAR2,
1535 onmouseover IN VARCHAR2,
1536 icon_top IN VARCHAR2,
1537 icon_name IN VARCHAR2,
1538 show_text IN VARCHAR2)
1539 IS
1540 BEGIN
1541 -- bug 7314545
1542 null;
1543 end create_reg_button;
1544
1545 -- show_plsql_doc
1546 -- Show the content of a plsql document in a browser window
1547 -- Called from the related documents function
1548
1549 procedure show_plsql_doc (
1550 nid in number,
1551 aname in varchar2,
1552 nkey in varchar2)
1553 is
1554
1555 username varchar2(320);
1556
1557 clob_loc clob;
1558 blob_loc blob;
1559 clob_id number;
1560 clob_chunk number := 0;
1561 doctext varchar2(32000);
1562 end_of_text boolean :=FALSE;
1563 attr_name varchar2(30);
1564
1565 slash pls_integer;
1566 wfsession varchar2(240);
1567
1568 doctype varchar2(1000);
1569 lobsize number;
1570 amount number;
1571
1572 l_enpos pls_integer;
1573 l_copos pls_integer;
1574
1575 l_encoding varchar2(100);
1576 l_filename varchar2(255);
1577 l_extension varchar2(50);
1578 l_mime_type varchar2(255);
1579
1580 begin
1581
1582 -- Verify if user is admin or can access this notification
1583 username := wfa_html.authenticate(nid,nkey);
1584
1585 username := upper(username);
1586
1587 -- note that GetAttrDoc will not translate for PLSQLCLOB
1588 doctext := wf_notification.getattrdoc(nid, aname,wf_notification.doc_html);
1589
1590 -- if the attribute wasn't translated then try to translate for plsqlclobs.
1591 if doctext = '&'||aname then
1592 dbms_lob.createTemporary(clob_loc, false, dbms_lob.call);
1593 Wf_Notification.GetAttrCLOB(nid, aname, wf_notification.doc_html,
1594 clob_loc, doctype, attr_name);
1595 if (doctype is not null) then
1596 Wf_Mail_Util.ParseContentType(doctype, l_mime_type, l_filename, l_extension, l_encoding);
1597 end if;
1598 -- We have the document. Now determine the output method. HTML documents can be output as
1599 -- they are. Binary documents can only be downloaded
1600 if l_mime_type in (wf_notification.doc_text, wf_notification.doc_html) then
1601 -- HTML or text document.
1602 htp.htmlOpen;
1603 htp.headOpen;
1604 htp.p('<BASE TARGET="_top">');
1605 htp.title(wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT'));
1606 wfa_html.create_help_function('wfnew/wfnew52.htm#nrr');
1607 htp.headClose;
1608 wfa_sec.Header(FALSE, '',wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT'),
1609 TRUE);
1610 htp.br;
1611
1612 lobsize := dbms_lob.getlength(clob_loc);
1613 amount := 32000;
1614 wf_notification.clob_chunk := 0;
1615 while not (end_of_text) loop
1616 wf_notification.readattrclob(nid, aname, doctext, end_of_text);
1617 htp.prn(doctext);
1618 end loop;
1619 wfa_sec.Footer;
1620 htp.htmlClose;
1621 elsif attr_name is not null then
1622 -- BINARY Document
1623 if (l_encoding is not null) then
1624 -- Decode base64 encoded content
1625 if (upper(trim(l_encoding)) = 'BASE64') then
1626 dbms_lob.createTemporary(blob_loc, FALSE, dbms_lob.call);
1627
1628 wf_mail_util.decodeBLOB(clob_loc, blob_loc);
1629 -- owa_util.mime_header(doctype, FALSE);
1630 -- Write appropriate headers before downloading the document
1631 if (l_filename is null or l_filename = '') then
1632 l_filename := aname || '.' || l_extension;
1633 end if;
1634 htp.p('Content-type: '||l_mime_type);
1635 htp.p('Content-Disposition: attachment; filename="'||l_filename||'"');
1636 htp.p('Content-length: ' || dbms_lob.getlength(blob_loc));
1637 htp.p('');
1638 -- owa_util.http_header_close;
1639
1640 wpg_docload.download_file(blob_loc);
1641 dbms_lob.freeTemporary(blob_loc);
1642 end if;
1643 else
1644 -- This provides limited binary document support. It assumes that the document in
1645 -- stored as raw in varchar.
1646 owa_util.mime_header(l_mime_type, TRUE);
1647 lobsize := dbms_lob.getlength(clob_loc);
1648 amount := 32000;
1649 wf_notification.clob_chunk := 0;
1650 while not (end_of_text) loop
1651 wf_notification.readattrclob(nid, aname, doctext, end_of_text);
1652 htp.p(doctext);
1653 end loop;
1654 end if;
1655 else
1656 -- attr_name is null try for a PLSQLBLOB document
1657 dbms_lob.createTemporary(blob_loc, false, dbms_lob.call);
1658 Wf_Notification.GetAttrBLOB(nid, aname, wf_notification.doc_html,
1659 blob_loc, doctype, attr_name);
1660 if (doctype is not null) then
1661 Wf_Mail_Util.ParseContentType(doctype, l_mime_type, l_filename, l_extension, l_encoding);
1662 end if;
1663 if (l_filename is null or l_filename = '') then
1664 l_filename := aname || '.' || l_extension;
1665 end if;
1666 -- owa_util.mime_header(doctype, FALSE);
1667 htp.p('Content-type: '||l_mime_type);
1668 htp.p('Content-Disposition: attachment; filename="'||l_filename||'"');
1669 htp.p('Content-length: ' || dbms_lob.getlength(blob_loc));
1670 htp.p('');
1671 -- owa_util.http_header_close;
1672
1673 wpg_docload.download_file(blob_loc);
1674 dbms_lob.freeTemporary(blob_loc);
1675 end if;
1676
1677 else
1678 -- Set page title
1679 htp.htmlOpen;
1680 htp.headOpen;
1681 htp.title(wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT'));
1682 wfa_html.create_help_function('wfnew/wfnew52.htm#nrr');
1683 htp.headClose;
1684 wfa_sec.Header(FALSE, '',wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT'),
1685 TRUE);
1686 htp.br;
1687
1688 htp.p (doctext);
1689
1690 wfa_sec.Footer;
1691 htp.htmlClose;
1692 end if;
1693
1694 exception
1695 when others then
1696 wf_core.context('Wfa_Html','show_plsql_doc',wf_core.substitutespecialchars(nid),
1697 wf_core.substitutespecialchars(aname));
1698 wfa_html.Error;
1699 end show_plsql_doc;
1700
1701 -- base_url
1702 -- Get the base url for the current browser where you have launched the
1703 -- login for Workflow
1704 function base_url (get_from_resources BOOLEAN)
1705 return varchar2 IS
1706
1707 l_base_url VARCHAR2(2000) := NULL;
1708
1709 BEGIN
1710
1711 BEGIN
1712
1713 IF (get_from_resources = FALSE) THEN
1714
1715 -- Need to strip off trailing / to match wf_web_agent format
1716 l_base_url := SUBSTR(RTRIM(owa_util.get_owa_service_path), 1,
1717 LENGTH(RTRIM(owa_util.get_owa_service_path)) - 1);
1718
1719 ELSE
1720
1721 l_base_url := wf_core.translate ('WF_WEB_AGENT');
1722
1723 END IF;
1724
1725 EXCEPTION
1726 WHEN OTHERS THEN
1727
1728 l_base_url := wf_core.translate ('WF_WEB_AGENT');
1729
1730 END;
1731
1732 return (l_base_url);
1733
1734 exception
1735 when others then
1736 wf_core.context('Wfa_Html','base_url');
1737 wfa_html.Error;
1738 end base_url;
1739
1740 --
1741 -- wf_user_val
1742 -- Create the lov content for our user lov. This function
1743 -- is called by the generic lov function
1744 -- IN
1745 -- RETURNS
1746 --
1747 procedure wf_user_val (
1748 p_mode in varchar2,
1749 p_lov_name in varchar2,
1750 p_start_row in number,
1751 p_max_rows in number,
1752 p_hidden_value in out nocopy varchar2,
1753 p_display_value in out nocopy varchar2,
1754 p_result out nocopy number)
1755
1756
1757 IS
1758
1759 CURSOR c_user_lov (c_find_criteria IN VARCHAR2) IS
1760 SELECT
1761 name,
1762 display_name
1763 FROM wf_role_lov_vl
1764 where status <> 'INACTIVE'
1765 and (UPPER(display_name) LIKE UPPER(c_find_criteria)||'%')
1766 order by display_name;
1767
1768 -- Added additional where condition "status <> 'INACTIVE' so only ACTIVE
1769 -- roles display
1770
1771 -- CURSOR c_user_display_value (c_name IN VARCHAR2) IS
1772 -- select name, display_name
1773 -- from wf_roles
1774 -- where name = c_name;
1775
1776 ii NUMBER := 0;
1777 nn NUMBER := 0;
1778 l_total_rows NUMBER := 0;
1779 l_id NUMBER;
1780 l_name VARCHAR2 (320); -- enlarged from 30 to match db definition
1781 l_display_name VARCHAR2 (360); -- enlarged from 80 to match db definition
1782 l_result NUMBER := 1; -- This is the return value for each mode
1783
1784 colon NUMBER;
1785
1786 role_info_tbl wf_directory.wf_local_roles_tbl_type;
1787
1788 BEGIN
1789
1790 if (p_mode = 'LOV') then
1791
1792 /*
1793 ** Need to get a count on the number of rows that will meet the
1794 ** criteria before actually executing the fetch to show the user
1795 ** how many matches are available.
1796 */
1797 select count(*)
1798 into l_total_rows
1799 FROM wf_role_lov_vl
1800 where status <> 'INACTIVE'
1801 and (UPPER(display_name) LIKE UPPER(p_display_value)||'%');
1802
1803 wf_lov.g_define_rec.total_rows := l_total_rows;
1804
1805 wf_lov.g_define_rec.add_attr1_title := wf_core.translate ('WFITD_INTERNAL_NAME');
1806
1807 open c_user_lov (p_display_value);
1808
1809 LOOP
1810
1811 FETCH c_user_lov INTO l_name, l_display_name;
1812
1813 EXIT WHEN c_user_lov%NOTFOUND OR nn >= p_max_rows;
1814
1815 ii := ii + 1;
1816
1817 IF (ii >= p_start_row) THEN
1818
1819 nn := nn + 1;
1820
1821 wf_lov.g_value_tbl(nn).hidden_key := l_name;
1822 wf_lov.g_value_tbl(nn).display_value := l_display_name;
1823 wf_lov.g_value_tbl(nn).add_attr1_value := l_name;
1824
1825 END IF;
1826
1827 END LOOP;
1828
1829 l_result := 1;
1830
1831 elsif (p_mode = 'GET_DISPLAY_VAL') THEN
1832
1833 Wf_Directory.GetRoleInfo2(p_hidden_value,role_info_tbl);
1834 l_name := role_info_tbl(1).name;
1835 l_display_name := role_info_tbl(1).display_name;
1836 p_display_value:= l_name;
1837
1838 l_result := 1;
1839
1840 elsif (p_mode = 'VALIDATE') THEN
1841
1842 /*
1843 ** If mode = VALIDATE then see how many rows match the criteria
1844 ** If its 0 then thats not good. Raise an error and tell them to use LOV
1845 ** If its 1 then thats great.
1846 ** If its more than 1 then check to see if they used the LOV to select
1847 ** the value
1848 */
1849 open c_user_lov (p_display_value);
1850
1851 LOOP
1852
1853 FETCH c_user_lov INTO l_name, l_display_name;
1854
1855 EXIT WHEN c_user_lov%NOTFOUND OR ii = 2;
1856
1857 ii := ii + 1;
1858
1859 p_hidden_value := l_name;
1860
1861 END LOOP;
1862
1863 /*
1864 ** If ii=0 then no rows were found and you have an error in the value
1865 ** entered so present a no rows found and use the lov icon to select
1866 ** value
1867 ** If ii=1 then one row is found then you've got the right value
1868 ** If ii=2 then more than one row was found so check to see if the display
1869 ** value taht was selected is not unique in the LOV (Person Name) and
1870 ** that the LOV was used so the Hidden value has been set to a unique
1871 ** value. If it comes up with more than 1 in this case then present
1872 ** the please use lov icon to select value.
1873 */
1874 if (ii = 2) then
1875
1876 -- copy logic from wf_directory.getroleinfo2
1877 colon := instr(p_display_value,':');
1878 if (colon = 0) then
1879 select count(*)
1880 into ii
1881 from WF_ROLES
1882 where NAME = p_display_value
1883 and ORIG_SYSTEM not in ('HZ_PARTY','POS','ENG_LIST','AMV_CHN',
1884 'HZ_GROUP','CUST_CONT');
1885 else
1886 select count(*)
1887 into ii
1888 from WF_ROLES
1889 where NAME = p_display_value
1890 and ORIG_SYSTEM = substr(p_display_value, 1, colon-1)
1891 and ORIG_SYSTEM_ID = substr(p_display_value, colon+1);
1892 end if;
1893
1894 END IF;
1895
1896 l_result := ii;
1897
1898 end if;
1899
1900 p_result := l_result;
1901
1902 exception
1903 when others then
1904 rollback;
1905 wf_core.context('Wfa_Html', 'wf_user_val');
1906 raise;
1907 end wf_user_val;
1908
1909
1910 function replace_onMouseOver_quotes(p_string in varchar2) return varchar2 is
1911
1912 temp_string varchar2(2000);
1913 c_browser varchar2(400) := owa_util.get_cgi_env('HTTP_USER_AGENT');
1914
1915 begin
1916
1917 -- replace single quotes
1918 temp_string := replace(p_string,'''','\''');
1919
1920 -- replace double quotes
1921 if (instr(c_browser, 'MSIE') <> 0) then
1922 temp_string := replace(temp_string,'"','\''');
1923 else
1924 temp_string := replace(temp_string,'"','`"');
1925 end if;
1926
1927 -- check for double escapes
1928 temp_string := replace(temp_string,'\\','\');
1929
1930 return temp_string;
1931
1932 end replace_onMouseOver_quotes;
1933
1934 procedure validate_display_name (
1935 p_display_name in varchar2,
1936 p_user_name in out nocopy varchar2) IS
1937
1938 l_colon NUMBER := 0;
1939 l_names_count NUMBER := 0;
1940 l_name VARCHAR2(320);
1941 l_upper_name VARCHAR2(360);
1942 l_orig_system_id NUMBER;
1943 l_get_role BOOLEAN := TRUE;
1944
1945 role_info_tbl wf_directory.wf_local_roles_tbl_type;
1946
1947 BEGIN
1948
1949 /*
1950 ** Make sure to blank out the internal name if the user originally
1951 ** used the LOV to select the name and then blanked out the display
1952 ** name then make sure here to blank out the insternal name and return
1953 */
1954 if (p_display_name is null) then
1955
1956 p_user_name := NULL;
1957 return;
1958
1959 end if;
1960
1961 /*
1962 ** Bug# 2236250 validating the display name to contain a valid number
1963 ** after the colon to be used as a internal name for the role
1964 */
1965 l_colon := instr(p_display_name, ':');
1966 if (l_colon > 0) then
1967 begin
1968 l_orig_system_id := to_number(substr(p_display_name, l_colon+1));
1969 exception
1970 when invalid_number then
1971 l_get_role := FALSE;
1972 when others then
1973 raise;
1974 end;
1975 l_colon := 0;
1976 end if;
1977
1978 /*
1979 ** First look first for internal name to see if you find a match. If
1980 ** there are duplicate internal names that match the criteria then
1981 ** there is a problem with directory services but what can you do. Go
1982 ** ahead and pick the first name so you return something
1983 **
1984 ** Bug# 2236250 calling Wf_Directory.GetRoleInfo2 only if the value
1985 ** after ':' is numeric.
1986 */
1987 if (l_get_role) then
1988 l_upper_name := upper(p_display_name);
1989 Wf_Directory.GetRoleInfo2(l_upper_name,role_info_tbl);
1990 l_name := role_info_tbl(1).name;
1991 end if;
1992
1993 /*
1994 ** If you found a match on internal name then set the p_user_name
1995 ** accordingly.
1996 */
1997 if (l_name IS NOT NULL) then
1998
1999 p_user_name := l_name;
2000
2001 /*
2002 ** If there was no match on internal name then check for a display
2003 ** name
2004 */
2005 else
2006
2007 /*
2008 ** Check out how many names match the display name
2009 */
2010 select count(1)
2011 into l_names_count
2012 from wf_role_lov_vl
2013 where display_name = p_display_name;
2014
2015 /*
2016 ** If there are no matches for the display name then raise an error
2017 */
2018 if (l_names_count = 0) then
2019
2020 -- Not displayed or internal role name, error
2021 wf_core.token('ROLE', p_display_name);
2022 wf_core.raise('WFNTF_ROLE');
2023
2024 /*
2025 ** If there is just one match then get the internal name
2026 ** and assign it.
2027 */
2028 elsif (l_names_count = 1) then
2029
2030 select name
2031 into l_name
2032 from wf_role_lov_vl
2033 where display_name = p_display_name;
2034
2035 p_user_name := l_name;
2036
2037 /*
2038 ** If there is more than one match then see if the user
2039 ** used the lov to select the name in which case the combination
2040 ** of the display name and the user name should be unique
2041 */
2042 else
2043
2044 -- copy logic from wf_directory.getroleinfo2
2045 l_colon := instr(p_user_name,':');
2046
2047 if (l_colon = 0) then
2048 select count(1)
2049 into l_names_count
2050 from WF_ROLES
2051 where NAME = p_user_name
2052 and ORIG_SYSTEM not in ('HZ_PARTY','POS','ENG_LIST','AMV_CHN',
2053 'HZ_GROUP','CUST_CONT')
2054 and DISPLAY_NAME = p_display_name;
2055 else
2056 /*
2057 ** Bug# 2236250 validate if the value after ':' is number
2058 ** before using it in the query
2059 */
2060 begin
2061 l_orig_system_id := to_number(substr(p_user_name, l_colon+1));
2062 exception
2063 when invalid_number then
2064 wf_core.raise('WFNTF_ORIGSYSTEMID');
2065 when others then
2066 raise;
2067 end;
2068 select count(1)
2069 into l_names_count
2070 from WF_ROLES
2071 where NAME = p_user_name
2072 and ORIG_SYSTEM = substr(p_user_name, 1, l_colon-1)
2073 and ORIG_SYSTEM_ID = l_orig_system_id
2074 and DISPLAY_NAME = p_display_name;
2075 end if;
2076
2077 if (l_names_count <> 1) then
2078 wf_core.token('ROLE', p_display_name);
2079 wf_core.raise('WFNTF_UNIQUE_ROLE');
2080 end if;
2081
2082 end if;
2083
2084 end if;
2085
2086 exception
2087 when others then
2088 wf_core.context('Wfa_Html', 'validate_display_name', p_display_name,
2089 p_user_name);
2090 raise;
2091 end validate_display_name;
2092
2093 -- LongDesc
2094 -- Displays an html page with the token message. This is called from
2095 -- frames for the LONGDESC attribute.
2096 procedure LongDesc (p_token in varchar2)
2097 as
2098 BEGIN
2099 htp.htmlOpen;
2100 htp.headOpen;
2101 htp.title(wf_core.translate('LONG_DESC'));
2102 htp.headClose;
2103
2104 begin
2105 wfa_sec.Header(background_only=>TRUE);
2106 exception
2107 when others then
2108 htp.bodyOpen;
2109 end;
2110
2111 htp.p(WF_CORE.Translate(UPPER(p_token)));
2112
2113 wfa_sec.Footer;
2114 htp.htmlClose;
2115
2116 END LongDesc;
2117
2118 end WFA_HTML;