changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > werc / bin/cgilib.rc

changeset 663: 5c2c279b6320
parent: fb460a671d19
author: sl
date: Wed, 10 Feb 2016 20:32:57 -0500
permissions: -rwxr-xr-x
description: bin/cgilib.rc: hack urlencode/urldecode for UNIX *and* Plan 9
1 # Useful CGI stuff
2 
3 fn dprint { echo $* >[1=2] }
4 fn dprintv { { for(v in $*) { echo -n $v^'#'^$#$v^'=' $$v '; ' }; echo } >[1=2] }
5 fn echo {if(! ~ $1 -n || ! ~ $2 '') /bin/echo $*}
6 fn escape_html { sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' $* }
7 
8 fn http_redirect {
9  if(~ $1 http://* https://*)
10  t=$1
11  if not if(~ $1 /*)
12  t=$"base_url^$1
13  if not
14  t=$"base_url^$"req_path^$1
15  exec /bin/echo 'Status: '^$2^'
16 Location: '^$t^'
17 
18 '
19  exit
20 }
21 fn perm_redirect { http_redirect $1 '301 Moved Permanantly' }
22 fn post_redirect { http_redirect $1 '303 See Other' }
23 
24 
25 # Note: should check if content type is application/x-www-form-urlencoded?
26 # Should compare with http://www.shelldorado.com/scripts/cmds/urlgetopt.txt
27 fn load_post_args {
28  if(~ $REQUEST_METHOD POST && ~ $#post_args 0) {
29  ifs='&
30 ' for(pair in `{cat}) {
31  ifs='=' { pair=`{echo -n $pair} }
32  n='post_arg_'^`{echo $pair(1)|urldecode|tr -cd 'a-zA-Z0-9_'}
33  post_args=( $post_args $n )
34  ifs=() { $n=`{echo -n $pair(2)|urldecode|tr -d '
35 '} }
36  }
37  pair=()
38  }
39  if not
40  status='No POST or post args already loaded'
41 }
42 # Status is () if at least one arg is found. DEPRECATED: access vars directly.
43 fn get_post_args {
44  load_post_args
45  _status='No post arg matches'
46  for(n in $*) {
47  v=post_arg_$n
48  if(! ~ $#$v 0) {
49  $n=$$v
50  _status=()
51  }
52  }
53  status=$_status
54 }
55 
56 # This seems slightly improve performance, but might depend on httpd buffering behavior.
57 fn awk_buffer {
58  awk '{
59  buf = buf $0"\n"
60  if(length(buf) > 1400) {
61  printf "%s", buf
62  buf = ""
63  }
64  }
65  END { printf "%s", buf }'
66 }
67 
68 fn urldecode { $PLAN9/bin/urlencode -d || url_decode} # GROSS
69 
70 fn url_decode {
71 awk '
72 BEGIN {
73  hextab ["0"] = 0; hextab ["8"] = 8;
74  hextab ["1"] = 1; hextab ["9"] = 9;
75  hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10
76  hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11;
77  hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12;
78  hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13;
79  hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14;
80  hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15;
81 }
82 {
83  decoded = ""
84  i = 1
85  len = length ($0)
86  while ( i <= len ) {
87  c = substr ($0, i, 1)
88  if ( c == "%" ) {
89  if ( i+2 <= len ) {
90  c1 = substr ($0, i+1, 1)
91  c2 = substr ($0, i+2, 1)
92  if ( hextab [c1] == "" || hextab [c2] == "" ) {
93  print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2"
94  } else {
95  code = 0 + hextab [c1] * 16 + hextab [c2] + 0
96  c = sprintf ("%c", code)
97  i = i + 2
98  }
99  } else {
100  print "WARNING: invalid % encoding: " substr ($0, i, len - i)
101  }
102  } else if ( c == "+" ) {
103  c = " "
104  }
105  decoded = decoded c
106  ++i
107  }
108  printf "%s", decoded
109 }
110 '
111 }
112 
113 fn urlencode { $PLAN9/bin/urlencode $* || url_encode } # GROSS
114 
115 fn url_encode {
116  awk '
117  BEGIN {
118  # We assume an awk implementation that is just plain dumb.
119  # We will convert an character to its ASCII value with the
120  # table ord[], and produce two-digit hexadecimal output
121  # without the printf("%02X") feature.
122 
123  EOL = "%0A" # "end of line" string (encoded)
124  split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ")
125  hextab [0] = 0
126  for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
127  if ("'^$"EncodeEOL^'" == "yes") EncodeEOL = 1; else EncodeEOL = 0
128  }
129  {
130  encoded = ""
131  for ( i=1; i<=length ($0); ++i ) {
132  c = substr ($0, i, 1)
133  if ( c ~ /[a-zA-Z0-9.-]/ ) {
134  encoded = encoded c # safe character
135  } else if ( c == " " ) {
136  encoded = encoded "+" # special handling
137  } else {
138  # unsafe character, encode it as a two-digit hex-number
139  lo = ord [c] % 16
140  hi = int (ord [c] / 16);
141  encoded = encoded "%" hextab [hi] hextab [lo]
142  }
143  }
144  if ( EncodeEOL ) {
145  printf ("%s", encoded EOL)
146  } else {
147  print encoded
148  }
149  }
150  END {
151  #if ( EncodeEOL ) print ""
152  }
153 ' $*
154 }
155 
156 # Cookies
157 fn set_cookie {
158  # TODO: should check input values more carefully
159  name=$1
160  val=$2
161  extraHttpHeaders=( $extraHttpHeaders 'Set-cookie: '^$"name^'='^$"val^'; path=/;' )
162 }
163 fn get_cookie {
164  ifs=';' { co=`{echo $HTTP_COOKIE} }
165 
166  # XXX: we might be adding a trailing new line?
167  # The ' ?' is needed to deal with '; ' inter-cookie delimiter
168  { for(c in $co) echo $c } | sed -n 's/^ ?'$1'=//p'
169 }
170 
171 
172 fn static_file {
173  echo -n 'Content-Type: '
174  select_mime $1
175  echo
176  exec cat $1
177 }
178 
179 fn select_mime {
180  m='text/plain'
181  if(~ $1 *.css)
182  m='text/css'
183  if not if(~ $1 *.ico)
184  m='image/x-icon'
185  if not if(~ $1 *.png)
186  m='image/png'
187  if not if(~ $1 *.jpg *.jpeg)
188  m='image/jpeg'
189  if not if(~ $1 *.gif)
190  m='image/gif'
191  if not if(~ $1 *.pdf)
192  m='application/pdf'
193  echo $m
194 }
195 
196 ##############################################
197 # Generic rc programming helpers
198 
199 # Manage nested lists
200 fn ll_add {
201  _l=$1^_^$#$1
202  $_l=$*(2-)
203  $1=( $$1 $_l )
204 }
205 # Add to the head: dangerous if you shrink list by hand!
206 fn ll_addh {
207  _l=$1^_^$#$1
208  $_l=$*(2-)
209  $1=( $_l $$1 )
210 }
211 
212 
213 NEW_LINE='
214 '
215 
216 # crop_text [max_lenght [ellipsis]]
217 # TODO: Option to crop only at word-delimiters.
218 fn crop_text {
219  m=512
220  e='...'
221  if(! ~ $#1 0)
222  m=$1
223  if(! ~ $#2 0)
224  e=$2
225 
226  awk -v 'max='^$"m -v 'ellipsis='$e '
227  {
228  nc += 1 + length;
229  if(nc > max) {
230  print substr($0, 1, nc - max) " " ellipsis
231  exit
232  }
233  print
234  }'
235 }
236 
237