changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > werc / bin/cgilib.rc

changeset 360: 279b02c9df5a
parent: 031828ebade4
child: fb1db1dee588
author: uriel@engel.se.cat-v.org
date: Sun, 25 Jan 2009 13:56:53 +0100
permissions: -rw-r--r--
description: Various changes:
- New generic http_redirect function, and two shortcuts for 303: post_redirect and 301: perm_redirect
- Allow get_lib_file to take a default value, and change where master_template is set.
- Fix bugs in auth code and properly trim ^M from post data.
- Other cosmetic/minor improvements.
1 ##############################################
2 # Useful CGI functions
3 
4 NEW_LINE='
5 '
6 
7 fn dprint { echo $* >[1=2] }
8 fn dprintvars { { for(v in $*) { echo -n $v^'#'^$#$v^'=' $$v '; ' }; echo } >[1=2] }
9 
10 fn escape_html { sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' $* }
11 
12 fn http_redirect {
13  echo 'Status: '^$2^'
14 Location: '^$1^'
15 
16 '
17  exit
18 }
19 fn perm_redirect { http_redirect $1 '301 Moved Permanantly' }
20 fn post_redirect { http_redirect $1 '303 See Other' }
21 
22 fn static_file {
23  echo 'Content-Type: '`{select_mime $1}
24  echo
25  cat $1
26  exit
27 }
28 
29 
30 # Note: should check if content type is application/x-www-form-urlencoded?
31 fn load_post_args {
32  if(~ $REQUEST_METHOD POST && ~ $#post_args 0) {
33  ifs='&
34 ' for(pair in `{cat}) {
35  ifs='=' { pair=`{echo -n $pair} }
36  n='post_arg_'^`{echo $pair(1)|tr -cd 'a-zA-Z0-9_'}
37  post_args=( $post_args $n )
38  ifs=() { $n=`{echo -n $pair(2)|urldecode|tr -d '
39 '} }
40  }
41  pair=()
42  }
43  if not
44  status='No POST or post args already loaded'
45 }
46 # Status is () if at least one arg is found. DEPRECATED: access vars directly.
47 fn get_post_args {
48  load_post_args
49  _status='No post arg matches'
50  for(n in $*) {
51  v=post_arg_$n
52  if(! ~ $#$v 0) {
53  $n=$$v
54  _status=()
55  }
56  }
57  status=$_status
58 }
59 
60 # This seems slightly improve performance, but might depend on httpd buffering behavior.
61 fn awk_buffer {
62  awk '{
63  buf = buf $0"\n"
64  if(length(buf) > 1400) {
65  printf "%s", buf
66  buf = ""
67  }
68  }
69  END { printf "%s", buf }'
70 }
71 
72 fn urldecode {
73 awk '
74 BEGIN {
75  hextab ["0"] = 0; hextab ["8"] = 8;
76  hextab ["1"] = 1; hextab ["9"] = 9;
77  hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10
78  hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11;
79  hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12;
80  hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13;
81  hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14;
82  hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15;
83 }
84 {
85  decoded = ""
86  i = 1
87  len = length ($0)
88  while ( i <= len ) {
89  c = substr ($0, i, 1)
90  if ( c == "%" ) {
91  if ( i+2 <= len ) {
92  c1 = substr ($0, i+1, 1)
93  c2 = substr ($0, i+2, 1)
94  if ( hextab [c1] == "" || hextab [c2] == "" ) {
95  print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2"
96  } else {
97  code = 0 + hextab [c1] * 16 + hextab [c2] + 0
98  c = sprintf ("%c", code)
99  i = i + 2
100  }
101  } else {
102  print "WARNING: invalid % encoding: " substr ($0, i, len - i)
103  }
104  } else if ( c == "+" ) {
105  c = " "
106  }
107  decoded = decoded c
108  ++i
109  }
110  printf "%s", decoded
111 }
112 '
113 }
114 
115 fn crop_text {
116  ellipsis='...'
117  if(~ $#* 2)
118  ellipsis=$2
119 
120  awk -v max'='^$"1^' ' -v 'ellipsis='$ellipsis '
121  {
122  nc += 1 + length;
123  if(nc > max) {
124  print substr($0, 1, nc - max) ellipsis
125  exit
126  }
127  print
128  }'
129 }
130 
131 
132 # Cookies
133 fn set_cookie {
134  # TODO: should check input values more carefully
135  name=$1
136  val=$2
137  extraHttpHeaders=( $extraHttpHeaders 'Set-cookie: '^$"name^'='^$"val^'; path=/;' )
138 }
139 fn get_cookie {
140  ifs=';' { co = `{ echo $HTTP_COOKIE } }
141 
142  # XXX: we might be adding a trailing new line?
143  # The ' ?' is needed to deal with '; ' inter-cookie delimiter
144  { for(c in $co) echo $c } | sed -n 's/^ ?'$1'=//p'
145 }
146 
147 fn select_mime {
148  m='text/plain'
149  if(~ $1 *.css)
150  m='text/css'
151  if not if(~ $1 *.ico)
152  m='image/x-icon'
153  if not if(~ $1 *.png)
154  m='image/png'
155  if not if(~ $1 *.jpg *.jpeg)
156  m='image/jpeg'
157  if not if(~ $1 *.gif)
158  m='image/gif'
159  if not if(~ $1 *.pdf)
160  m='application/pdf'
161  echo $m
162 }
163 
164 ##############################################
165 # Generic rc programming helpers
166 
167 fn ll_add {
168  _l=$1^_^$#$1
169  $_l=$*(2-)
170  $1=( $$1 $_l )
171 }
172 
173 
174 ##############################################
175 # Werc-specific functions
176 
177 fn get_lib_file {
178  if(! ~ $#sitedir 0 && test -f $sitedir/_werc/lib/$1)
179  echo -n $sitedir/_werc/lib/$1
180  if not if(! ~ $#masterSite 0 && test -f $sitesdir/$masterSite/_werc/lib/$1)
181  echo -n $sitesdir/$masterSite/_werc/lib/$1
182  if not if(test -f lib/$1)
183  echo -n lib/$1
184  if not if(~ $#* 2)
185  echo -n $2
186  if not
187  status='Can''t find lib file: '$1
188 }
189 
190 fn template { awk -f bin/template.awk $* | rc $rcargs }
191 
192 # Auth code
193 
194 # Cookie format: WERC_USER: name:timestamp:hash(name.timestamp.password)
195 # login_user can't be used from a template because it sets a cookie
196 fn login_user {
197  # Note: we set the cookie even if it is already there.
198  if(get_user $*)
199  set_cookie werc_user $"logged_user^':0:'^$"logged_password
200 }
201 
202 # Check loggin status, if called with group arg we check membership too
203 fn check_user {
204  get_user
205  _status=$status
206  if(! ~ $#_status 0 )
207  _status=(Not logged in: $"_status)
208  if not if(! ~ $#* 0 && ! grep -s '^'^$logged_user^'$' etc/groups/$*) {
209  dprint NOT IN GROUP
210  _status=(User $logged_user not in groups $*)
211  }
212  status=$_status
213 }
214 
215 # If not logged in, try to get user login info from POST or from cookie
216 fn get_user {
217  if(~ $#logged_user 0) {
218  if(~ $#* 2) {
219  user_name=$1
220  user_password=$2
221  }
222  if not if(~ $REQUEST_METHOD POST)
223  get_post_args user_name user_password
224 
225  if(~ $#user_name 0) {
226  ifs=':' { cu=`{get_cookie werc_user|tr -d $NEW_LINE} }
227  if(! ~ $#cu 0) {
228  user_name=$cu(1)
229  user_password=$cu(3)
230  }
231  }
232  auth_user $user_name $user_password
233  }
234  if not
235  status=()
236 }
237 
238 # Check if user_name and user_password represent a valid user account
239 # If valid, 'log in' by setting logged_user
240 fn auth_user {
241  user_name=$1
242  user_password=$2
243 
244  pfile='etc/users/'^$"user_name^'/password'
245  if(~ $#user_name 0 || ~ $#user_password 0)
246  status=('Auth: missing user name or pass: '^$"user_name^' / '^$"user_password)
247  if not if(! test -f $pfile)
248  status=('Auth: cant find '^$pfile)
249  if not if(! ~ $user_password `{cat $pfile})
250  status=('Auth: Pass '$user_password' doesnt match '^`{cat $pfile})
251  if not {
252  logged_user=$user_name
253  logged_password=$user_password
254  dprint Auth: success
255  status=()
256  }
257 }
258 
259 fn user_controls {
260  echo User: $"logged_user
261 }
262 
263 
264 # .md '(meta-)data' extract
265 fn get_md_file_attr {
266  sed -n '/^\* '$2': /p; /^\* '$2': /q; /^$/q' < $1
267 }
268 
269 #app_blog_methods = ( _post index.rss )
270 #fn app_blog__post {
271 # echo
272 #}
273 #
274 #app_blog___default {
275 # if (~ $blog)
276 # call_app blogpost
277 #}
278 #
279 ## --
280 #app_blogpost_methods = ( comment _edit )
281 #
282 #fn app_blogpost_comment {
283 # call_app comments
284 #}
285 #
286 ## --
287 #app_comments_methods = ( _post _edit )
288 #
289 #fn app_comments___default {
290 #
291 #}