1 # ===================================================================== 2 # weblib.rc: common stuff for application-layer Web services. 3 # 4 # Copyright (c) 2006-2011 Carlo Strozzi 5 # 6 # This program is free software; you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation; version 2 dated June, 1991. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program; if not, write to the Free Software 17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 # 19 # ===================================================================== 20 21 # ===================================================================== 22 # CSA rc(1) function overrides. 23 # ===================================================================== 24 25 # ===================================================================== 26 # Account for SSL implemented with stunnel(8) and thttpd(8). 27 # 28 # Usage: csaIsWeb [-s|--ssl] 29 # 30 # Return '0' if CSA is running as a WWW processor, or '1' otherwise. 31 # If '-s' is specified, additional tests are done to see whether 32 # SSL is in use. 33 # ===================================================================== 34 35 fn csaIsWeb { 36 37 ~ $CSA_DEBUG 0 || csaDebug $0 $* 38 39 CSA_STATUS=0 40 41 if (~ $REQUEST_METHOD ()) { 42 CSA_STATUS=1 43 return 1 44 } 45 46 # Add more hard-coded cases below if necessary. 47 if (~ $1 -s --ssl) { 48 if (~ $SERVER_SOFTWARE thttpd/2.* && 49 ~ $REMOTE_ADDR 127.0.0.1 ::1 && 50 ~ $HTTP_HOST $TNS_STUNNEL_HOSTS) { 51 52 return 0 53 } 54 55 # Probably specific to the Apache web server. 56 if (~ $SSL_CIPHER_USEKEYSIZE () && !~ $HTTPS on) { 57 CSA_STATUS=1 58 return 1 59 } 60 } 61 62 return 0 # probably necessary. 63 } 64 65 # ===================================================================== 66 # Usage: makeFullName [-s|--sreg] [first [last]] 67 # 68 # Return "First Last" starting from first and last name. If '--sreg' is 69 # specified, the returned string will be in OpenID Simple Registration 70 # Extension's "Last, First" format. 71 # ===================================================================== 72 73 fn makeFullName { 74 75 ~ $CSA_DEBUG 0 || csaDebug $0 $* 76 77 if (~ $1 -s --sreg) { 78 79 if (~ $2 () && ~ $3 ()) { 80 CSA_RESULT = () 81 } else { 82 if (~ $2 ()) { 83 CSA_RESULT = $3 84 } else { 85 if (~ $3 ()) { 86 CSA_RESULT = $2 87 } else CSA_RESULT = $3,' '$2 88 } 89 } 90 91 } else { 92 93 if (~ $1 () && ~ $2 ()) { 94 CSA_RESULT = () 95 } else { 96 if (~ $1 ()) { 97 CSA_RESULT = $2 98 } else { 99 if (~ $2 ()) { 100 CSA_RESULT = $1 101 } else CSA_RESULT = $1' '$2 102 } 103 } 104 105 } 106 107 CSA_STATUS=0 108 } 109 110 # ===================================================================== 111 # csvMatch [needle [haystack]] 112 # 113 # Return '0' if *any* of the comma-separated (CSV) values in 'needle' 114 # are found in the comma-separated string 'haystack'. Return '1' if no 115 # values match or '0' if there is at least one match. 116 # 117 # TODO: 118 # * "--all" switch, to require a match on all input values, by contrast 119 # with the current requirement of a match on any of the values. 120 # * A command-line switch to pick other than comma as separator. 121 # ===================================================================== 122 123 fn csvMatch { 124 125 ~ $CSA_DEBUG 0 || csaDebug $0 $* 126 127 csa1 = $2 { 128 129 ~ $#* 0 1 2 || csaExit.fault 0001 $0' [needle [haystack]]' 130 131 CSA_STATUS = 0 132 133 # Two empty values always match. 134 ~ $* () && return 0 135 136 # A single argument always evaluates to no-match. 137 ~ $2 () && { CSA_STATUS=1; return 1 } 138 139 * = ``,{echo -n $1} 140 141 while (!~ $#* 0) { 142 ~ ,$csa1, *,$1,* && return 0 143 shift 144 } 145 146 CSA_STATUS=1; return 1 147 } 148 } 149 150 # ===================================================================== 151 # Usage: makeNode args ... 152 # 153 # Create a new node in the TW database and write 'args' into it. 154 # ===================================================================== 155 156 fn makeNode { 157 158 ~ $CSA_DEBUG 0 || csaDebug $0 $* 159 160 ~ $#* 0 && csaExit.fault 0001 $0' content' 161 162 node_num = () 163 node_path = () 164 node_pid = $pid 165 node_args = $* 166 167 # Compute unique numeric node-ID, and account for the 168 # (hopefully unlikely) case where the computed node already 169 # exists. Albeit unlikely, this may theoretically happen 170 # on a NFS filesystem shared by multiple CPUs running TW. 171 # The computed node number is such that it is compatible with 172 # mawk's max-integer default limit of 1999999999 . 173 174 ~ $'cgi.node.stem' () && csaExit.fault 0041 cgi.node.stem 175 ~ $'cgi.node.pbc' () && csaExit.fault 0041 cgi.node.pbc 176 177 # This can be done without TPC, as if the directory does not 178 # exist it will be created unconditionally, which is correct. 179 180 mkdir -p $CSA_ROOT/var/nodes/$'cgi.node.pbc' || 181 csaExit.fault 0003 mkdir 182 183 * = (1 2 3 4) # let's not loop forever! 184 185 while (!~ $1 ()) { 186 node_num = `{csa-space $node_pid} 187 ~ $#node_num () && csaExit.fault 0003 csa-space 188 189 # Take the rightmost four digits of $pid, after front-padding 190 # the latter with zeroes to make it 4-digit long if shorter. 191 192 while (~ $node_num(4) ()) node_num = (0 $node_num) 193 194 # Last chance to get a free node ID ? Then try and step 195 # the epoch part down by ten. Better not to step it up, 196 # not to steal that possibility from a future run. 197 198 ~ $2 () && cgi.node.stem = `{expr $'cgi.node.stem' - 10} 199 200 # Compute new node's full path. 201 node_num = \ 202 $'cgi.node.stem'$node_num(1)^$node_num(2)^$node_num(3)^$node_num(4) 203 node_path = $CSA_ROOT/var/nodes/$'cgi.node.pbc'/$node_num 204 205 # Lock the target file, in case someone alse is trying to 206 # create the same node name. 207 208 csaLock $node_path || csaExit.fault 209 210 if (csaIsFullPath --exists --quiet $node_path) { 211 212 # Release right-away. 213 csaUnlock $node_path 214 215 # Try again with different pid 216 node_pid = `{sh -c 'echo $$'} 217 218 } else { 219 220 csaTrue $CSA_AUDIT && csaTrapFile $node_path,v 221 222 csaOpen --fast --relaxed $node_path || csaExit.fault 223 echo $node_args > $CSA_RESULT 224 ~ $status 0 || csaExit.fault 0009 $CSA_RESULT 225 break # node created. 226 } 227 shift 228 } 229 230 ~ $1 () && csaExit.fault 0037 1 makeNode # unable to create new node. 231 232 return 0 233 } 234 235 # ===================================================================== 236 # Initialization section. 237 # ===================================================================== 238 239 if (csaIsWeb) { 240 241 # Our default PRG processor. 242 CSA_PRG_URL = $CSA_RPC_URI/$CSA_LANG/tw-prg 243 244 # This is necessary for cookie-based PRG to work. 245 csaSession.set $CSA_GUID 5 246 247 # Other useful session data. 248 csaSession.set $CSA_PGM($#CSA_PGM) 4 249 250 # Set default value if empty. 251 ~ $CSA_SESSION(19) tag:* || csaSession.set $CSA_GUID 19 immediate 252 253 # Modify some of the URLs if we are running behind SSL (override what 254 # was done by csaCgilib.rc with the original 'csaIsWeb'). 255 256 if (csaIsWeb --ssl) { 257 258 CSA_URL = $CSA_URL2 259 CSA_RPC_URL = $CSA_RPC_URL2 260 CSA_RPC_URI = $CSA_RPC_URI2 261 CSA_RPC_HREF = $CSA_RPC_URI2$PATH_INFO 262 263 # If we are behind stunnel(8) and the transparent proxy 264 # mode is not active, then REMOTE_ADDR will always be 265 # 127.0.0.1 under SSL. To try and get the original client 266 # address I use a session token. 267 268 ~ $CSA_SESSION(3) [1-9]* && REMOTE_ADDR = $CSA_SESSION(3) 269 270 } else { 271 272 # Store REMOTE_ADDR value in a session variable if we are not 273 # behind SSL, i.e. we have not been called by stunnel(8). 274 275 csaSession.set $REMOTE_ADDR 3 276 } 277 } 278 279 # ===================================================================== 280 # Template-related initial defs. 281 # ===================================================================== 282 283 # Set default namespace for XHTML 1.1 284 CSA_XMLNS_DEFAULT = http://www.w3.org/1999/xhtml 285 286 # Set default values for common page variables. 287 288 tpl.if.tw.subcat = '(::DEL:)' 289 tpl.fi.tw.subcat = '(:DEL::)' 290 291 # By default, output is a page, not a view. 292 tpl.if.tw.isview = '(::DEL:)' 293 tpl.fi.tw.isview = '(:DEL::)' 294 tpl.if.tw.ispage = () 295 tpl.fi.tw.ispage = () 296 297 # By default, the page does not refer shop items. 298 tpl.if.tw.shop = '(::DEL:)' 299 tpl.fi.tw.shop = '(:DEL::)' 300 301 # By default, the client isn't global editor. 302 tpl.if.tw.global.editor = '(::DEL:)' 303 tpl.fi.tw.global.editor = '(:DEL::)' 304 305 tpl.var.tw.allow = () 306 tpl.var.tw.arg1 = () 307 tpl.var.tw.arg2 = () 308 tpl.var.tw.arg3 = () 309 tpl.var.tw.arg4 = () 310 tpl.var.tw.arg5 = () 311 tpl.var.tw.arg6 = () 312 tpl.var.tw.author = () 313 tpl.var.tw.auth.email = () 314 tpl.var.tw.user.gravatar = identicon # hard-coded default. 315 tpl.var.tw.auth.group = () 316 tpl.var.tw.auth.gui = () 317 tpl.var.tw.user.email.md5 = () 318 tpl.var.tw.cmt.aumail.md5 = () 319 tpl.var.tw.auth.name = () 320 tpl.var.tw.auth.openid = () 321 tpl.var.tw.cart.more = () 322 tpl.var.tw.cart.total = 0.00 323 tpl.var.tw.ord.total = 0.00 324 tpl.var.tw.chgdate = () 325 tpl.var.tw.chgtime = () 326 tpl.var.tw.date = () 327 tpl.var.tw.descr = () 328 tpl.var.tw.group = () 329 tpl.var.tw.group.unx = () 330 tpl.var.tw.meta = () 331 tpl.var.tw.page = () 332 tpl.var.tw.page.att.count.priv = 0 333 tpl.var.tw.page.cmt.count = 0 334 tpl.var.tw.page.cmt.last = () 335 tpl.var.tw.page.nav = () 336 tpl.var.tw.page.ping.count = 0 337 tpl.var.tw.page.ping.url = () 338 tpl.var.tw.page.rev1 = () 339 tpl.var.tw.page.rev2 = () 340 tpl.var.tw.page.revision = () 341 tpl.var.tw.page.store = () 342 tpl.var.tw.page.subcat = () 343 tpl.var.tw.page.title = () 344 tpl.var.tw.page.unx = () 345 tpl.var.tw.page.vtime = () 346 tpl.var.tw.pager = () 347 tpl.var.tw.paging = () 348 tpl.var.tw.reldate = () 349 tpl.var.tw.time = () 350 tpl.var.tw.url = () 351 352 tpl.var.nls.1 = () 353 354 tpl.var.html.base = $CSA_URL 355 tpl.var.html.title = () 356 tpl.include.html.body = /dev/null 357 tpl.include.nav.next = /dev/null 358 tpl.include.nav.session = /dev/null 359 360 tpl.include.tw.page = /dev/null 361 tpl.include.tw.page2 = /dev/null 362 tpl.include.tw.page.diff1 = /dev/null 363 tpl.include.tw.page.diff2 = /dev/null 364 tpl.include.tw.page.diff3 = /dev/null 365 tpl.include.tw.page.header = /dev/null 366 tpl.include.tw.page.footer = /dev/null 367 tpl.include.tw.page.rdf = /dev/null 368 tpl.include.tw.page.captcha = /dev/null 369 tpl.include.tw.page.meta = /dev/null 370 tpl.include.tw.page.att = /dev/null 371 tpl.include.tw.group.rdf = /dev/null 372 tpl.include.tw.msg = /dev/null 373 tpl.include.tw.recent.links = /dev/null 374 tpl.include.tw.subcat.recent.links = /dev/null 375 tpl.include.tw.recent.cmts = /dev/null 376 tpl.include.tw.related = /dev/null 377 tpl.include.tw.year.links = /dev/null 378 tpl.include.tw.group.cal = /dev/null 379 tpl.include.tw.group.cat = /dev/null 380 tpl.include.tw.group.tag = /dev/null 381 tpl.include.tw.user.gui = /dev/null 382 tpl.include.tw.rpc = /dev/null 383 tpl.include.tw.tpl.ok = $CSA_INSTALL/lib/csaOk.html 384 tpl.include.tw.tpl.fault = $CSA_INSTALL/lib/csaError.html 385 tpl.include.tw.text = /dev/null 386 387 cgi.node.stem = () 388 cgi.node.pbc = () 389 390 CSA_TPL_EVAL = tpl.include.^(html.body nav.^(next session) 391 tw.^((recent subcat.recent year)^.links recent.cmts page 392 page2 text related tpl.^(fault ok) (group page)^.rdf msg 393 rpc group.^(cal cat tag) user.gui page.^(diff^(1 2 3) att 394 header footer captcha meta))) 395 396 TNS_HIST_GOTO = -1 397 TNS_LC_ALL = en_US 398 399 TNS_FORBIDDEN_EXT = () # may be overridden in group+cf 400 401 # Choose a suitable date format to be used in templates. 402 403 switch ($CSA_LANG) { 404 case it* 405 tpl.var.tw.date = \ 406 $CSA_TIME_LOCAL(3)^/$CSA_TIME_LOCAL(2)^/$CSA_TIME_LOCAL(1) 407 case * 408 tpl.var.tw.date = \ 409 $CSA_TIME_LOCAL(2)^/$CSA_TIME_LOCAL(3)^/$CSA_TIME_LOCAL(1) 410 } 411 412 tpl.var.tw.time = $CSA_TIME_LOCAL(4)^:$CSA_TIME_LOCAL(5) 413 414 ~ $CSA_SESSION(17) - && csaSession.set Login 17 immediate 415 416 TNS_AUTH_DISPLAY = $CSA_SESSION(17) 417 418 # If anything from the session file needs to be made available to 419 # '_userproc(_O_REQUEST)' of the called method through 'csaGetArgs', 420 # it can be loaded here as shown. 421 422 authCheck --return # load authentication data. 423 424 # Allow for public read/write on this wiki. This cannot be done with a 425 # profile switch, as csa.rc has not been read at this stage yet. Note 426 # that by setting this value here we are allowing anyone to create new 427 # groups in this wiki. To be more restrictive, this should rather be 428 # set on a per-group basis inside each relevant group.cf file. 429 # 430 #TNS_AUTH_GRP = ,editor, 431 432 CSA_STATUS = 0 # always recommended. 433 434 # End of program.