1 # ===================================================================== 2 # showPage.awk: RPC I/O function for rpclib/showPage. 3 # 4 # Copyright (c) 2007,2008,2009,2010,2012 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 # void _userproc(int mode) 23 # ===================================================================== 24 25 function _userproc(mode, value,fmt1,fmt2,in1,out1,e,f,out2,\ 26 out3,a,i,j,tmp,tmp1,api,tmp2,tmp3) { 27 28 if (mode == _O_REQUEST) { # request. 29 30 # BloggerAPI 1.0 31 if (_request("0_0",1) ~ /^blogger\./) { 32 api = "blogger" 33 bloggerAuth() 34 } 35 36 # MetaWeblog API and derivatives. 37 else if (_request("0_0",1) != _NULL) { 38 api = "mw" 39 # Skip auth checks where appropriate. 40 if (_request("0_0",1) != "mt.getTrackbackPings") 41 bloggerAuth("2_1","3_1","1_1") 42 } 43 44 # target group 45 if ((value=_request("1",1)) == _NULL) { 46 if ((value=_request("p",1)) != _NULL) sub(/\..*/,_NULL,value) 47 } 48 49 # BloggerAPI 1.0 and MetaWeblog API, but also numeric page spec. 50 # Make sure "value" is not casted into "0" here. 51 if (value == _NULL || value ~ /^[1-9][0-9]+$/) { 52 53 # target language/group 54 if (value ~ /^[1-9][0-9]+$/) 55 i=split(value,a,"/") # split on bogus char. 56 else if (api == "blogger") i=split(_request("2_1",1),a,"/") 57 else split(_request("1_1",1),a,"/") # MetaWeblog API (default) 58 59 # Handle numeric target specification. 60 if (a[2] == _NULL && (a[1]/=1)) { 61 tmp = ENVIRON["CSA_ROOT"] "/var/nodes/" \ 62 substr(a[1],1,1) "/" substr(a[1],2,1) "/" \ 63 substr(a[1],3,1) "/" a[1] 64 65 getline value < tmp; close(tmp) 66 split(value,a,/[\/ +]/) 67 68 # Numeric target specs are currently supported only 69 # for pages and comments. 70 71 if (a[4] ~ /^[1-9][0-9]+-/) { 72 _rcset("cgi.item.type","comment") 73 _rcset("cgi.item",a[4]) 74 } 75 76 _rcset("cgi.numeric","on") # tell the caller. 77 } 78 79 if (_LANG[a[1]] != _NULL) _rcset("CSA_LANG",a[1]) 80 81 # Target group name is expected to be a unixified string here. 82 value = a[2] 83 } 84 85 # group must not be null and it may not contain 86 # the ``.'' character. 87 88 if (value != _NULL && value !~ /\./) { 89 _rcset("cgi.group",unixify(value)) 90 _rcset("cgi.group.literal",value) 91 } 92 93 # target page within group; may be null, thus defaulting 94 # to whatever is set in the relevant 'group+cf' file. 95 if ((value=_request("2",1)) == _NULL) { 96 if ((value=_request("p",1)) != _NULL) sub(/[^.]+\./,_NULL,value) 97 else value = a[3] 98 } 99 100 # BloggerAPI 1.0 and MetaWeblog API 101 #if (value == _NULL && _request("0_0",1) != _NULL) value = a[3] 102 103 # page name must be at least 2-character long. 104 if (length(value) > 1) { 105 _rcset("cgi.page.literal",value) 106 value = unixify(value,1) 107 _rcset("cgi.page",value) 108 109 # extract unixified page meta-category if available. 110 if ((value=getcat(value)) != _NULL) _rcset("cgi.subcat",value) 111 } 112 113 # optional author name. 114 if ((value=_request("twauthor",1)) != _NULL) { 115 gsub(/[\t\r\n<>]+/," ",value) 116 _rcset("cgi.author",substr(_strip(value,_O_MIDDLE),1,32)) 117 } 118 119 # Show links to nonexistent pages in the same group ? 120 if ((value=_request("3",1)) == "show") 121 _rcset("cgi.wikilinks","show") 122 123 # Page visual appearance. 124 if ((value=_request("4",1)) ~ /^(screen|print|toc)$/) 125 _rcset("cgi.style",value) 126 127 # Page revision (ISO date) 128 value = _request("5",1) 129 sub(/\+[0-9]+$/,_NULL,value) # Remove TZ if any. 130 if (_isdate(value) == _TRUE) _rcset("cgi.revision",value) 131 132 # The following test is necessary since the address could, 133 # at least in theory, have been set to any string by the 134 # remote user, due to how it is handled to cope with stunnel(8) 135 # and the lack of transproxy support in kernel 2.4.x. 136 137 if (_isipaddr(ENVIRON["REMOTE_ADDR"]) == _TRUE) 138 value = ENVIRON["REMOTE_ADDR"] 139 else value = "0.0.0.0" 140 141 _rcset("REMOTE_ADDR",value) 142 } 143 144 else { # response. 145 146 value = _rcget("tbl_page.p_tags",1) 147 gsub(/g:[-_0-9a-zA-Z.,:;]+/,_NULL,value) # strip geo tag. 148 gsub(/[MT]:[^ ]+ ?/,_NULL,value) # strip local and title tags. 149 gsub(/ +/,", ",value) 150 gsub(/_/," ",value) 151 _response("tpl.var.tw.tags",value) 152 153 # Handle local tag separately. 154 value = _rcget("tbl_page.p_tags",1) 155 #if (!sub(/.* M:/,"M:",value)) sub(/^M:/,"M:",value) 156 sub(/.* M:/,"M:",value); sub(/ .*/,_NULL,value) 157 if (sub(/^M:/,_NULL,value)) _response("tpl.var.tw.tag.my",value) 158 159 value = _rcget("tbl_page.p_mtime",1) 160 split(value,a,/[- :T]/) 161 _response("tpl.var.tw.chgdate",_localdate(a[1] "-" a[2] "-" a[3])) 162 _response("tpl.var.tw.chgtime",a[4]/1 ":" a[5]) 163 164 # This time format is mainly for RPC2 responses. 165 value = _rcget("tbl_page.p_ctime") 166 gsub(/-/,"",value); sub(/ /,"T",value) 167 _response("tpl.var.tw.page.ctime",value) 168 169 value = _rcget("tbl_page.p_creau",1) 170 _response("tpl.var.tw.page.creau",value) 171 172 value = _rcget("tbl_page.p_vtime",1) 173 sub(/^.*,/,"",value) # strip ranking. 174 _response("tpl.var.tw.page.vtime",value) 175 split(value,a,/-/) 176 _response("tpl.include.tw.group.cal",\ 177 _rcget("tw_gstem") "/cal-" a[1] "-" a[2] "+xml") 178 179 value = _rcget("tbl_page.p_link",1) 180 _response("tpl.var.tw.link",value) 181 182 tmp2 = _xmlencode(_rcget("TNS_GROUP_MISC_PROP",2)) 183 if (split(_rcget("tbl_page.p_name",1),a,".") > 1) { 184 tmp = a[1]; tmp1 = a[2] 185 split(_rcget("tbl_page.k_page",1),a,".") 186 value = tmp2 "" tmp "" 189 } 190 191 if (tmp1 != _NULL) value = value tmp2 tmp1 192 else value = value tmp2 _rcget("tbl_page.p_name",1) 193 _response("tpl.var.tw.page.nav",value) 194 195 tmp = tmp1 = tmp2 = _NULL # clear for later. 196 197 # shop-specific template stuff, where applicable. 198 199 if ((value=_rcget("tbl_page.p_store",1)) ~ /^[^:]*:[1-9]/) { 200 201 _response("tpl.if.tw.shop",_NULL) 202 _response("tpl.fi.tw.shop",_NULL) 203 204 # force default unit of measure if missing. 205 if (value ~ /^[^:]+:[^:]+ /) 206 sub (/ /,":" _nlsmap(_NULL,"units") " ",value) 207 208 gsub(/,/,".",value) # fix currencies 209 split(value,a,/[: +]/) 210 211 if (!a[2]) { 212 # min. sellable qty. 213 _response("tpl.var.tw.shop.qmin",\ 214 _nlsmap(_NULL,"n/a","showPage")) 215 216 # selling price. 217 _response("tpl.var.tw.shop.price",\ 218 _nlsmap(_NULL,"n/a","showPage")) 219 220 # list price. 221 _response("tpl.var.tw.shop.price2",\ 222 _nlsmap(_NULL,"n/a","showPage")) 223 224 # Since the item is not available for sale (qty_min=0) 225 # I could disable "tpl.{if,fi}.tw.shop" template conditionals 226 # altogether, but I prefer not to do so and leave this decision 227 # to the site editor, who may want to make the relevant page 228 # hidden by prepending its description with "-", or leave it 229 # visible regardless. Of course any attempt to buy unavailable 230 # items will be refused by the shopping cart processor. 231 } 232 else { 233 _response("tpl.var.tw.shop.qmin",a[2]) 234 _response("tpl.var.tw.shop.price",a[4]) 235 _response("tpl.var.tw.shop.price2",a[5]) 236 } 237 238 # unit of measure 239 _response("tpl.var.tw.shop.unit",a[3]) 240 241 # item code 242 _response("tpl.var.tw.shop.item",a[1]) 243 } 244 245 # set generic template conditionals. 246 ifsections() 247 248 # If none of the above then assume "editor" and show all sections. 249 # This is ok as security policies do not rely on this mechanism, 250 # which is solely a matter of user interface. 251 252 # Default page title to page name and set page subcat name if any. 253 254 value = tmp = _rcget("tpl.var.tw.page",1) 255 256 if ((tmp=getcat(tmp)) != _NULL) { 257 _response("tpl.var.tw.page.subcat",tmp) 258 tmp2 = tmp # save subcat for later. 259 sub(/[^.]+\./,_NULL,value) 260 _html("show","tpl.if.tw.subcat","tpl.fi.tw.subcat") 261 } else _html("hide","tpl.if.tw.subcat","tpl.fi.tw.subcat") 262 263 # Get actual page title from the "T:" special tag if available. 264 tmp = _rcget("tbl_page.p_tags",1) 265 if (sub(/(.* )?T:/,_NULL,tmp)) { 266 sub(/ .*/,_NULL,tmp) 267 gsub(/_+/," ",tmp) 268 if (tmp != _NULL) value = tmp 269 } 270 271 value = _rcget("tbl_group.g_descr") ": " value 272 _response("tpl.var.html.title",value) 273 274 # Set visible page description, stripped of any extra 275 # directives conveyed by the page description field. 276 value = _rcget("tpl.var.tw.descr") 277 sub(/^ *[-!]+ */,_NULL,value) 278 sub(/ *\+\(:redirect .*/,_NULL,value) 279 _response("tpl.var.html.descr",value) 280 281 # build page header. 282 out1 = _rcget("tpl.include.tw.page.header") 283 if (out1 !~ /^\/\.*[a-zA-Z0-9]/) 284 return(_sys("csaExit.fault 0041 tpl.include.tw.page.header")) 285 286 # Set header format string. 287 288 fmt1 = readfmt("tw-page-header") 289 gsub(/%/,"%%",fmt1) # turn plain '%' into '%%'. 290 gsub(/\\/,"\\\\&",fmt1) # turn '\' into '\\'. 291 gsub(/[\n\r]+/,"",fmt1) # just in case. 292 tmp = fmt1 293 294 # Handle custom positioning of output tokens. 295 sub(/.*\[:/,_NULL,tmp); sub(/:].*/,_NULL,tmp) 296 tmp = _strip(tmp,_O_MIDDLE) 297 if (tmp !~ /^[0-3 ]+$/) tmp = "1 2 3" 298 299 # pad missing arg specs with "0". 300 if ((i=split(tmp,f," ")) < 3) { 301 while (i++ <= 3) tmp = tmp " 0" 302 i = split(tmp,f," ") 303 } 304 305 tmp = _NULL 306 307 for (j=1; j<=i; j++) { 308 if (j > 3) break # ignore excess arg specs. 309 if (!sub(//,"%s",fmt1)) fmt1 = fmt1 "" 310 tmp = tmp " " f[j] 311 } 312 313 # encode any extra markers. 314 gsub(//, "\\<tw:s/\\>",fmt1) 315 316 fmt1 = fmt1 "\n" 317 318 split(_strip(tmp),f," "); f[0] = 0 319 320 value = ENVIRON["CSA_TIME_ISO"] 321 sub(/ /,"T",value) 322 gsub(/:/,"_",value) 323 value = _xmlencode(value "." ENVIRON["CSA_RID"]) 324 325 tmp = _rcget("tpl.var.tw.page.vtime") 326 sub(/^.*,/,"",tmp) # strip ranking. 327 if ((tmp=_localdate(tmp,1)) == _NULL) 328 tmp = _localdate(_rcget("tpl.var.tw.chgdate") \ 329 " " _rcget("tpl.var.tw.chgtime"),1) 330 331 split(tmp,a," "); sub(/:..$/,"",a[2]) # retain only HH:MM 332 333 e[0] = _NULL 334 335 e[1] = value 336 e[2] = a[1] 337 e[3] = a[2] 338 printf(fmt1,e[f[1]],e[f[2]],e[f[3]]) > out1 339 340 close(out1) 341 342 # build page footer. 343 out2 = _rcget("tpl.include.tw.page.footer") 344 if (out2 !~ /^\/\.*[a-zA-Z0-9]/) 345 return(_sys("csaExit.fault 0041 tpl.include.tw.page.footer")) 346 347 # Set footer format string. 348 349 fmt2 = readfmt("tw-page-footer") 350 gsub(/%/,"%%",fmt2) # turn plain '%' into '%%'. 351 gsub(/\\/,"\\\\&",fmt2) # turn '\' into '\\'. 352 gsub(/[\n\r]+/,"",fmt2) # just in case. 353 tmp = fmt2 354 355 # Handle custom positioning of output tokens. 356 sub(/.*\[:/,_NULL,tmp); sub(/:].*/,_NULL,tmp) 357 tmp = _strip(tmp,_O_MIDDLE) 358 if (tmp !~ /^[0-2 ]+$/) tmp = "1 2" 359 360 # pad missing arg specs with "0". 361 if ((i=split(tmp,f," ")) < 2) { 362 while (i++ <= 2) tmp = tmp " 0" 363 i = split(tmp,f," ") 364 } 365 366 tmp = _NULL 367 368 for (j=1; j<=i; j++) { 369 if (j > 2) break # ignore excess arg specs. 370 if (!sub(//,"%s",fmt2)) fmt2 = fmt2 "" 371 tmp = tmp " " f[j] 372 } 373 374 # encode any extra markers. 375 gsub(//,"\\<tw:s/\\>",fmt2) 376 377 fmt2 = fmt2 "\n" 378 379 split(_strip(tmp),f," "); f[0] = 0 380 381 value = _rcget("tpl.var.tw.author") 382 if (value == "") value = _nlsmap(_NULL,"anonymous") 383 384 e[1] = _xmlencode(value) 385 e[2] = ENVIRON["CSA_RPC_URI"] "/" ENVIRON["CSA_LANG"] "/" \ 386 _uriencode(_rcget("tpl.var.tw.group",1),_O_PATHINFO) "/" \ 387 _uriencode(_rcget("tpl.var.tw.page",1),_O_PATHINFO) 388 389 printf(fmt2,e[f[1]],e[f[2]]) > out2 390 391 close(out2) 392 393 # Show links to nonexistent wiki pages within the same group. 394 if (_rcget("cgi.wikilinks") != _NULL) { 395 out3 = _rcget("outfile") 396 if (out3 !~ /^\/\.*[a-zA-Z0-9]/) 397 return(_sys("csaExit.fault 0041 outfile")) 398 399 in1 = _rcget("infile") 400 if (in1 !~ /^\/\.*[a-zA-Z0-9]/) 401 return(_sys("csaExit.fault 0041 infile")) 402 403 # Note: newlines MUST be preserved, or "
" sections
   404		 # will no longer work (the extra leading newline should
   405		 # not matter).
   406	
   407		 value = _NULL
   408		 while (getline tmp < in1 > 0) value = value "\n" tmp
   409	
   410		 # We are only concerned with same-group wiki links here,
   411		 # all other URLs will be left alone.
   412	
   413		 tmp = "^(" _escreg(ENVIRON["CSA_CGI_STEM"]) "|" \
   414			   _escreg(ENVIRON["CSA_RPC_URI"]) ")/" \
   415			   _escreg(ENVIRON["CSA_LANG"]) "/"
   416	
   417		 i = split(value,a,/"
   504	
   505		       # Remove any explicit exclusion directive.
   506		       sub(/lt;title> *! */,"lt;title>",tmp1)
   507	
   508		       if (tmp2 != _NULL) tmp1 = tmp1 "<category>" \
   509						_xmlencode(tmp2) "</category>"
   510	
   511		    }
   512	
   513		    else tmp1 = _NULL
   514	
   515		    printf("%s%s",tmp1,value) > out3
   516		 }
   517	
   518		 else {
   519	
   520		    # Save on overhead if there's no RDFa to parse.
   521		    if (value ~ /\(:v-/) {
   522		       if (_rcget("TNS_GROUP_MISC_PROP",4) == "rdfa")
   523				printf("%s",_rdfacpi(_wikicpi(value))) > out3
   524		       else printf("%s",_mfmtcpi(_wikicpi(value))) > out3
   525		    }
   526		    else printf("%s",_wikicpi(value)) > out3
   527		 }
   528		 close(out3)
   529	      }
   530	   }
   531	} 
   532	
   533	# EOF