#!c:\rebol\lib-core\rebol.exe -cs

;; you will need your own shebang on the line above

REBOL [
    Title: "cookie-example.r"
    Date: 6-october-2003
    Version: 1.0.1
    File: %cookie-example.r
    Author: "Sunanda"
    Purpose: {Demonstrates how to set session cookies and use them to retrieve
            session variables. Much of the code has been cobbled together from
            much more structured (ie not all in one module) code used by
            rebol.org itself}
    library: [
        level: 'intermediate
        platform: 'all
        type: 'demo
        domain: [cgi web]
        tested-under: none
        support: none
        license: bsd
        see-also: none
    ]
]

;; function to send page
;; ----------------------
send-output: func [html [string!]]
[

    print "Content-type: text/html^/"
    print html
    quit
]


; =======================================
clear-place-holders: func [str [string!]
                    /local out-str ph
                    len old-len
                    ]
;; ---------------------------------------
;; In some pages we'll have some place-holders
;; left over when we've finished replacing the
;; ones in use. This function removes the
;; remaining ones.
;; A place-holder is identified as starting
;; and ending with "!!".
;; -------------------------------------------

[
out-str: copy str

 forever [
    ph: none
    parse/all out-str [thru "!!"  copy ph to "!!"]
    if none? ph [break]
    replace/all out-str join "!!" [ph "!!"] ""
    ]

return trim/lines out-str   ;; no one needs spaces in a web-page
                            ;; unless you have 
]


;;  ====================================
defuse-cgi-field: func [field [string!]]

;;  Input CGI fields that contain <, > or & are
;;  bad for security if we just slip-stream them into
;;  the output. The could contain "active" elements
;;  like HTML formatting or Javascript code
;;  We defuse them by converting harmful characters to
;;  their equivalent entities
[

 replace/all field "&" "&"
 replace/all field "<" "<"
 replace/all field ">" ">"
 return field

]


read-cgi: func [
;; --------------------------------------------
;; Read CGI data. Return data as string or NONE.
;; Lifted from Carl's viewback.cgi.
;; --------------------------------------------
    /local data buffer
][
    switch system/options/cgi/request-method [
        "POST" [
            data: make string! 1020
            buffer: make string! 16380
            while [positive? read-io system/ports/input buffer 16380][
                append data buffer
                clear buffer
            ]
        ]
        "GET" [data: system/options/cgi/query-string]
    ]
    data
]



;;  =======================
;;  gets or sets the cookie
;;  Assumed to be in the format
;;  keyword=xxxxxxxxxxxx
;;  =======================
    cookie: func    [/get
                     /set cookie-data [string!]
                     /local pointer
                     				cookie-value
                     ]
[


 if get [
 		 	  cookie-value: select system/options/cgi/other-headers "HTTP_COOKIE"
 		 	  if none? cookie-value [return none]
 		 	  return first parse cookie-value "="
      ]

 if set
    [

     pointer: find  system/options/cgi/other-headers "HTTP_COOKIE"
     either none? pointer
            [
             append system/options/cgi/other-headers "HTTP_COOKIE"
             append system/options/cgi/other-headers cookie-data

            ]
            [
             poke system/options/cgi/other-headers (1 + index? pointer) cookie-data
             ]
     print join "set-cookie: " form cookie-data      ;; sends cookie to browser

     return true
    ]
]


;; ================================
;;  Read user data from the cookie.
;;
;;  Returns:
;;  -- an object if cookie points to a user data record
;;  -- false if it doesn't
;;  ================================
read-user-record-from-cookie: func [
                    /local cookie-value
                        cookie-split
                        user-data
                        error-code
                    ]

[   cookie-value: cookie/get
    if none? cookie-value [return "no cookie"]
    if error? error-code: try [user-data: do read to-file form cookie-value]
            [return join "bad read" mold disarm error-code]

    return user-data
]


;; ========================================
write-user-record: func [user-data [object!]
                    /local
                    ]

[

 user-data/last-active-date: now/precise


 write  to-file  form cookie/get
            mold user-data
 return true


]


Web-page: {





Cookie-example.r from the REBOL.org Script Library




Cookie-example.r

Type stuff into the text field below. It will be reflected into the next paragraph. Because we store a cookie in your browser and an object on the web-server, we can rembemer what you typed and we will reflect all previous strings typed until you exit the browser.

Input text

Cumulative text from previous sends

!!cumulative-text!!

You last pressed enter on !!last-active!!

Your cookie is

!!cookie!!

} ;; Main processing starts here ;; =========================== if error? cgi-error: try [ cgi-input: read-cgi ;; No cgi? Give them a page with all fields empty and retire ;; ----------------------------------------------------------- if any [none? cgi-input "" = cgi-input ] [send-output clear-place-holders web-page] ;; we got data ;; ------------ ;; create object with all fields ;; ---------------------------- cgi-object: make object! [] cgi-object: construct/with decode-cgi cgi-input cgi-object ;; check if required fields are present ;; ------------------------------------- if error? try [cgi-object/input-text] [ send-output clear-place-holders web-page ] ;; get or set the cookie ;; ===================== user-data-object: read-user-record-from-cookie user-data-was: mold user-data-object if not object? user-data-object [ cookie/set: form checksum/secure form now/precise user-data-object: make object! [last-active-date: none user-data: copy [] ] ] ;; We now have a new user-data object, ;; or the one from the last time. ;; Now we add to the saved user data, ;; and reflect back all the data append user-data-object/user-data form cgi-object/input-text foreach text user-data-object/user-data [ replace web-page "!!cumulative-text!!" join defuse-cgi-field text [
"!!cumulative-text!!"] ] ;; Reflect the input fields to the output page ;; ------------------------------------------ replace web-page "!!input-text!!" defuse-cgi-field cgi-object/input-text replace web-page "!!cookie!!" cookie/get replace web-page "!!last-active!!" user-data-object/last-active-date ;; Save the user record ;; -------------------- write-user-record user-data-object send-output clear-place-holders web-page ] ;; cgi error code ;; -------------- [ print "Content-type: text/html^/" print "

Oops we had an error

" print mold disarm cgi-error quit ]