Unit 15.2. The Web Toolkit and Cookies

Three Cookie Actions

As a Web developer, there are three main actions you need to know in order to work with cookies; in fact, you will probably only use the first two:

  1. send— Send a cookie, or reset the value of an existing cookie

  2. get— Get, or read, the value of an existing cookie

  3. delete— Delete an expired cookie by setting its expiration date to the past. (This option is not often done and may not be handled as expected by the browser.)

OWA_COOKIE Package

Oracle provides a package, OWA_COOKIE, with procedures that allow you to perform each of these actions (Table 15.2). Other elements in the OWA_COOKIE package, such as the OWA_COOKIE type, provide additional built-in support for cookies.

HTTP Header

Cookies are sent (and removed) in the HTTP header.

To send and remove cookies, use the following syntax to open and then later close this HTTP header:

1.
OWA_UTIL.mime_header(bclose_header=>FALSE);

2.
Use OWA_COOKIE.send or OWA_COOKIE.remove here

3.
OWA_UTIL.http_header_close;

Table 15.2. OWA_COOKIE Procedures
Procedure Description
OWA_COOKIE.send( name, value, expires, path, domain, secure) OWA_COOKIE.send(‘USER_TYPE’,’Student’, NULL,’/’,NULL,NULL);

Name is the name you give your cookie, which you use when you are referring to the cookie later.

Value is a text string you set for the value of the cookie.

Expires is an Oracle DATE type expiration date for the cookie. This is a date in Oracle DATE format, not seconds as in the previous UNIX example. If expires is null, then the expiration is the end of the “current session,” i.e., when the user closes the browser window. Cookies that only last for the length of the session are sometimes referred to as “session cookies”—they are stored in the browser temporarily and are deleted when the browser is closed. These session cookies are not stored on the file system.

Path is used to specify a path that the cookies are valid for on your server. Specify / so that any branch of your “root” URL directory tree can get the cookie. In other words, you would indicate that requests for resources in other paths off your main site should also be sent the cookie. If you have several directories in your site, such as products.thumbtackworld.com/news and products.thumbtackworld.com/contact _us, specify / to allow the browser to send the cookie with requests for either page. By default, the path is the same directory as the current document.

Domain is used similarly to specify a domain that a cookie is valid for on the server. By default, the domain is the current domain, so you can specify NULL. If you have several machines in your domain, such as orders.thumbtackworld. com and products.thumbtackworld.com, you can specify a domain of .thumbtackworld.com to encompass both domains. You cannot choose a different domain, however.

Secure means the cookie can only be passed over an SSL (Secure Socket Layer) connection. You can only send cookies from within the HTTP header. Use this procedure between OWA_UTIL.mime_header and OWA_UTIL.http_header_close.
OWA_COOKIE.cookie Record type for a cookie. A PL/SQL variable declared with a type of OWA_COOKIE.cookie holds the results of a call to the procedure, OWA_COOKIE.get.

Example:

DECLARE

v_cookie OWA_COOKIE.cookie;
OWA_COOKIE.cookie (cont.) BEGIN

v_cookie := OWA_COOKIE.get(‘COUNTER’);

END;

There are two additional characteristics of a variable declared with the datatype OWA_COOKIE.cookie:

NUM_VALS: returns the number of values stored in the array.

VALS(n): returns the nth value stored in the array. Since the HTTP specification allows multiple values for the same cookie name, the cookie value must be retrieved using this notation. The OWA_COOKIE data type is a PL/SQL record.
OWA_COOKIE.vc_arr Array to hold multiple values of type VARCHAR2(4096). It is provided as a datatype to use when declaring variables to hold results of retrieving all cookies.
OWA_COOKIE.get( name) Gets a cookie with the specified name.

The result of this goes into a variable of type OWA_COOKIE.COOKIE.

Examples:

v_cookie := OWA_COOKIE.GET(‘LOGIN_NAME’);

Check that a cookie was found for the v_cookie variable by using num_vals:

IF (v_cookie.Num_Vals != 0) THEN ...

You cannot refer to the value of v_cookie directly. Instead use Vals(1):

v_cookie.Vals(1)

Since the HTTP specification allows multiple values for the same cookie name, the cookie value must be retrieved using this notation. The OWA_COOKIE data type is a PL/SQL record.
OWA_COOKIE.get_all() Retrieves all cookies that the server has access to in the order they were sent by the browser.
OWA_COOKIE.remove( name, value, path) Example:

OWA_COOKIE.REMOVE(‘USER_ID’,

v_cookie_user_type.vals(1));

Name is the name of the cookie you want to remove.

Value is the value for the cookie.

Path is optional.

You can only remove cookies from within the HTTP header. Use this procedure between OWA_UTIL.mime_header and OWA_UTIL.http_header_close.

FOR EXAMPLE

							[procedure text goes here - no HTML generated] 
OWA_UTIL.mime_header(bclose_header=>FALSE); 
OWA_COOKIE.send('SESSION_ID', 572, sysdate+365); 
OWA_UTIL.http_header_close; 
  [generate any HTML here, after closing http header]
						

The HTTP header must be opened and closed before any htp procedures or functions are executed; that is, before any HTML is generated by the PL/SQL procedure. If not, then the cookie will not be sent/removed.



The OWA_UTIL.mime_header procedure actually takes several parameters (Table 15.3):

OWA_UTIL.mime_header(ccontent_type, bclose_header, ccharset); 

If you just want to read or “get” the value of a cookie, you do not need to worry about the HTTP header. It is not necessary to put the OWA_COOKIE.get procedure inside of an HTTP header.

Cookie Recipes

The best way to manage cookies is to write small procedures and functions that work with cookies. Whenever possible, create modular code that can be reused.

The next sections contain short procedures and functions to set a cookie, read a cookie value, read all cookie values, and check for a cookie. Once these are created, you can use these procedures and functions as needed throughout your site.

Table 15.3. OWA_UTIL.mime_header parameters
Parameter Default Value Description
ccontent_type ‘text/html’ The MIME type for the document being sent. Has a default value of ‘text/html,’ which is fine.
bclose_header TRUE A Boolean value. TRUE means the header will be closed immediately. When you specify FALSE, the HTTP header remains open until you explicitly close it with OWA_UTIL.http_header_close. Close the HTTP after your cookie send/remove commands.
ccharset NULL Character set. Optional.

Set a Cookie: OWA_COOKIE.SEND

The following code sets a cookie for whatever name and value are passed in. The expiration date is optional. If it is supplied, the cookie will be set as a persistent cookie by the browser, with the expiration date supplied. If no expiration date is supplied, then the default value of NULL will be used, making it a session-level cookie. Session-level cookies cease to exist when the browser is closed.

FOR EXAMPLE

CREATE OR REPLACE PROCEDURE set_cookie 
     (p_cookie_name  IN VARCHAR2, 
      p_cookie_value IN VARCHAR2, 
      p_expires      IN DATE DEFAULT NULL) 
 IS 
BEGIN 
  OWA_UTIL.mime_header(bclose_header=>FALSE); 
  OWA_COOKIE.SEND(p_cookie_name, 
                  p_cookie_value, 
                  p_expires); 
  OWA_UTIL.http_header_close; 
END; 

Now any time that you need to set a cookie, call this procedure from PL/SQL— but only call it before any HTML has been generated by your PL/SQL procedure.

set_cookie('SESSION_ID','572'), 

To set a persistent cookie, supply an expiration date. The following call sets the cookie to expire in 5 days:

set_cookie('SESSION_ID','572',sysdate+5); 

Change a Cookie Value: OWA_COOKIE.SEND

To change a cookie value, use the same code that you would use to set the cookie. The name you supply should be the name of the cookie you want to change. Provide this name and the new value.

A cookie value can only be set from within the HTTP header, even if you are changing the value of an existing cookie. Again, the HTTP header must be opened and closed before any HTML is generated.



Read a Cookie Value: OWA_COOKIE.GET

The next function retrieves the value of a cookie with the name passed in. If no values are found, then the function returns a NULL value.

In the example below, note that a variable v_cookie is declared. This declaration is necessary because OWA_COOKIE.get is used to retrieve cookie values, and a container must exist to hold these returned values. The resulting cookie information must be stored in a variable of type OWA_COOKIE.cookie.

The OWA_COOKIE.cookie datatype is an array datatype. Any variable of type OWA_COOKIE.cookie has three characteristics.

NAME: The name of the cookie in the array.

NUM_VALS: The number of values stored in the array.

VALS(n): The nth value stored in the array. Unlike JavaScript arrays, this array starts with 1.

The syntax for these is demonstrated in the get_cookie function, below. This function is reusable. It has an IN parameter of a cookie name. The function checks for the existence of a cookie with the name that is passed in. If a cookie exists with that name, the procedure returns the cookie value. Otherwise, it returns a NULL value.

FOR EXAMPLE

CREATE OR REPLACE FUNCTION get_cookie 
   (p_cookie_name IN VARCHAR2) 
 RETURN VARCHAR2 
 IS 
    v_cookie     OWA_COOKIE.cookie; 
 BEGIN 
   v_cookie := OWA_COOKIE.GET(p_cookie_name); 
   IF v_cookie.num_vals != 0 THEN 
       RETURN v_cookie.vals(1); 
   ELSE 
       RETURN NULL; 
   END IF; 
END; 

Read All Cookie Values: OWA_COOKIE.GET_ALL

The OWA_COOKIE.get_all function retrieves all cookies. It has three out parameters. Two of them are arrays to hold the names and values of the cookies, since more than one cookie may be returned:

  • NAMES: The name of each cookie in the array.

  • VALS: The values of each cookie stored in the array.

  • NUM_VALS: The total number of values stored in the array. This is an integer, not an array.

The syntax for using these parameters is demonstrated in the get_all_cookies procedure, below. It does not have an IN parameter of a cookie name, because it is retrieving all cookies, not a specific one. Arrays of type OWA_COOKIE.vc_arr are declared to hold the names and values of the cookies.

This procedure paints all cookie names and values to the screen, if any are found. Note that the step where cookie values are displayed to the screen is not typical cookie processing; normally, users would not see cookie values on the screen. Instead, cookie values would be used for other processing.

FOR EXAMPLE

CREATE OR REPLACE PROCEDURE get_all_cookies 
 IS 
    v_cookie_names  OWA_COOKIE.vc_arr; 
    v_cookie_values OWA_COOKIE.vc_arr; 
    v_cookie_count  INTEGER; 
 BEGIN 
   OWA_COOKIE.get_all(v_cookie_names, 
                      v_cookie_values, 
                      v_cookie_count); 
   htp.p('<HTML><BODY>'), 
   FOR num IN 1..v_cookie_count LOOP 
      htp.p('Cookie #'||num||': Name='|| 
             v_cookie_names(num)||', Value='|| 
             v_cookie_values(num)||'<BR>'), 
   END LOOP; 
   htp.p('</BODY></HTML>'), 
   EXCEPTION 
      WHEN OTHERS THEN 
      htp.p('Error in get_all_cookies: '||SQLERRM); 
END; 

Check Whether a Cookie Exists

Sometimes it is enough to know whether a cookie exists or not, without retrieving its value. The following function checks for the existence of a cookie with the name passed in. The function returns a TRUE value if cookie values are found. It returns FALSE if there are no values stored for the cookie.

FOR EXAMPLE

CREATE OR REPLACE FUNCTION cookie_exists 
    (p_cookie_name IN VARCHAR2) 
 RETURN BOOLEAN 
 IS 
   v_cookie OWA_COOKIE.COOKIE; 
BEGIN 
   v_cookie := OWA_COOKIE.GET(p_cookie_name); 
   IF v_cookie.num_vals != 0 THEN 
       RETURN TRUE; 
   ELSE 
       RETURN FALSE; 
   END IF; 
END; 

Unit 15.2 Exercises

15.2.1. Compile the Procedures
Q1: Compile the procedures/functions from this chapter:
  • set_cookie

  • get_cookie

  • get_all_cookies

  • cookie_exists

15.2.2. Collect Information for a Cookie
Q1: Create a procedure called visitor_name that displays a form asking for the user’s name. The action of the form should be a procedure called process_visitor_name.
15.2.3. Set a Cookie
Q1: Create the procedure process_visitor_name, the action of the form in visitor_name. Set a cookie called VISITOR that stores the visitor name passed in. To set the cookie, utilize the set_cookie procedure from this chapter. Then paint a page with a hyperlink to the main_frame procedure.
15.2.4. Check for the Existence of a Cookie
Q1: Change the main_frame procedure to check for the existence of the VISITOR cookie. Use the cookie_exists function to check for the VISITOR cookie. If the cookie value returned is not null, display the name. Otherwise, call visitor_name.
15.2.5. Retrieve and Display a Cookie Value
Q1: Change the top_frame procedure to retrieve the value of the VISITOR cookie. Use the get_cookie function to retrieve the value of the VISITOR cookie. After the words “University Maintenance Website,” display the words “for” and the visitor’s name. Underneath, in smaller letters, include the message, “If you are not <visitor name>, click here.” Make the word “here” a hyperlink to the visitor_name page.
15.2.6. Retrieve and Display a Cookie Value
Q1: Change the process_visitor_name procedure to set a persistent cookie by giving the cookie an expiration date. Make sure that the visitor name is displayed on subsequent pages by reading the cookie. Close and reopen the browser—it should still display the visitor’s name.

Unit 15.2 Exercise Answers

15.2.1. Answer

Q1: Compile the procedures/functions from this chapter:
  • set_cookie

  • get_cookie

  • get_all_cookies

  • cookie_exists

Answer:
CREATE OR REPLACE PROCEDURE set_cookie 
     (p_cookie_name  IN VARCHAR2, 
      p_cookie_value IN VARCHAR2, 
      p_expires      IN DATE DEFAULT NULL) 
 IS 
BEGIN 
  OWA_UTIL.mime_header(bclose_header=>FALSE); 
  OWA_COOKIE.SEND(p_cookie_name, 
                  p_cookie_value, 
                  p_expires); 
  OWA_UTIL.http_header_close; 
END; 

CREATE OR REPLACE FUNCTION get_cookie 
   (p_cookie_name IN VARCHAR2) 
 RETURN VARCHAR2 
 IS 
    v_cookie     OWA_COOKIE.cookie; 
 BEGIN 
   v_cookie := OWA_COOKIE.GET(p_cookie_name); 
   IF v_cookie.num_vals != 0 THEN 
       RETURN v_cookie.vals(1); 
   ELSE 
       RETURN NULL; 
   END IF; 
END; 

CREATE OR REPLACE PROCEDURE get_all_cookies 
 IS 
    v_cookie_names  OWA_COOKIE.vc_arr; 
    v_cookie_values OWA_COOKIE.vc_arr; 
    v_cookie_count  INTEGER; 
 BEGIN 
   OWA_COOKIE.get_all(v_cookie_names, 
                      v_cookie_values, 
                      v_cookie_count); 
   htp.p('<HTML><BODY>'), 
   FOR num IN 1..v_cookie_count LOOP 
      htp.p('Cookie #'||num||': Name='|| 
             v_cookie_names(num)||', Value='|| 
             v_cookie_values(num)||'<BR>'), 
   END LOOP; 
   htp.p('</BODY></HTML>'), 
   EXCEPTION 
      WHEN OTHERS THEN 
      htp.p('Error in get_all_cookies: '||SQLERRM); 
END; 
CREATE OR REPLACE FUNCTION cookie_exists 
    (p_cookie_name IN VARCHAR2) 
 RETURN BOOLEAN 
 IS 
   v_cookie OWA_COOKIE.COOKIE; 
BEGIN 
   v_cookie := OWA_COOKIE.GET(p_cookie_name); 
   IF v_cookie.num_vals != 0 THEN 
       RETURN TRUE; 
   ELSE 
       RETURN FALSE; 
   END IF; 
END; 

15.2.2. Answer

Q1: Create a procedure called visitor_name that displays a form asking for the user’s name. The action of the form should be a procedure called process_visitor_name.
Answer:
CREATE OR REPLACE PROCEDURE VISITOR_NAME 
   IS 
BEGIN 
htp.p('<HTML> 
       <HEAD><TITLE>Name, Please</TITLE></HEAD> 
       <BODY> 
       <H1>What is Your Name?</H1> 
       <FORM NAME="visitor_name_form" 
             ACTION="process_visitor_name" 
             METHOD="POST"> 
       <INPUT NAME="p_visitor_name" TYPE="text" > 
       <INPUT TYPE="submit" VALUE="Save"> 
       </FORM> 
       </BODY> 
       </HTML>'), 
EXCEPTION 
    WHEN OTHERS THEN 
       htp.p('An error occurred in VISITOR_NAME: ' 
             ||SQLERRM); 
END; 

15.2.3. Answer

Q1: Create the procedure process_visitor_name, the action of the form in visitor_name. Set a cookie called VISITOR that stores the visitor name passed in. To set the cookie, utilize the set_cookie procedure from this chapter. Then paint a page with a hyperlink to the main_frame procedure.
Answer:
CREATE OR REPLACE PROCEDURE PROCESS_VISITOR_NAME 
   (p_visitor_name IN VARCHAR2) 
   IS 
BEGIN 
    set_cookie('VISITOR',p_visitor_name); 
    htp.p('<HTML> 
           <HEAD><TITLE>Thank You</TITLE></HEAD> 
           <BODY> 
           Click <A HREF="main_frame">here</A> to 
           enter the application. 
           </BODY> 
           </HTML>'), 
EXCEPTION 
    WHEN OTHERS THEN 
        htp.p('An error occurred in 
        PROCESS_VISITOR_NAME: '||SQLERRM); 
END; 

15.2.4. Answer

Q1: Change the main_frame procedure to check for the existence of the VISITOR cookie. Use the cookie_exists function to check for the VISITOR cookie. If the cookie value returned is not null, display the name. Otherwise, call visitor_name.
Answer:
CREATE OR REPLACE PROCEDURE MAIN_FRAME AS 
    v_val VARCHAR2(100); 
BEGIN 
IF cookie_exists('VISITOR') THEN 
htp.p(' 
<HTML> 
<HEAD> 
<TITLE>University Maintenance Website 
</TITLE> 
</HEAD> 
<FRAMESET ROWS="133,*"> 
  <FRAME NAME="top" SCROLLING="no" NORESIZE 
         TARGET="main" SRC="top_menu"> 
  <FRAME NAME="main" SRC="splash" TARGET="main"> 
  <NOFRAMES> 
    <BODY> 
    <P>This page uses frames, but your browser doesn''t 
support them. </P> 
    </BODY> 
   </NOFRAMES> 
</FRAMESET> 
</HTML> 
'), 
ELSE
											htp.script('document.location="visitor_name";'),
											END IF; 
END; 

15.2.5. Answer

Q1: Change the top_frame procedure to retrieve the value of the VISITOR cookie. Use the get_cookie function to retrieve the value of the VISITOR cookie. After the words “University Maintenance Website,” display the words “for” and the visitor’s name. Underneath, in smaller letters, include the message, “If you are not <visitor name>, click here.” Make the word “here” a hyperlink to the visitor_name page.
Answer:
CREATE OR REPLACE PROCEDURE TOP_MENU AS 
    v_visitor  VARCHAR2(100); 
 BEGIN 
    v_visitor := get_cookie('VISITOR'), 
    htp.p(' 
    <HTML> 
    <HEAD> 
    <TITLE>University Maintenance Website 
    </TITLE> 
    </HEAD> 
    <BODY BGCOLOR="#99CCFF"> 
    '), 
    htp.p(' 
    <P ALIGN="center"> 
    <FONT FACE="Arial" SIZE=5 >University Maintenance Website for
											'||v_visitor||'</FONT></P> 
    <P ALIGN="right">If you are not '||v_visitor||', click <A
											HREF="visitor_name" TARGET="_top">here</A></P> 
    '), 

    htp.p(' 
    <TABLE BORDER="0" WIDTH="100%"> 
    <TR> 
    <TD ALIGN="center"><A HREF="students_frame" TARGET="main"><FONT 
    FACE="Arial">Students</FONT></A></TD> 
    <TD ALIGN="center"><A HREF="instructors_frame" 
    TARGET="main"><FONT FACE="Arial">Instructors</FONT></A></TD> 
    <TD ALIGN="center"><A HREF="classes_frame" TARGET="main"><FONT 
    face="Arial">Classes</FONT></A></TD> 
    </TR> 
    </TABLE> 
    </BODY> 
    </HTML> 
    '), 
END; 

15.2.6. Answer

Q1: Change the process_visitor_name procedure to set a persistent cookie by giving the cookie an expiration date. Make sure that the visitor name is displayed on subsequent pages by reading the cookie. Close and reopen the browser—it should still display the visitor’s name.
Answer:
CREATE OR REPLACE PROCEDURE PROCESS_VISITOR_NAME 
   (p_visitor_name IN VARCHAR2) 
   IS 
BEGIN 
    set_cookie('VISITOR', 
               p_visitor_name, 
               sysdate+5); 
    htp.p('<HTML> 
           <HEAD><TITLE>Thank You</TITLE></HEAD> 
           <BODY> 
           Click <A HREF="main_frame">here</A> to 
           enter the application. 
           </BODY> 
           </HTML>'), 
EXCEPTION 
    WHEN OTHERS THEN 
        htp.p('An error occurred in 
        PROCESS_VISITOR_NAME: '||SQLERRM); 
END; 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.73.142