Switch to Italian
Giovanni's logo
Handling Cookies
this means Version 2
index
M
power search
blue line
1. About Cookies

Cookies are a mechanism for storing persistent data on the client. As HTTP is a stateless protocol, cookies provide a way to maintain information between client requests.
In a sense, a cookie may be though of as a small data area on the client.
A cookie has the following properties:

Name mandatory Identifies the cookie (as if it were the name of a data area)
Value mandatory The contents of the cookie (as if it were the value of a data area). Note that Mozilla browser (Firefox) does not support blanks in the cookie value. If that happens, the Set-Cookie string is trimmed right at the first blank met. Therefore it may be needed to substitute all the blanks in a cookie value with some other character before creating the cookie; in such a case, the opposite operation should be performed after retrieving the cookie.
Expiration optional The date until which the cookie should survive. If the expiration is not specified, the cookie expires when the user session ends.
Domain optional The domain under which the cookie can be retrieved. If the domain is not specified, the web browser should assume the host name of the server generating the cookie.
Path optional The path under which the cookie can be retrieved. If the path is not specified, the web browser should assume the path of the page generating the cookie.
HttpOnly optional HttpOnly is an additional flag included in a Set-Cookie HTTP response header. Using the HttpOnly flag when generating a cookie helps mitigate the risk that a malicious client side script (usually written in XSS) -if supported by the browser - to access the cookie thus stealing security sensible information (example: passwords).
For more information, see this page.
The use of this feature is highly recommended.
Secure optional Secure is another additional flag included in a Set-Cookie HTTP response header. When specified, the cookie can be accessed only through a "secure" HTTP server (HTTPS).

Cookies are stored and retrieved by the web browser.

Whenever a web page is loaded, the web browser makes available all the unexpired cookies that:

  1. match the domain of the page
    (for instance, www.ibm.com or 195.183.8.2)
  2. are in the path of the page
    (for instance, to page /cgidev2o/exhibiu8.htm are made available all the cookies with path "/" and all the cookies with path "/cgidev2o").
For a comprehensive guide about creating and using cookies, see Website Cookies: Everything You Need To Know.



2. Creating a Cookie with a CGI - Basic approach

To create a cookie you must provide, in the external html, a Set-Cookie http header, as follow:

/$top
Content-type: text/html
Set-Cookie: name=value [;EXPIRES=dateValue] [;DOMAIN=domainName] [;PATH=pathName] [;SECURE] [;HTTPONLY]
(mandatory blank line)
<html>
  ... etc. ...

For detail explanation about the Set-Cookie http header, please refer to the following page.



3. Retrieving a cookie in a CGI - Basic approach

A CGI can retrieve all the available cookies through the environment variable HTTP_COOKIE. The cookies made available are all those compliant with the domain name and the path of the CGI. The following example illustrates the value returned from the environment variable HTTP_COOKIE in a case where two cookies were found:

  • the first cookie has name=IBM and value=HG1V432
  • the second cookie has name=Easy400 and value=JohnVincentBrown
IBM=HG1V432; Easy400=JohnVincentBrown

Note 1. As all the available cookies are returned in a single string, it is a program responsibility to retrieve from this string the cookies it might be interested in.

Note 2. The value of a cookie may contain escaped characters. An escaped character is the ASCII hexadecimal representation of an ASCII character. For instance, %3D is an escaped character and is the ASCII hexadecimal representation of ASCII character "=".
Escaped characters are generated by the web browser when storing a cookie. This is done to eliminate conflicts with regulare string separator and control characters.
Now, it is a responsibility of the CGI program to convert any ASCII escaped characters --in the value of a retrieved cookie-- to the corresponding EBCDIC characters.

See our example about creating and retrieving a cookie in a CGI through this approach.



4. Creating/retrieving a cookie in a CGI - Advanced approach
Service program cgidev2/cgisrvpgm2 provides two subprocedures to help managing cookies in a CGI:
  • crtCookie allows for an easier construction of the Set-Cookie http header
  • getCookieByName retrieves a given cookie from the HTTP_COOKIE environment variable.
/$top
Content-type: text/html
Expires: 0
/%setmycookie%/

<html>
... etc. ...
      ** Variables used to build the http header "Set-Cookie"
      ** through subprocedure "CrtCookie"
     D  SetMyCookie    s           1000    varying
     D  CookieNam      s           1000    varying
     D  CookieVal      s           4000    varying
     D  RetCode        s             10i 0
     D  Domain         s           1000    varying
     D  Path           s           1000    varying
     D  Secure         s               n
     D  Expires        s               z
     D  HttpOnly       s               n
     D  xdocloc        s            512
      ** Other variables
     D TimeNow         s               z
     D r1              s             10i 0
     D r2              s             10i 0
      *=====================================================================
      * Main line
      *=====================================================================
      /free

            // Get broswer input
            nbrVars=zhbgetinput(savedquerystring:qusec);

            // Load external html, if not loaded yet
            gethtml('DEMOHTML':'CGIDEV2':'COOKIE2':'/$');

            // Create the Set-Cookie header
            exsr CrtMyCook;

            // Start the output html
            updhtmlvar('setmycookie':SetMyCookie);
            wrtsection('top');

            // Retrieve cookie current value and display it
            exsr RtvMyCook;
            updHtmlVar('cookienam':CookieNam);
            updHtmlVar('cookieval':CookieVal);
            if CookieVal=' ';
               wrtsection('cookieno');
            else;
               wrtsection('cookieyes');
            endif;

            // End the output html
            UpdHtmlVar('timenow':%trim(%char(TimeNow)));
            wrtsection('endhtml *fini');

            return;

      /end-free
      *=====================================================================
      * Create a cookie
      *   Name:    ThreeMonths
      *   Value:   current timestamp
      *   Domain:  current CGI domain
      *   Path:    /
      *   Secure:  no
      *   Expires: three months from now
      *   HttpOnly:yes
      *=====================================================================
      /free

            Begsr CrtMyCook;

            //Retrieve the server domain into variable "Domain"; trim off the port number
            exsr RtvDomain;
            //Reset the domain to blank. The WEB browser assumes the host name of the server
            // generating the cookie
            Domain=' ';

            //Set cookie name, cookie value and cookie path
            CookieNam='ThreeMonths';
            CookieVal=randomString(10);
            Path='/';

            //Set cookie expiration date & time
            TimeNow=%timestamp;
            Expires=TimeNow+%months(3);

            //Set HttpOnly flag
            //In this way the cookie can be accessed (created or read) only from the HTTP server.
            //This prevents access from malicious javascripts (XSS).
            HttpOnly=*on;

            //In this example the "secure" flag is not used.
            //It may be used to restrict the cookie access only to HTTPS
            //(HTTP would not be able to access the cookie).

            //Create the Set-Cookie header
            SetMyCookie=CrtCookie(CookieNam:CookieVal:RetCode:Domain:
                        Path:*off:Expires:HttpOnly);

            Endsr;

      /end-free
      *=====================================================================
      * Retrieve the server domain
      * The server domain is the one the URL of a document starts with,
      * As an example, in the URL
      *       http://www.easy400.net/easy400p/maindown.html
      * the server domain is
      *       www.easy400.net
      *
      * HOW TO SET THE DOMAIN OF THE COOKIE
      * 1-APPROACH NUMBER ONE (deprecated)
      * Usually, there is no easy way through which your CGI can find out
      * what the server domain is.
      * One way I found, is to have the document URL retrieved from some javascript
      * and have it passed in an input variable of the form invoking the CGI.
      * Example:
      *  <form name=cookie2 method=post action="/cgidev2p/cookie2.pgm">
      *  <script language=javascript>
      *  document.write("<input type=hidden name=xdocloc value='"+document.location+"'>")
      *  </script>
      *      ....
      *  </form>
      *  In this way the document URL is passed in the input variable "xdocloc".
      *  NOTE, however, that if a port number is specified, the port number is returned
      *  with the URL and it should not be part of the domain.
      * 2-APPROACH NUMBER TWO (suggested)
      *  The easiest way is to specify no domain for the cookie. When this is done, the
      *  WEB browser assumes as domain of the cookie the name of the host creating the cookie.
      *
      * Though this subroutine uses approach number ONE to retrieve the domain name for the
      * cookie, the program sets the domain name for the cookie to blank, thus making the
      * WEB browser default the cookie domain to the name of the host creating the cookie.
      *
      *=====================================================================
      /free

            Begsr RtvDomain;

            Domain=' ';
            xdocloc=zhbgetvar('xdocloc');        //document location ("http://domain:port/...")

            //Remove the URI ("/...") and the port number (if any)
            r1=%scan('http://':xdocloc);
            if r1=1;
               r2=%scan('/':xdocloc:8);
               if r2>8;
                  Domain=%subst(xdocloc:8:r2-8);
                  r1=%scan(':':Domain);
                  if r1>1;
                     Domain=%subst(Domain:1:r1-1);
                  endif;
               endif;
            endif;

            Endsr;

      /end-free
      *=====================================================================
      * Retrieve a cookie of given name
      * Returns a string containing the current value of the cookie,
      *         or blanks if cookie not found
      *=====================================================================
      /free

            Begsr RtvMyCook;

            CookieNam='ThreeMonths';
            CookieVal=GetCookieByName(CookieNam);

            Endsr;

See our example about creating and retrieving a cookie in a CGI through this approach.



5. About privacy

Sending a cookie to a client device could be interpreted as a privacy violation. This is why, when a site works with cookies, it is highly recommended to;
  • notify the user that cookies will be used
  • specify what kind of use they are for
  • disable further process until the user checks a button after reading
(European contries have been given a regulation on this subject in September 2016, see EU legislation on cookies).

For some information about different types of cookies and user defenses from them, see How cookies track you around the web and how to stop them.