PageRenderTime 68ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/emsi/web/cgi-bin/search/searchmods/common.pl

#
Perl | 2687 lines | 2277 code | 348 blank | 62 comment | 161 complexity | 51386317c170751ad58db2cb37c319ff MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. use strict;
  2. sub version_c {
  3. return '2.0.0.0063';
  4. }
  5. =head1 HEAD
  6. Copyright 1997-2003 by Zoltan Milosevic, All Rights Reserved
  7. See http://www.xav.com/scripts/search/ for more information.
  8. If you edit the source code, you'll find it useful to restore the function comments and #&Assert checks:
  9. cd "search/searchmods/powerusr/"
  10. hacksubs.pl build_map
  11. hacksubs.pl restore_comments
  12. hacksubs.pl assert_on
  13. This library, common.pl, contains simple standalone functions which are shared among all modes.
  14. =cut
  15. sub choose_interface_lang {
  16. my ($b_is_admin_rq, $browser_lang, $form_set_lang, $form_p_lang) = @_;
  17. my $options = '';
  18. my $lang = $Rules{'language'};
  19. my $err = '';
  20. Err: {
  21. my %valid;
  22. ($err, $options, %valid) = &get_valid_langs();
  23. next Err if ($err);
  24. last Err if ($b_is_admin_rq);
  25. my $uls = $Rules{'user language selection'};
  26. if (($uls == 1) or ($uls == 3)) {
  27. # detect lang based on browser
  28. my $browser = substr( &query_env('HTTP_ACCEPT_LANGUAGE'), 0, 2 );
  29. # only map non-2-char entries; others pass through
  30. my %fdse_name_map = (
  31. 'en' => 'english',
  32. 'pt' => 'portuguese',
  33. 'fr' => 'french',
  34. 'it' => 'italian',
  35. 'nl' => 'dutch',
  36. 'de' => 'german',
  37. 'es' => 'spanish',
  38. );
  39. $browser = $fdse_name_map{$browser} || $browser;
  40. if ($valid{$browser}) {
  41. $lang = $browser;
  42. }
  43. }
  44. if (($uls == 2) or ($uls == 3)) {
  45. # detect lang from form settings
  46. if (defined($FORM{'set:lang'})) {
  47. $FORM{'p:lang'} = $FORM{'set:lang'};
  48. delete $FORM{'set:lang'};
  49. }
  50. if (($FORM{'p:lang'}) and ($FORM{'p:lang'} =~ m!^(\w+)$!) and ($valid{$1})) {
  51. $lang = $1;
  52. }
  53. }
  54. last Err;
  55. }
  56. return ($err, $options, $lang);
  57. }
  58. sub get_valid_langs {
  59. my %valid = ();
  60. my $err = '';
  61. Err: {
  62. my $cache_string = '';
  63. my $template_time = (stat('templates'))[9];
  64. my $cache = 'valid_languages_cache.txt';
  65. if ((-e $cache) and (-f $cache)) {
  66. ($err, $cache_string) = &ReadFileL( $cache );
  67. next Err if ($err);
  68. my ($cache_version, $cache_build_time, $cache_template_time, %cache_valid) = split(m!\$!, $cache_string);
  69. if (
  70. ($cache_version ne $VERSION)
  71. or
  72. (($private{'script_start_time'} - $cache_build_time) > 86400)
  73. or
  74. ($cache_template_time != $template_time)
  75. ) {
  76. # discard cache
  77. }
  78. else {
  79. %valid = %cache_valid;
  80. last Err;
  81. }
  82. }
  83. # query file system, either because no cache present, or because it has been discarded:
  84. if (opendir(DIR, 'templates')) {
  85. my @folders = sort readdir(DIR);
  86. closedir(DIR);
  87. foreach (@folders) {
  88. next unless (-e "templates/$_/strings.txt");
  89. unless (open(FILE, "<templates/$_/strings.txt" )) {
  90. #$err = "unable to open file '$_/strings.txt' - $!"; next Err;
  91. next;
  92. }
  93. my ($ver, $selfname) = (<FILE>, <FILE>);
  94. close(FILE);
  95. if ($ver =~ m!^VERSION $VERSION!) {
  96. # ok
  97. $selfname =~ s!\r|\n|\015|\012!!sg;
  98. $valid{$_} = $selfname;
  99. }
  100. }
  101. }
  102. # save cache if possible:
  103. $cache_string = join( '$', $VERSION, $private{'script_start_time'}, $template_time, %valid );
  104. if (open(FILE, ">$cache")) {
  105. binmode(FILE);
  106. print FILE $cache_string;
  107. close(FILE);
  108. chmod($private{'file_mask'},$cache);
  109. }
  110. last Err;
  111. }
  112. my $options = '';
  113. foreach (sort keys %valid) {
  114. $options .= qq!<option value="$_">$valid{$_}</option>!;
  115. }
  116. return ($err, $options, %valid);
  117. }
  118. sub rewrite_url {
  119. my ($level, $url) = @_;
  120. my $key = "rewrite_url_" . $level;
  121. unless ($Rules{$key}) {
  122. return $url;
  123. }
  124. # format is b_enabled,p1,p2,comment,b_verbose,
  125. unless ($private{$key}) {
  126. # create a cache copy
  127. my @rules = ();
  128. my $rule;
  129. foreach $rule (split(m!\&!, $Rules{$key})) {
  130. my @fields = split(m!\=!, $rule);
  131. next unless ($fields[0]);
  132. my @rule = ( &ud($fields[1],$fields[2]), $fields[4] );
  133. push(@rules, \@rule);
  134. }
  135. $private{$key} = \@rules;
  136. }
  137. my $p_rules = $private{$key}; # pointer to an array of arrays
  138. my $p_rule;
  139. foreach $p_rule (@$p_rules) {
  140. my $init = $url;
  141. my ($p1, $p2, $b_verbose) = @$p_rule;
  142. #changed 0056; Brian Renken's contrib; rewrite rules now support $1, $2, uc/lc($1)
  143. my @backref = ($url =~ m!$p1!is);
  144. my $count = ($url =~ s!$p1!$p2!isg);
  145. my $i = 0;
  146. my $ref;
  147. foreach $ref (@backref) {
  148. $i++;
  149. $url =~ s!lc\(\$$i\)!lc($ref)!iesg;
  150. $url =~ s!uc\(\$$i\)!uc($ref)!iesg;
  151. $url =~ s!\$$i!$ref!sg;
  152. }
  153. if (($count) and ($b_verbose)) {
  154. my $h_init = &he($init);
  155. print "<p><b>Status:</b> URL rewrite feature has converted $h_init to " . &he($url) . ".</p>\n";
  156. }
  157. }
  158. return $url;
  159. }
  160. sub check_regex {
  161. my ($pattern) = @_;
  162. my $err = '';
  163. Err: {
  164. if ($pattern =~ m!\?\{!) {
  165. $err = &pstr(50,&he($pattern));
  166. next Err;
  167. }
  168. eval '"foo" =~ m!$pattern!;';
  169. if ($@) {
  170. $err = &pstr(51,&he($pattern,$@));
  171. undef($@);
  172. next Err;
  173. }
  174. }
  175. return $err;
  176. }
  177. sub pstr {
  178. local $_ = $str[$_[0]];
  179. my $x = 0;
  180. foreach $x (1..((scalar @_) - 1)) {
  181. my $c = (s!\$s$x!$_[$x]!g);
  182. #&Assert($c != 0);
  183. }
  184. #&Assert( $_ !~ m!\$s\d! );
  185. return $_;
  186. }
  187. sub ppstr {
  188. local $_ = $str[$_[0]];
  189. #&Assert(defined($_));
  190. my $x = 0;
  191. foreach $x (1..((scalar @_) - 1)) {
  192. #&Assert(defined($_[$x]));
  193. my $c = (s!\$s$x!$_[$x]!g);
  194. #&Assert($c != 0);
  195. }
  196. #&Assert( $_ !~ m!\$s\d! );
  197. print;
  198. }
  199. sub pppstr {
  200. local $_ = $str[$_[0]];
  201. my $x = 0;
  202. foreach $x (1..((scalar @_) - 1)) {
  203. my $c = (s!\$s$x!$_[$x]!g);
  204. #&Assert($c != 0);
  205. }
  206. #&Assert( $_ !~ m!\$s\d! );
  207. if ($const{'is_cmd'}) {
  208. print "\n$_\n";
  209. }
  210. else {
  211. print "<p>" . $_ . "</p>\n";
  212. }
  213. }
  214. sub CompressStrip {
  215. local $_ = defined($_[0]) ? $_[0] : '';
  216. $_ = &RawTranslate(" $_ ");
  217. s'\s+' 'og;
  218. eval($const{'code_strip_ignored_words'});
  219. die $@ if $@;
  220. s'\s+' 'og;
  221. s'^ '';
  222. s' $'';
  223. return " $_ ";
  224. }
  225. sub create_conversion_code {
  226. my ($b_verbose) = @_;
  227. my $code = '';
  228. # Format of %charset is { char_number => [ @values, $name ] }
  229. # where @values represents what the character should be converted to under 4 circumstances
  230. # -1 means "strip, is non-word"
  231. # 0 means "leave as is"
  232. # any other string value is the value to be converted to
  233. my %base_charset = (
  234. 9 => [ -1, -1, -1, -1, 'Horizontal tab'],
  235. 10 => [ -1, -1, -1, -1, 'Line feed'],
  236. 13 => [ -1, -1, -1, -1, 'Carriage Return'],
  237. 32 => [ -1, -1, -1, -1, 'Space'],
  238. 33 => [ -1, -1, -1, -1, 'Exclamation mark'],
  239. 34 => [ -1, -1, -1, -1, 'Quotation mark'],
  240. 35 => [ -1, -1, -1, -1, 'Number sign'],
  241. 36 => [ -1, -1, -1, -1, 'Dollar sign'],
  242. 37 => [ -1, -1, -1, -1, 'Percent sign'],
  243. 38 => [ -1, -1, -1, -1, 'Ampersand'],
  244. 39 => [ -1, -1, -1, -1, 'Apostrophe'],
  245. 40 => [ -1, -1, -1, -1, 'Left parenthesis'],
  246. 41 => [ -1, -1, -1, -1, 'Right parenthesis'],
  247. 42 => [ -1, -1, -1, -1, 'Asterisk'],
  248. 43 => [ -1, -1, -1, -1, 'Plus sign'],
  249. 44 => [ -1, -1, -1, -1, 'Comma'],
  250. 45 => [ -1, -1, -1, -1, 'Hyphen'],
  251. 46 => [ -1, -1, -1, -1, 'Period (fullstop)'],
  252. 47 => [ -1, -1, -1, -1, 'Solidus (slash)'],
  253. 48 => [ 0, 0, 0, 0, 'Digit 0'],
  254. 49 => [ 0, 0, 0, 0, 'Digit 1'],
  255. 50 => [ 0, 0, 0, 0, 'Digit 2'],
  256. 51 => [ 0, 0, 0, 0, 'Digit 3'],
  257. 52 => [ 0, 0, 0, 0, 'Digit 4'],
  258. 53 => [ 0, 0, 0, 0, 'Digit 5'],
  259. 54 => [ 0, 0, 0, 0, 'Digit 6'],
  260. 55 => [ 0, 0, 0, 0, 'Digit 7'],
  261. 56 => [ 0, 0, 0, 0, 'Digit 8'],
  262. 57 => [ 0, 0, 0, 0, 'Digit 9'],
  263. 58 => [ -1, -1, -1, -1, 'Colon'],
  264. 59 => [ -1, -1, -1, -1, 'Semicolon'],
  265. 60 => [ -1, -1, -1, -1, 'Less than'],
  266. 61 => [ -1, -1, -1, -1, 'Equals sign'],
  267. 62 => [ -1, -1, -1, -1, 'Greater than'],
  268. 63 => [ -1, -1, -1, -1, 'Question mark'],
  269. 64 => [ -1, -1, -1, -1, 'Commercial at'],
  270. 65 => [ 'a', 0, 'a', 0, 'Capital A'],
  271. 66 => [ 'b', 0, 'b', 0, 'Capital B'],
  272. 67 => [ 'c', 0, 'c', 0, 'Capital C'],
  273. 68 => [ 'd', 0, 'd', 0, 'Capital D'],
  274. 69 => [ 'e', 0, 'e', 0, 'Capital E'],
  275. 70 => [ 'f', 0, 'f', 0, 'Capital F'],
  276. 71 => [ 'g', 0, 'g', 0, 'Capital G'],
  277. 72 => [ 'h', 0, 'h', 0, 'Capital H'],
  278. 73 => [ 'i', 0, 'i', 0, 'Capital I'],
  279. 74 => [ 'j', 0, 'j', 0, 'Capital J'],
  280. 75 => [ 'k', 0, 'k', 0, 'Capital K'],
  281. 76 => [ 'l', 0, 'l', 0, 'Capital L'],
  282. 77 => [ 'm', 0, 'm', 0, 'Capital M'],
  283. 78 => [ 'n', 0, 'n', 0, 'Capital N'],
  284. 79 => [ 'o', 0, 'o', 0, 'Capital O'],
  285. 80 => [ 'p', 0, 'p', 0, 'Capital P'],
  286. 81 => [ 'q', 0, 'q', 0, 'Capital Q'],
  287. 82 => [ 'r', 0, 'r', 0, 'Capital R'],
  288. 83 => [ 's', 0, 's', 0, 'Capital S'],
  289. 84 => [ 't', 0, 't', 0, 'Capital T'],
  290. 85 => [ 'u', 0, 'u', 0, 'Capital U'],
  291. 86 => [ 'v', 0, 'v', 0, 'Capital V'],
  292. 87 => [ 'w', 0, 'w', 0, 'Capital W'],
  293. 88 => [ 'x', 0, 'x', 0, 'Capital X'],
  294. 89 => [ 'y', 0, 'y', 0, 'Capital Y'],
  295. 90 => [ 'z', 0, 'z', 0, 'Capital Z'],
  296. 91 => [ -1, -1, -1, -1, 'Left square bracket'],
  297. 92 => [ -1, -1, -1, -1, 'Reverse solidus (backslash)'],
  298. 93 => [ -1, -1, -1, -1, 'Right square bracket'],
  299. 94 => [ -1, -1, -1, -1, 'Caret'],
  300. 95 => [ -1, -1, -1, -1, 'Horizontal bar (underscore)'],
  301. 96 => [ -1, -1, -1, -1, 'Acute accent'],
  302. 97 => [ 0, 0, 0, 0, 'Small a'],
  303. 98 => [ 0, 0, 0, 0, 'Small b'],
  304. 99 => [ 0, 0, 0, 0, 'Small c'],
  305. 100 => [ 0, 0, 0, 0, 'Small d'],
  306. 101 => [ 0, 0, 0, 0, 'Small e'],
  307. 102 => [ 0, 0, 0, 0, 'Small f'],
  308. 103 => [ 0, 0, 0, 0, 'Small g'],
  309. 104 => [ 0, 0, 0, 0, 'Small h'],
  310. 105 => [ 0, 0, 0, 0, 'Small i'],
  311. 106 => [ 0, 0, 0, 0, 'Small j'],
  312. 107 => [ 0, 0, 0, 0, 'Small k'],
  313. 108 => [ 0, 0, 0, 0, 'Small l'],
  314. 109 => [ 0, 0, 0, 0, 'Small m'],
  315. 110 => [ 0, 0, 0, 0, 'Small n'],
  316. 111 => [ 0, 0, 0, 0, 'Small o'],
  317. 112 => [ 0, 0, 0, 0, 'Small p'],
  318. 113 => [ 0, 0, 0, 0, 'Small q'],
  319. 114 => [ 0, 0, 0, 0, 'Small r'],
  320. 115 => [ 0, 0, 0, 0, 'Small s'],
  321. 116 => [ 0, 0, 0, 0, 'Small t'],
  322. 117 => [ 0, 0, 0, 0, 'Small u'],
  323. 118 => [ 0, 0, 0, 0, 'Small v'],
  324. 119 => [ 0, 0, 0, 0, 'Small w'],
  325. 120 => [ 0, 0, 0, 0, 'Small x'],
  326. 121 => [ 0, 0, 0, 0, 'Small y'],
  327. 122 => [ 0, 0, 0, 0, 'Small z'],
  328. 123 => [ -1, -1, -1, -1, 'Left curly brace'],
  329. 124 => [ -1, -1, -1, -1, 'Vertical bar'],
  330. 125 => [ -1, -1, -1, -1, 'Right curly brace'],
  331. 126 => [ -1, -1, -1, -1, 'Tilde'],
  332. );
  333. my %extended_charset = (
  334. 138 => [ 's', 'S', chr(154), 0, 'Scaron'],
  335. 140 => [ 'oe', 'OE', chr(156), 0, 'OE ligature'],
  336. 142 => [ 'z', 'Z', chr(158), 0, ''],
  337. 154 => [ 's', 's', 0, 0, 'scaron'],
  338. 156 => [ 'oe', 'oe', 0, 0, 'oe ligature'],
  339. 158 => [ 'z', 'z', 0, 0, ''],
  340. 159 => [ 'y', 'Y', chr(255), 0, ''],
  341. 160 => [ -1, -1, -1, -1, 'Nonbreaking space'],
  342. 161 => [ -1, -1, -1, -1, 'Inverted exclamation'],
  343. 162 => [ -1, -1, -1, -1, 'Cent sign'],
  344. 163 => [ -1, -1, -1, -1, 'Pound sterling'],
  345. 164 => [ -1, -1, -1, -1, 'General currency sign'],
  346. 165 => [ -1, -1, -1, -1, 'Yen sign'],
  347. 166 => [ -1, -1, -1, -1, 'Broken vertical bar'],
  348. 167 => [ -1, -1, -1, -1, 'Section sign'],
  349. 168 => [ -1, -1, -1, -1, 'Di?resis / Umlaut'],
  350. 169 => [ -1, -1, -1, -1, 'Copyright'],
  351. 170 => [ -1, -1, -1, -1, 'Feminine ordinal'],
  352. 171 => [ -1, -1, -1, -1, 'Left angle quote, guillemet left'],
  353. 172 => [ -1, -1, -1, -1, 'Not sign'],
  354. 173 => [ -1, -1, -1, -1, 'Soft hyphen'],
  355. 174 => [ -1, -1, -1, -1, 'Registered trademark'],
  356. 175 => [ -1, -1, -1, -1, 'Macron accent'],
  357. 176 => [ -1, -1, -1, -1, 'Degree sign'],
  358. 177 => [ -1, -1, -1, -1, 'Plus or minus'],
  359. 178 => [ -1, -1, -1, -1, 'Superscript 2'],
  360. 179 => [ -1, -1, -1, -1, 'Superscript 3'],
  361. 180 => [ -1, -1, -1, -1, 'Acute accent'],
  362. 181 => [ -1, -1, -1, -1, 'Micro sign'],
  363. 182 => [ -1, -1, -1, -1, 'Paragraph sign'],
  364. 183 => [ -1, -1, -1, -1, 'Middle dot'],
  365. 184 => [ -1, -1, -1, -1, 'Cedilla'],
  366. 185 => [ -1, -1, -1, -1, 'Superscript 1'],
  367. 186 => [ -1, -1, -1, -1, 'Masculine ordinal'],
  368. 187 => [ -1, -1, -1, -1, 'Right angle quote, guillemet right'],
  369. 188 => [ -1, -1, -1, -1, 'Fraction one-fourth'],
  370. 189 => [ -1, -1, -1, -1, 'Fraction one-half'],
  371. 190 => [ -1, -1, -1, -1, 'Fraction three-fourths'],
  372. 191 => [ -1, -1, -1, -1, 'Inverted question mark'],
  373. 192 => [ 'a', 'A', chr(224), 0, 'Capital A, grave accent'],
  374. 193 => [ 'a', 'A', chr(225), 0, 'Capital A, acute accent'],
  375. 194 => [ 'a', 'A', chr(226), 0, 'Capital A, circumflex'],
  376. 195 => [ 'a', 'A', chr(227), 0, 'Capital A, tilde'],
  377. 196 => [ 'ae', 'Ae', chr(228), 0, 'Capital A, diaeresis / umlaut'],
  378. 197 => [ 'a', 'A', chr(229), 0, 'Capital A, ring'],
  379. 198 => [ 'ae', 'AE', chr(230), 0, 'Capital AE ligature'],
  380. 199 => [ 'c', 'c', chr(231), 0, 'Capital C, cedilla'],
  381. 200 => [ 'e', 'E', chr(232), 0, 'Capital E, grave accent'],
  382. 201 => [ 'e', 'E', chr(233), 0, 'Capital E, acute accent'],
  383. 202 => [ 'e', 'E', chr(234), 0, 'Capital E, circumflex'],
  384. 203 => [ 'e', 'E', chr(235), 0, 'Capital E, diaeresis / umlaut'],
  385. 204 => [ 'i', 'I', chr(236), 0, 'Capital I, grave accent'],
  386. 205 => [ 'i', 'I', chr(237), 0, 'Capital I, acute accent'],
  387. 206 => [ 'i', 'I', chr(238), 0, 'Capital I, circumflex'],
  388. 207 => [ 'i', 'I', chr(239), 0, 'Capital I, diaeresis / umlaut'],
  389. 208 => [ 'd', 'D', chr(240), 0, 'Capital Eth, Icelandic'],
  390. 209 => [ 'n', 'N', chr(241), 0, 'Capital N, tilde'],
  391. 210 => [ 'o', 'O', chr(242), 0, 'Capital O, grave accent'],
  392. 211 => [ 'o', 'O', chr(243), 0, 'Capital O, acute accent'],
  393. 212 => [ 'o', 'O', chr(244), 0, 'Capital O, circumflex'],
  394. 213 => [ 'o', 'O', chr(245), 0, 'Capital O, tilde'],
  395. 214 => [ 'oe', 'Oe', chr(246), 0, 'Capital O, diaeresis / umlaut'],
  396. 215 => [ -1, -1, -1, -1, 'Multiply sign'],
  397. 216 => [ 'o', 'O', chr(248), 0, 'Capital O, slash'],
  398. 217 => [ 'u', 'U', chr(249), 0, 'Capital U, grave accent'],
  399. 218 => [ 'u', 'U', chr(250), 0, 'Capital U, acute accent'],
  400. 219 => [ 'u', 'U', chr(251), 0, 'Capital U, circumflex'],
  401. 220 => [ 'ue', 'Ue', chr(252), 0, 'Capital U, diaeresis / umlaut'],
  402. 221 => [ 'y', 'Y', chr(253), 0, 'Capital Y, acute accent'],
  403. 222 => [ 'p', 'P', chr(254), 0, 'Capital Thorn, Icelandic'],
  404. 223 => [ 'ss', 'ss', 0, 0, 'Small sharp s, German sz'],
  405. 224 => [ 'a', 'a', 0, 0, 'Small a, grave accent'],
  406. 225 => [ 'a', 'a', 0, 0, 'Small a, acute accent'],
  407. 226 => [ 'a', 'a', 0, 0, 'Small a, circumflex'],
  408. 227 => [ 'a', 'a', 0, 0, 'Small a, tilde'],
  409. 228 => [ 'ae', 'ae', 0, 0, 'Small a, diaeresis / umlaut'],
  410. 229 => [ 'a', 'a', 0, 0, 'Small a, ring'],
  411. 230 => [ 'ae', 'ae', 0, 0, 'Small ae ligature'],
  412. 231 => [ 'c', 'c', 0, 0, 'Small c, cedilla'],
  413. 232 => [ 'e', 'e', 0, 0, 'Small e, grave accent'],
  414. 233 => [ 'e', 'e', 0, 0, 'Small e, acute accent'],
  415. 234 => [ 'e', 'e', 0, 0, 'Small e, circumflex'],
  416. 235 => [ 'e', 'e', 0, 0, 'Small e, diaeresis / umlaut'],
  417. 236 => [ 'i', 'i', 0, 0, 'Small i, grave accent'],
  418. 237 => [ 'i', 'i', 0, 0, 'Small i, acute accent'],
  419. 238 => [ 'i', 'i', 0, 0, 'Small i, circumflex'],
  420. 239 => [ 'i', 'i', 0, 0, 'Small i, diaeresis / umlaut'],
  421. 240 => [ 'o', 'o', 0, 0, 'Small eth, Icelandic'],
  422. 241 => [ 'n', 'n', 0, 0, 'Small n, tilde'],
  423. 242 => [ 'o', 'o', 0, 0, 'Small o, grave accent'],
  424. 243 => [ 'o', 'o', 0, 0, 'Small o, acute accent'],
  425. 244 => [ 'o', 'o', 0, 0, 'Small o, circumflex'],
  426. 245 => [ 'o', 'o', 0, 0, 'Small o, tilde'],
  427. 246 => [ 'oe', 'oe', 0, 0, 'Small o, diaeresis / umlaut'],
  428. 247 => [ -1, -1, -1, -1, 'Division sign'],
  429. 248 => [ 'o', 'o', 0, 0, 'Small o, slash'],
  430. 249 => [ 'u', 'u', 0, 0, 'Small u, grave accent'],
  431. 250 => [ 'u', 'u', 0, 0, 'Small u, acute accent'],
  432. 251 => [ 'u', 'u', 0, 0, 'Small u, circumflex'],
  433. 252 => [ 'ue', 'ue', 0, 0, 'Small u, diaeresis / umlaut'],
  434. 253 => [ 'y', 'y', 0, 0, 'Small y, acute accent'],
  435. 254 => [ 'p', 'p', 0, 0, 'Small thorn, Icelandic'],
  436. 255 => [ 'y', 'y', 0, 0, 'Small y, diaeresis / umlaut'],
  437. );
  438. =item reserved
  439. The %reserved hash contains the Latin character index of characters that FDSE uses internally to delimit data, including newlines, whitespace, and the equals sign. These characters are *always* stripped from incoming data regardless of locale settings.
  440. =cut
  441. my %reserved = (
  442. 34 => 1,
  443. 38 => 1,
  444. 60 => 1,
  445. 62 => 1,
  446. 9 => 1,
  447. 95 => 1,
  448. 10 => 1,
  449. 13 => 1,
  450. 32 => 1,
  451. 61 => 1,
  452. );
  453. =item named_entities
  454. The %named_entities hash maps HTML entities to their Latin character index.
  455. Numeric formats like "#ddd" and "xHH" are programmatically added to the hash -- there is no need to manually add them.
  456. Named entities which do not map to alphanumeric "word" characters, like "amp", are omitted as an optimization, since those characters are never included in the index.
  457. =cut
  458. my %named_entities = (
  459. '#338' => 140,
  460. '#339' => 156,
  461. '#352' => 138,
  462. '#353' => 154,
  463. 'AElig' => 198,
  464. 'Aacute' => 193,
  465. 'Acirc' => 194,
  466. 'Agrave' => 192,
  467. 'Aring' => 197,
  468. 'Atilde' => 195,
  469. 'Auml' => 196,
  470. 'Ccedil' => 199,
  471. 'ETH' => 208,
  472. 'Eacute' => 201,
  473. 'Ecirc' => 202,
  474. 'Egrave' => 200,
  475. 'Euml' => 203,
  476. 'Iacute' => 205,
  477. 'Icirc' => 206,
  478. 'Igrave' => 204,
  479. 'Iuml' => 207,
  480. 'Ntilde' => 209,
  481. 'OElig' => 140,
  482. 'Oacute' => 211,
  483. 'Ocirc' => 212,
  484. 'Ograve' => 210,
  485. 'Oslash' => 216,
  486. 'Otilde' => 213,
  487. 'Ouml' => 214,
  488. 'Scaron' => 138,
  489. 'THORN' => 222,
  490. 'Uacute' => 218,
  491. 'Ucirc' => 219,
  492. 'Ugrave' => 217,
  493. 'Uuml' => 220,
  494. 'Yacute' => 221,
  495. 'aacute' => 225,
  496. 'acirc' => 226,
  497. 'aelig' => 230,
  498. 'agrave' => 224,
  499. 'aring' => 229,
  500. 'atilde' => 227,
  501. 'auml' => 228,
  502. 'ccedil' => 231,
  503. 'eacute' => 233,
  504. 'ecirc' => 234,
  505. 'egrave' => 232,
  506. 'eth' => 240,
  507. 'euml' => 235,
  508. 'iacute' => 237,
  509. 'icirc' => 238,
  510. 'igrave' => 236,
  511. 'iquest' => 191,
  512. 'iuml' => 239,
  513. 'ntilde' => 241,
  514. 'oacute' => 243,
  515. 'ocirc' => 244,
  516. 'oelig' => 156,
  517. 'ograve' => 242,
  518. 'oslash' => 248,
  519. 'otilde' => 245,
  520. 'ouml' => 246,
  521. 'scaron' => 154,
  522. 'sup1' => 185,
  523. 'sup2' => 178,
  524. 'sup3' => 179,
  525. 'szlig' => 223,
  526. 'thorn' => 254,
  527. 'uacute' => 250,
  528. 'ucirc' => 251,
  529. 'ugrave' => 249,
  530. 'uuml' => 252,
  531. 'yacute' => 253,
  532. 'yuml' => 255,
  533. );
  534. my %entity_name_by_num = ();
  535. %entity_value_by_name = ();
  536. my ($name, $number) = ('', 0);
  537. while (($name, $number) = each %named_entities) {
  538. $entity_name_by_num{ $number } .= "$name ";
  539. $entity_value_by_name{ $name } = chr($number);
  540. }
  541. my %ac_map_cs = ();
  542. my @nonword = ();
  543. my $focus = (2 + (-2 * $Rules{'character conversion: accent insensitive'})) + (1 + (-1 * $Rules{'character conversion: case insensitive'}));
  544. my $chx = 0;
  545. if (not $b_verbose) {
  546. for (my $chx = 255; $chx > 0; $chx--) {
  547. my $ch = chr($chx);
  548. my $value = -1;
  549. if (defined($base_charset{$chx})) {
  550. $value = $base_charset{$chx}[$focus];
  551. }
  552. elsif (defined($extended_charset{$chx})) {
  553. $value = $extended_charset{$chx}[$focus];
  554. }
  555. if ($value eq '-1') {
  556. $nonword[$chx] = 1;
  557. }
  558. elsif ($value ne '0') {
  559. $ac_map_cs{$value} .= $ch;
  560. }
  561. }
  562. }
  563. else {
  564. print <<"EOM";
  565. <table border="1">
  566. <tr>
  567. <th>$str[62]</th>
  568. <th>$str[63]</th>
  569. <th>$str[61]</th>
  570. <th>$str[60]</th>
  571. <th>$str[59]<br />$str[57]</th>
  572. <th>$str[59]<br />$str[56]</th>
  573. <th>$str[58]<br />$str[57]</th>
  574. <th>$str[58]<br />$str[56]</th>
  575. </tr>
  576. EOM
  577. for (my $chx = 255; $chx > 0; $chx--) {
  578. my $ch = chr($chx);
  579. my @data = (-1, -1, -1, -1, 'Unused'); #default
  580. if (defined($base_charset{$chx})) {
  581. for (0..4) {
  582. $data[$_] = $base_charset{$chx}[$_];
  583. }
  584. }
  585. elsif (defined($extended_charset{$chx})) {
  586. for (0..4) {
  587. $data[$_] = $extended_charset{$chx}[$_];
  588. }
  589. }
  590. print qq!<tr><td align="center"><tt>! . substr(1000 + $chx, 1, 3) . qq!</tt></td><td align="center">$data[4]<br /></td><td nowrap="nowrap"><tt>!;
  591. if ($entity_name_by_num{$chx}) {
  592. my @list = split(m!\s+!, $entity_name_by_num{$chx});
  593. my $en;
  594. foreach $en (@list) {
  595. next unless ($en);
  596. print '&' . "amp;$en; - &$en;<br />";
  597. }
  598. }
  599. else {
  600. print "<br />";
  601. }
  602. print qq!</tt></td><td class="fdtan" align="center"><b>! . &he($ch) . "<br /></b></td>";
  603. my $zz = 0;
  604. for $zz (0..3) {
  605. if ($zz == $focus) {
  606. if ($data[$zz] eq '-1') {
  607. print qq!<td align="center" bgcolor="#cccccc">---</td>\n!;
  608. $nonword[$chx] = 1;
  609. }
  610. elsif ($data[$zz] eq '0') {
  611. print qq!<td class="fdtan" align="center"><b>$ch</b></td>\n!;
  612. }
  613. else {
  614. print qq!<td class="fdtan" align="center"><b>$data[$zz]</b></td>\n!;
  615. # format {dest} = {orig orig orig}
  616. $ac_map_cs{$data[$zz]} .= $ch;
  617. }
  618. }
  619. else {
  620. if ($data[$zz] eq '-1') {
  621. print qq!<td align="center"><br /></td>\n!;
  622. }
  623. elsif ($data[$zz] eq '0') {
  624. print qq!<td align="center">$ch</td>\n!;
  625. }
  626. else {
  627. print qq!<td align="center">$data[$zz]</td>\n!;
  628. }
  629. }
  630. }
  631. print "</tr>\n";
  632. next;
  633. }
  634. print '</table>';
  635. }
  636. # build the code to strip spans of non-word characters:
  637. my @kill = ();
  638. foreach (1..255) {
  639. next unless ($nonword[$_]);
  640. push(@kill,quotemeta(chr($_)));
  641. }
  642. my $frag = join("|",@kill);
  643. my $cnw = '';
  644. if ($frag) {
  645. $cnw = "s'($frag)+' 'og;\n";
  646. }
  647. my $ccc = '';
  648. foreach (keys %ac_map_cs) {
  649. my $ch = ();
  650. my @chars = ();
  651. foreach $ch (split(m!!, $ac_map_cs{$_})) {
  652. push(@chars, quotemeta($ch));
  653. }
  654. my $in = join('|',@chars);
  655. if (1 == length($in)) {
  656. $ccc .= "s!$in!$_!og;\n";
  657. }
  658. elsif ($in) {
  659. $ccc .= "s!($in)!$_!og;\n";
  660. }
  661. }
  662. # Add numeric entities for 1..255:
  663. for (1..255) {
  664. next if ($nonword[$_]);
  665. $entity_value_by_name{ "#$_" } = chr($_);
  666. }
  667. @kill = ();
  668. foreach (keys %reserved) {
  669. push(@kill, quotemeta(chr($_)));
  670. }
  671. $frag = join('|', @kill);
  672. my $csr = '';
  673. if ($frag) {
  674. $csr = "s!($frag)+! !sog;\n";
  675. }
  676. #changed 0056 - map %20 to ' ' as very special case to avoid "foo%20bar" from mapping to "foo 20bar"
  677. $code = <<'EOM';
  678. s!\%20! !sg;
  679. # Replace all hex entities:
  680. s!&#x(..);!chr(hex($1))!eisg;
  681. # Replace all numeric and named entities with their single-character equivalent; unknown entities will be replaced with spaces:
  682. s!&(\S+?);!{$entity_value_by_name{$1} || ' '}!esg;
  683. EOM
  684. $code .= $csr;
  685. $code .= $ccc;
  686. $code .= $cnw;
  687. return $code;
  688. }
  689. =item RawTranslate
  690. Usage:
  691. my $lc_ai_string = &RawTranslate($string);
  692. Returns a lowercase, accent-stripped version on its input. Replaces HTML-encoded characters with their ASCII equivalents.
  693. This function is called mainly by &CompressStrip; also by &LoadRules when preparing the code for ignore words.
  694. See http://www.utoronto.ca/webdocs/HTMLdocs/NewHTML/iso_table.html
  695. Dependencies:
  696. Called by: CompressStrip
  697. Called by: LoadRules
  698. Global: %Rules - 1
  699. Dependency: none
  700. =cut
  701. sub RawTranslate {
  702. local $_ = defined($_[0]) ? $_[0] : '';
  703. if (not exists($const{'conversion_code'})) {
  704. $const{'conversion_code'} = &create_conversion_code(0);
  705. }
  706. eval $const{'conversion_code'};
  707. return $_;
  708. }
  709. sub SelectAdEx {
  710. my ($p_terms) = @_;
  711. my @Ads = ('','','','');
  712. my $err = '';
  713. Err: {
  714. last Err if ($const{'mode'} == 3);
  715. my $text = '';
  716. ($err, $text) = &ReadFileL('ads.xml');
  717. next Err if ($err);
  718. my $ads_ver = 1;
  719. if ($text =~ m! version=\"(\d)!s) {
  720. $ads_ver = $1;
  721. }
  722. last Err unless ($text =~ m!<FDSE:Ads placement="(.*?)">(.+)</FDSE:Ads>!s);
  723. my ($master_pos_str, $ads) = ($1, $2);
  724. next unless ($master_pos_str);
  725. my $term_pattern = '';
  726. foreach (@$p_terms) {
  727. $term_pattern .= quotemeta($_) . '|';
  728. }
  729. if ($FORM{'Realm'}) {
  730. $term_pattern .= "realm:$FORM{'Realm'}|";
  731. }
  732. $term_pattern =~ s!\|$!!;
  733. $term_pattern = "($term_pattern)" if ($term_pattern);
  734. my @match_ads = ();
  735. my @all_ads = ();
  736. foreach (split(m!<FDSE:Ad !s, $ads)) {
  737. next unless (m!(.*?)>(.*)</FDSE:Ad>!s);
  738. my %adinfo = ();
  739. $adinfo{'text'} = $2;
  740. my $attributes = $1;
  741. while ($attributes =~ m!^\s*(\S+)\=\"(.*?)\"(.*)$!s) {
  742. $adinfo{$1} = $2;
  743. $attributes = $3;
  744. }
  745. if ($ads_ver > 1) {
  746. foreach (keys %adinfo) {
  747. $adinfo{$_} = &ud($adinfo{$_});
  748. }
  749. }
  750. push(@all_ads, \%adinfo);
  751. }
  752. # for each of 4 positions, select an ad:
  753. my $i = 1;
  754. for ($i = 1; $i < 5; $i++) {
  755. # skip if we've globally decided not to put ads in this position
  756. next unless ($master_pos_str =~ m!$i!);
  757. my ($matchweight, $weight) = (0, 0);
  758. my (@my_ads, @match_ads) = ();
  759. # Select an ad for position $i
  760. my $p_data = ();
  761. foreach $p_data (@all_ads) {
  762. # skip this ad if we've decided to to show it at position $i:
  763. next unless ($$p_data{'placement'} =~ m!$i!);
  764. # ok, do we have search words to work with, and are there keywords with this ad?
  765. my $is_keyword_match = 0;
  766. if (($term_pattern) and ($$p_data{'keywords'})) {
  767. # Is there a keyword match?
  768. if ($$p_data{'keywords'} =~ m!$term_pattern!i) {
  769. $matchweight += $$p_data{'weight'};
  770. push(@match_ads, $p_data);
  771. $is_keyword_match = 1;
  772. }
  773. }
  774. # have they decided that this ad *only* appears for keyword matches?
  775. if (($$p_data{'kw'}) and (not $is_keyword_match)) {
  776. # sorry maybe next time:
  777. next;
  778. }
  779. $weight += $$p_data{'weight'};
  780. push(@my_ads, $p_data);
  781. }
  782. if ($matchweight) {
  783. $weight = $matchweight;
  784. @my_ads = @match_ads;
  785. }
  786. my $num = int($weight * rand());
  787. foreach $p_data (@my_ads) {
  788. $num -= $$p_data{'weight'};
  789. next if ($num > 0);
  790. # Increment the logfile
  791. my $logfile = "ads_hitcount_$$p_data{'ident'}.txt";
  792. my $hits = 0;
  793. if ((not (-e $logfile)) and (open(FILE, ">$logfile" ))) {
  794. print FILE 0;
  795. close(FILE);
  796. }
  797. if (open(FILE, "+<$logfile")) {
  798. $hits = <FILE>;
  799. seek(FILE, 0, 0);
  800. print FILE ++$hits;
  801. close(FILE);
  802. }
  803. $Ads[$i-1] = $$p_data{'text'};
  804. last;
  805. }
  806. }
  807. }
  808. return @Ads;
  809. }
  810. sub PrintTemplate {
  811. my ($b_return_as_string, $file, $language, $p_replace, $p_visited, $p_cache) = @_;
  812. my $return_text = '';
  813. my $err = '';
  814. Err: {
  815. # Initialize:
  816. unless ($p_replace) {
  817. my %hash = ();
  818. $p_replace = \%hash;
  819. }
  820. $$p_replace{'version'} = $VERSION;
  821. unless ($p_visited) {
  822. my %hash = ();
  823. $p_visited = \%hash;
  824. }
  825. my $text = '';
  826. if (($p_cache) and ('HASH' eq ref($p_cache)) and (exists($$p_cache{$file}))) {
  827. $text = $$p_cache{$file};
  828. }
  829. else {
  830. my $fullfile = '';
  831. my $base = "templates/$language/";
  832. my $max_parents = 12;
  833. for (0..$max_parents) {
  834. $fullfile = $base . ('../' x $_) . $file;
  835. $fullfile =~ s!/+!/!g;
  836. last if (-e $fullfile);
  837. }
  838. unless (-e $fullfile) {
  839. $err = "unable to find file '$file'";
  840. next Err;
  841. }
  842. if ($fullfile =~ m!([^\\|/]+)$!) {
  843. $$p_visited{$1}++;
  844. }
  845. ($err, $text) = &ReadFileL($fullfile);
  846. next Err if ($err);
  847. if (($p_cache) and ('HASH' eq ref($p_cache))) {
  848. $$p_cache{$file} = $text;
  849. }
  850. }
  851. #conditionals
  852. foreach (reverse sort keys %$p_replace) {
  853. next unless (defined($_));
  854. $$p_replace{$_} = '' if (not defined($$p_replace{$_}));
  855. if ($$p_replace{$_}) {
  856. # true
  857. $text =~ s!<%\s*if\s+$_\s*%\>(.*?)<%\s*end\s*if\s*%>!$1!isg;
  858. $text =~ s!<%\s*(if\s+not|unless)\s+$_\s*%>.*?<%\s*end\s*if\s*%>!!isg;
  859. }
  860. else {
  861. # false
  862. $text =~ s!<%\s*if\s+$_\s*%>.*?<%\s*end\s*if\s*%>!!isg;
  863. $text =~ s!<%\s*(if\s+not|unless)\s+$_\s*%>(.*?)<%\s*end\s*if\s*%>!$2!isg;
  864. }
  865. }
  866. foreach (reverse sort keys %$p_replace) {
  867. #revcompat
  868. $text =~ s!\$$_!$$p_replace{$_}!isg;
  869. $text =~ s!\_\_$_\_\_!$$p_replace{$_}!isg;
  870. #/revcompat
  871. $text =~ s!\%$_\%!$$p_replace{$_}!isg;
  872. }
  873. my $pattern = '<!--#(include file|include virtual|echo var)=\"(.*?)\" -->';
  874. while ($text =~ m!^(.*?)$pattern(.*)$!is) {
  875. my ($start, $c1, $incfile, $end) = ($1, lc($2), $3, $4);
  876. if ($b_return_as_string) {
  877. $return_text .= $start;
  878. }
  879. else {
  880. print $start;
  881. }
  882. if ($c1 eq 'echo var') {
  883. my $var = uc($incfile);
  884. my $vardata = '';
  885. if ($var eq 'DATE_GMT') {
  886. $vardata = scalar gmtime();
  887. }
  888. elsif ($var eq 'DATE_LOCAL') {
  889. $vardata = scalar localtime();
  890. }
  891. elsif ($var eq 'DOCUMENT_NAME') {
  892. $vardata = $1 if ($0 =~ m!([^\\|/]+)$!);
  893. }
  894. elsif ($var eq 'DOCUMENT_URI') {
  895. $vardata = &query_env('SCRIPT_NAME');
  896. }
  897. elsif ($var eq 'LAST_MODIFIED') {
  898. $vardata = scalar localtime( (stat($0))[9] );
  899. }
  900. elsif (defined($ENV{$var})) {
  901. $vardata = &query_env($var);
  902. }
  903. if ($b_return_as_string) {
  904. $return_text .= $vardata;
  905. }
  906. else {
  907. print $vardata;
  908. }
  909. }
  910. else {
  911. my $basefile = $incfile;
  912. if ($incfile =~ m!.*(\\|/)(.*?)$!) {
  913. $basefile = $2;
  914. }
  915. my $outstr = '';
  916. # Do we have a file extension?
  917. if ($basefile !~ m!\.(txt|htm|html|shtml|stm|inc)$!i) {
  918. $outstr = "<!-- FDSE: not including file '$incfile' because does not have a text/html file extension -->";
  919. }
  920. elsif ($$p_visited{$basefile}) {
  921. $outstr = "<!-- FDSE: loop avoidance: already parsed file '$basefile' -->";
  922. }
  923. else {
  924. $$p_visited{$basefile}++;
  925. $outstr .= &PrintTemplate( $b_return_as_string, $incfile, $language, $p_replace, $p_visited );
  926. }
  927. if ($b_return_as_string) {
  928. $return_text .= $outstr;
  929. }
  930. else {
  931. print $outstr;
  932. }
  933. }
  934. $text = $end;
  935. }
  936. if ($b_return_as_string) {
  937. $return_text .= $text;
  938. }
  939. else {
  940. print $text;
  941. }
  942. last Err;
  943. }
  944. continue {
  945. if ($b_return_as_string) {
  946. $return_text .= &pstr(64,$err);
  947. }
  948. else {
  949. &ppstr(64,$err);
  950. }
  951. }
  952. return $return_text;
  953. }
  954. sub ReadInput {
  955. # Initialize:
  956. %FORM = ();
  957. my @Pairs = ();
  958. if (&query_env('REQUEST_METHOD') eq 'POST') {
  959. my $buffer = '';
  960. read(STDIN, $buffer, &query_env('CONTENT_LENGTH',0));
  961. &untaintme(\$buffer);
  962. @Pairs = split(m!\&!, $buffer);
  963. }
  964. elsif ($ENV{'QUERY_STRING'}) {
  965. @Pairs = split(m!\&!, &query_env('QUERY_STRING'));
  966. }
  967. else {
  968. @Pairs = @ARGV;
  969. }
  970. #changed 0054 - support for multi-select
  971. my ($name, $value);
  972. foreach (@Pairs) {
  973. next unless (m!^(.*?)=(.*)$!);
  974. ($name, $value) = &ud($1,$2);
  975. if (defined($FORM{$name})) {
  976. # multi
  977. $FORM{$name} .= ",$value";
  978. }
  979. else {
  980. $FORM{$name} = $value;
  981. }
  982. }
  983. #changed 0053 - support for undefined-alt-value
  984. foreach (keys %FORM) {
  985. next unless (m!^(.*)_udav$!);
  986. next if (defined($FORM{$1}));
  987. $FORM{$1} = $FORM{$_};
  988. }
  989. $FORM{'Mode'} = '' if (not (defined($FORM{'Mode'})));
  990. }
  991. sub db_exec {
  992. my ($statement) = @_;
  993. my $dbh = undef();
  994. my $sth = undef();
  995. my $err = '';
  996. Err: {
  997. $err = &get_dbh(\$dbh);
  998. next Err if ($err);
  999. unless ($sth = $dbh->prepare($statement)) {
  1000. $err = $str[45] . ' ' . $dbh->errstr();
  1001. next Err;
  1002. }
  1003. unless ($sth->execute()) {
  1004. $err = $str[29] . ' ' . $sth->errstr();
  1005. next Err;
  1006. }
  1007. }
  1008. $sth->finish() if ($sth);
  1009. $dbh->disconnect() if ($dbh);
  1010. return $err;
  1011. }
  1012. sub get_dbh {
  1013. my ($ref_dbh) = @_;
  1014. my $err = '';
  1015. Err: {
  1016. foreach ('database', 'hostname', 'username', 'password') {
  1017. my $var = "sql: $_";
  1018. unless ($Rules{$var}) {
  1019. $err = &pstr(21, $var );
  1020. next Err;
  1021. }
  1022. }
  1023. # load the DBI
  1024. my %rq_mods = (
  1025. 'DBI' => 0.9,
  1026. 'DBD::mysql' => 1,
  1027. );
  1028. my $mod = ();
  1029. foreach $mod ('DBI', 'DBD::mysql') {
  1030. my $dbiver = 0;
  1031. my $code = 'use ' . $mod . '; $dbiver = $' . $mod . '::VERSION; ';
  1032. eval $code;
  1033. if ($@) {
  1034. $err = &pstr(22, $mod, $@ );
  1035. undef($@);
  1036. next Err;
  1037. }
  1038. elsif ($dbiver < $rq_mods{$mod}) {
  1039. $err = &pstr(23, $mod, $dbiver, $rq_mods{$mod} );
  1040. next Err;
  1041. }
  1042. }
  1043. $$ref_dbh = DBI->connect("DBI:mysql:$Rules{'sql: database'}:$Rules{'sql: hostname'}", $Rules{'sql: username'}, $Rules{'sql: password'});
  1044. unless ($$ref_dbh) {
  1045. my $dberr = '';
  1046. $err = $str[20];
  1047. eval '$dberr = DBI->errstr();';
  1048. if ($@) {
  1049. # well, some old DBI versions don't support DBI->errstr()
  1050. undef($@);
  1051. }
  1052. else {
  1053. $err .= ' - ' . $dberr;
  1054. }
  1055. next Err;
  1056. }
  1057. }
  1058. return $err;
  1059. }
  1060. sub Trim {
  1061. local $_ = defined($_[0]) ? $_[0] : '';
  1062. s!^[\r\n\s]+!!o;
  1063. s![\r\n\s]+$!!o;
  1064. return $_;
  1065. }
  1066. sub url_encode {
  1067. local $_ = defined($_[0]) ? $_[0] : '';
  1068. s!([^a-zA-Z0-9_.-])!uc(sprintf("%%%02x", ord($1)))!eg;
  1069. return $_;
  1070. }
  1071. sub ud {
  1072. my @out = @_;
  1073. local $_;
  1074. foreach (@out) {
  1075. next unless (defined($_));
  1076. tr!+! !;
  1077. s!\%([a-fA-F0-9][a-fA-F0-9])!pack('C', hex($1))!eg;
  1078. }
  1079. if ((wantarray) or ($#out > 0)) {
  1080. return @out;
  1081. }
  1082. else {
  1083. return $out[0];
  1084. }
  1085. }
  1086. sub ReadFile {
  1087. my ($file) = @_;
  1088. my ($err, $text) = ('', '');
  1089. Err: {
  1090. my ($BytesToRead, $BytesRead, $obj, $p_rhandle) = (-s $file);
  1091. last Err unless ($BytesToRead);
  1092. $obj = &LockFile_new();
  1093. ($err, $p_rhandle) = $obj->Read($file);
  1094. next Err if ($err);
  1095. $BytesRead = read($$p_rhandle, $text, $BytesToRead);
  1096. $err = $obj->Close();
  1097. next Err if ($err);
  1098. unless ($BytesRead == $BytesToRead) {
  1099. $err = &pstr(47, $file, $BytesRead, $BytesToRead );
  1100. next Err;
  1101. }
  1102. }
  1103. return ($err, $text);
  1104. }
  1105. sub ReadFileL {
  1106. my ($file) = @_;
  1107. my ($err,$text) = ('','');
  1108. Err: {
  1109. unless (open(FILE, "<$file")) {
  1110. $err = &pstr(44,$file,$!);
  1111. next Err;
  1112. }
  1113. unless (binmode(FILE)) {
  1114. $err = &pstr(39,$file,$!);
  1115. next Err;
  1116. }
  1117. $text = join('',<FILE>);
  1118. }
  1119. close(FILE);
  1120. return ($err,$text);
  1121. }
  1122. sub log_search {
  1123. my ($realm, $terms, $rank, $documents_found, $documents_searched) = @_;
  1124. my $err = '';
  1125. Err: {
  1126. last unless ($Rules{'logging: enable'});
  1127. $terms = &he( $terms );
  1128. #changed 0058
  1129. if ($realm eq 'include-by-name') {
  1130. my @realms = ();
  1131. foreach (keys %FORM) {
  1132. next unless (m!^Realm:(.+)$!);
  1133. push(@realms, $1);
  1134. }
  1135. $realm = join('|',sort @realms);
  1136. }
  1137. my $host = &query_env('REMOTE_HOST') || $private{'visitor_ip_addr'} || 'undefined';
  1138. my $time = time();
  1139. my $human_time = &FormatDateTime( $time, 14, 0 );
  1140. if ($Rules{'sql: logfile'}) {
  1141. $terms =~ s!\'!\'\'!g;
  1142. my $query = "INSERT INTO $Rules{'sql: table name: logs'} (visitor_ip, unix_time, human_time, realm, terms, rank, documents_found, documents_searched) VALUES ('$host', $time, now(), '$realm', '$terms', $rank, $documents_found, $documents_searched)";
  1143. $err = &db_exec($query);
  1144. next Err if ($err);
  1145. }
  1146. else {
  1147. my $lang = $Rules{'language'};
  1148. $lang =~ s!\,|\r|\n|\015|\012!!sg;
  1149. my @fields = ($host,$time,$human_time,$realm,$terms,$rank,$documents_found,$documents_searched,$lang);
  1150. #validate/cleanse all fields so as not to corrupt CSV
  1151. foreach (@fields) {
  1152. s!(\,|\s|\r|\n|\015|\012|\")+! !sg;
  1153. }
  1154. my $logline = join(',', @fields) . ",\n";
  1155. $logline =~ s!^(.+?)\,(.*)!$1 ,$2!; # insert space before first comma
  1156. unless (open(LOGFILE, ">>search.log.txt")) {
  1157. $err = &pstr(42,'search.log.txt',$!);
  1158. next Err;
  1159. }
  1160. binmode(LOGFILE);
  1161. print LOGFILE $logline;
  1162. close(LOGFILE);
  1163. chmod($private{'file_mask'},'search.log.txt');
  1164. }
  1165. eval {
  1166. DBMLog: {
  1167. last DBMLog unless ($Rules{'use dbm routines'});
  1168. if (length($terms) > 64) {# prevent overflow in dbm key-value len
  1169. $terms = substr($terms,0,64);
  1170. }
  1171. my (%str_all, %str_t20) = ();
  1172. last DBMLog unless (dbmopen( %str_all, 'dbm_strlog_all', 0666 ));
  1173. my $total = ++$str_all{$terms};
  1174. #maxval
  1175. if (not defined($str_all{'+++'})) {
  1176. $str_all{'+++'} = $total;
  1177. }
  1178. elsif ($total > $str_all{'+++'}) {
  1179. $str_all{'+++'} = $total;
  1180. }
  1181. $str_all{'++'} = time() unless ($str_all{'++'});
  1182. $str_all{'+'} = $str_all{'+'} || 0; # boundary
  1183. last unless ($total >= $str_all{'+'});
  1184. last DBMLog unless ($Rules{'logging: display most popular'});
  1185. dbmopen( %str_t20, 'dbm_strlog_top', 0666 ) || die &pstr( 43, 'dbm_strlog_top', $! );
  1186. $str_t20{'++'} = time() unless ($str_t20{'++'});
  1187. $str_t20{$terms} = $total;
  1188. my $maxval = 0;
  1189. my $count = 0;
  1190. foreach (sort { $str_t20{$b} <=> $str_t20{$a} || $a cmp $b } keys %str_t20) {
  1191. next if (m!^\++$!);
  1192. $count++;
  1193. if ($count > $Rules{'logging: display most popular'}) {
  1194. delete $str_t20{$_};
  1195. }
  1196. else {
  1197. if ($str_t20{$_} > $maxval) {
  1198. $maxval = $str_t20{$_};
  1199. }
  1200. $str_all{'+'} = $str_t20{$_};
  1201. }
  1202. }
  1203. if ($count < $Rules{'logging: display most popular'}) {
  1204. $str_all{'+'} = 0;
  1205. }
  1206. #maxval
  1207. if (not defined($str_t20{'+++'})) {
  1208. $str_t20{'+++'} = $maxval;
  1209. }
  1210. elsif ($maxval > $str_t20{'+++'}) {
  1211. $str_t20{'+++'} = $maxval;
  1212. }
  1213. }
  1214. };
  1215. if ($@) {
  1216. &ppstr(53, &pstr(67, &he($@), "$const{'help_file'}1169.html" ) );
  1217. }
  1218. }
  1219. return $err;
  1220. }
  1221. sub FormatNumber {
  1222. my ( $expression, $decimal_places, $include_leading_digit, $use_parens_for_negative, $group_digits, $euro_style ) = @_;
  1223. my $dec_ch = ($euro_style) ? ',' : '.';
  1224. my $tho_ch = ($euro_style) ? '.' : ',';
  1225. my $qm_dec_ch = quotemeta( $dec_ch );
  1226. local $_ = $expression;
  1227. unless (m!^\-?\d*\.?\d*$!) {
  1228. #print "Warning: arg '$num' isn't numeric.\n";
  1229. $_ = 0;
  1230. }
  1231. my $exp = 1;
  1232. for (1..$decimal_places) {
  1233. $exp *= 10;
  1234. }
  1235. $_ *= $exp;
  1236. $_ = int($_);
  1237. $_ = ($_ / $exp);
  1238. # Add a trailing decimal divider if we don't have one yet
  1239. $_ .= '.' unless (m!\.!);
  1240. # Pad zero'es if appropriate:
  1241. if ($decimal_places) {
  1242. if (m!^(.*)\.(.*)$!) {
  1243. $_ .= '0' x ($decimal_places - length($2));
  1244. }
  1245. }
  1246. # Re-write with localized decimal divider:
  1247. s!\.!$dec_ch!o;
  1248. # Group digits:
  1249. if ($group_digits) {
  1250. while (m!(.*)(\d)(\d\d\d)(\,|\.)(.*)!) {
  1251. $_ = "$1$2$tho_ch$3$4$5";
  1252. }
  1253. }
  1254. if ($include_leading_digit) {
  1255. s!^$qm_dec_ch!0$dec_ch!o;
  1256. }
  1257. # Have we somehow ended up with just a decimal point? Make it zero then:
  1258. if ("foo$_" eq "foo$dec_ch") {
  1259. $_ = "0";
  1260. }
  1261. # Strip trailing decimal point
  1262. s!$qm_dec_ch$!!o;
  1263. if ($use_parens_for_negative) {
  1264. s!^\-(.*)$!\($1\)!o;
  1265. }
  1266. return $_;
  1267. }
  1268. sub FormatDateTime {
  1269. my ($time, $format_type, $b_format_as_gmt) = @_;
  1270. $format_type = 0 unless ($format_type);
  1271. my $date_str = '';
  1272. $time = 0 unless ($time);
  1273. if ($format_type == 13) {
  1274. if ($b_format_as_gmt) {
  1275. $date_str = scalar gmtime( $time );
  1276. }
  1277. else {
  1278. $date_str = scalar localtime( $time );
  1279. }
  1280. }
  1281. else {
  1282. my ($sec, $min, $milhour, $day, $month_index, $year, $weekday_index) = ($b_format_as_gmt) ? gmtime( $time ) : localtime( $time );
  1283. $year += 1900;
  1284. my $ampm = ( $milhour >= 12 ) ? 'PM' : 'AM';
  1285. my $relhour = (($milhour - 1) % 12) + 1;
  1286. my $month = $month_index + 1;
  1287. foreach ($milhour, $relhour, $min, $sec, $month, $day) {
  1288. $_ = "0$_" if (1 == length($_));
  1289. }
  1290. my @MonthNames = (
  1291. $str[8],
  1292. $str[9],
  1293. $str[26],
  1294. $str[32],
  1295. $str[40],
  1296. $str[48],
  1297. $str[36],
  1298. $str[34],
  1299. $str[33],
  1300. $str[31],
  1301. $str[30],
  1302. $str[27],
  1303. );
  1304. my @WeekNames = (
  1305. $str[25],
  1306. $str[24],
  1307. $str[28],
  1308. $str[7],
  1309. $str[6],
  1310. $str[5],
  1311. $str[66],
  1312. );
  1313. my $full_weekday = $WeekNames[$weekday_index];
  1314. my $short_weekday = substr($full_weekday, 0, 3);
  1315. my $full_monthname = $MonthNames[$month_index];
  1316. my $short_monthname = substr($full_monthname, 0, 3); #localize bug?
  1317. if ($format_type == 0) {
  1318. $date_str = "$month/$day/$year $relhour:$min:$sec $ampm";
  1319. }
  1320. elsif ($format_type == 1) {
  1321. $date_str = "$full_weekday, $full_monthname $day, $year";
  1322. }
  1323. elsif ($format_type == 2) {
  1324. $date_str = "$month/$day/$year";
  1325. }
  1326. elsif ($format_type == 3) {
  1327. $date_str = "$relhour:$min:$sec $ampm";
  1328. }
  1329. elsif ($format_type == 4) {
  1330. $date_str = "$milhour:$min";
  1331. }
  1332. elsif ($format_type == 10) {
  1333. $date_str = "$short_weekday $month/$day/$year $relhour:$min:$sec $ampm";
  1334. }
  1335. elsif ($format_type == 11) {
  1336. $date_str = "$short_weekday, $day $short_monthname $year $milhour:$min:$sec -0000";
  1337. }
  1338. elsif ($format_type == 12) {
  1339. $date_str = "$year-$month-$day $milhour:$min:$sec";
  1340. }
  1341. elsif ($format_type == 14) {
  1342. $date_str = "$month/$day/$year $milhour:$min";
  1343. }
  1344. }
  1345. return $date_str;
  1346. }
  1347. sub SetDefaults {
  1348. my ($text, $p_params) = @_;
  1349. # short-circuit:
  1350. if ((ref($p_params) ne 'HASH') or (not (%$p_params))) {
  1351. return $text;
  1352. }
  1353. my @array = split(m!<(INPUT|SELECT|TEXTAREA)([^\>]+?)\>!is, $text);
  1354. my $finaltext = $array[0];
  1355. my $setval;
  1356. my $x = 1;
  1357. for ($x = 1; $x < $#array; $x += 3) {
  1358. my ($uctag, $origtag, $attribs, $trail) = (uc($array[$x]), $array[$x], $array[$x+1] || '', $array[$x+2] || '');
  1359. Tweak: {
  1360. my $tag_name = '';
  1361. if ($attribs =~ m! NAME\s*=\s*\"([^\"]+?)\"!is) {
  1362. $tag_name = $1;
  1363. }
  1364. elsif ($attribs =~ m! NAME\s*=\s*(\S+)!is) {
  1365. $tag_name = $1;
  1366. }
  1367. else {
  1368. # we cannot modify what we do not understand:
  1369. last Tweak;
  1370. }
  1371. last Tweak unless (defined($$p_params{$tag_name}));
  1372. $setval = &he($$p_params{$tag_name});
  1373. if ($uctag eq 'INPUT') {
  1374. # discover VALUE and TYPE
  1375. my $type = 'TEXT';
  1376. if ($attribs =~ m! TYPE\s*=\s*\"([^\"]+?)\"!is) {
  1377. $type = uc($1);
  1378. }
  1379. elsif ($attribs =~ m! TYPE\s*=\s*(\S+)!is) {
  1380. $type = uc($1);
  1381. }
  1382. # discover VALUE and TYPE
  1383. my $value = '';
  1384. if ($attribs =~ m! VALUE\s*=\s*\"([^\"]+?)\"!is) {
  1385. $value = $1;
  1386. }
  1387. elsif ($attribs =~ m! VALUE\s*=\s*(\S+)!is) {
  1388. $value = $1;
  1389. }
  1390. # we can only set values for known types:
  1391. if (($type eq 'RADIO') or ($type eq 'CHECKBOX')) {
  1392. #changed 2001-11-15; strip pre-existing checks
  1393. $attribs =~ s! (checked="checked"|checked)($| )!$2!ois;
  1394. if ($setval eq $value) {
  1395. $attribs = qq! checked="checked"$attribs!;
  1396. }
  1397. }
  1398. elsif (($type eq 'TEXT') or ($type eq 'PASSWORD') or ($type eq 'HIDDEN')) {
  1399. # but only hidden fields if value is null:
  1400. last Tweak if (($type eq 'HIDDEN') and ($value ne ''));
  1401. # replace any existing VALUE tag:
  1402. my $qm_value = quotemeta($value);
  1403. $attribs =~ s! value\s*=\s*\"$qm_value\"! value="$setval"!iso;
  1404. $attribs =~ s! value\s*=\s*$qm_value! value="$setval"!iso;
  1405. # add the tag if it's not present (i.e. if no VALUE was present in original tag)
  1406. my $qm_setval = quotemeta($setval);
  1407. unless ($attribs =~ m! VALUE="$qm_setval"!is) {
  1408. $attribs = " value=\"$setval\"$attribs";
  1409. }
  1410. }
  1411. }
  1412. elsif ($uctag eq 'SELECT') {
  1413. # does not support <OPTION>value syntax, only <OPTION VALUE="value">value
  1414. my $lc_set_value = lc($setval);
  1415. my @frags = ();
  1416. foreach (split(m!<option!is, $trail)) {
  1417. #changed 2001-11-15; strip pre-existing "selected"
  1418. $_ =~ s! (selected|selected="selected")($| )!$2!ois;
  1419. if (m!VALUE\s*=\s*\"(.*?)\"!is) {
  1420. if ($lc_set_value eq lc($1)) {
  1421. $_ = ' selected="selected"' . $_;
  1422. }
  1423. }
  1424. elsif (m!VALUE\s*=\s*(\S+)!is) {
  1425. if ($lc_set_value eq lc($1)) {
  1426. $_ = ' selected="selected"' . $_;
  1427. }
  1428. }
  1429. push(@frags, $_);
  1430. }
  1431. $trail = join('<option', @frags);
  1432. }
  1433. elsif ($uctag eq 'TEXTAREA') {
  1434. $trail =~ s!^.*?</(textarea)>!$setval</$1>!osi;
  1435. }
  1436. last Tweak;
  1437. }
  1438. $finaltext .= "<$origtag$attribs>$trail";
  1439. }
  1440. return $finaltext;
  1441. }
  1442. sub SearchIndexFile {
  1443. my $err = '';
  1444. Err: {
  1445. local $_;
  1446. my ($file, $search_code, $r_pages_searched, $r_hits) = @_;
  1447. my ($obj, $p_rhandle) = ();
  1448. $obj = &LockFile_new();
  1449. ($err, $p_rhandle) = $obj->Read( $file );
  1450. next Err if ($err);
  1451. eval($search_code);
  1452. die $@ if ($@);
  1453. $err = $obj->Close();
  1454. next Err if ($err);
  1455. last Err;
  1456. }
  1457. continue {
  1458. &ppstr(64,$err);
  1459. }
  1460. }
  1461. sub SearchDatabase {
  1462. local $_;
  1463. my $dbh = undef();
  1464. my $sth = undef();
  1465. my ($where_clause, $DocSearch, $r_hits) = @_;
  1466. my @WordCount = ();
  1467. my $pages_searched = 0;
  1468. my $r_pages_searched = \$pages_searched;
  1469. my ($WordMatches, $sort_num, $u, $t, $d, $k, $hdr, $n_context_matches, $context_str, $delta, $text);
  1470. my $err = '';
  1471. Err: {
  1472. my $query = "SELECT * FROM $Rules{'sql: table name: addresses'}";
  1473. if ($where_clause) {
  1474. $query .= ' WHERE ' . $where_clause;
  1475. }
  1476. $err = &get_dbh(\$dbh);
  1477. next Err if ($err);
  1478. unless ($sth = $dbh->prepare($query)) {
  1479. $err = $str[45] . ' ' . $dbh->errstr();
  1480. next Err;
  1481. }
  1482. unless ($sth->execute()) {
  1483. $err = $str[29] . ' ' . $sth->errstr();
  1484. next Err;
  1485. }
  1486. undef($@);
  1487. my $p_data = ();
  1488. while ($p_data = $sth->fetchrow_hashref()) {
  1489. ($err, $_) = &text_record_from_hash( $p_data );
  1490. next if ($err);
  1491. eval($DocSearch);
  1492. die($@) if ($@);
  1493. }
  1494. last Err;
  1495. }
  1496. continue {
  1497. &ppstr(64,$err);
  1498. }
  1499. $sth->finish() if ($sth);
  1500. $dbh->disconnect() if ($dbh);
  1501. }
  1502. sub leadpad {
  1503. my ($expr, $padch, $padlen) = @_;
  1504. if (length($expr) <= $padlen) {
  1505. return ($padch x ($padlen - length($expr))) . $expr;
  1506. }
  1507. else {
  1508. return substr($expr, length($expr) - $padlen, 6);
  1509. }
  1510. }
  1511. sub text_record_from_hash {
  1512. my ($p_pagedata) = @_;
  1513. my ($err, $text_record) = ('', '');
  1514. Err: {
  1515. my @require_fields = ('url', 'promote', 'size', 'title', 'description', 'keywords', 'text', 'links');
  1516. foreach (@require_fields) {
  1517. next if (defined($$p_pagedata{$_}));
  1518. $err = &pstr(21,$_);
  1519. next Err;
  1520. }
  1521. &compress_hash( $p_pagedata );
  1522. $text_record = '';
  1523. foreach ('promote', 'dd', 'mm') {
  1524. $text_record .= &leadpad( $$p_pagedata{$_}, '0', 2 );
  1525. }
  1526. #changed 0053 - not longer forcing size to be 6 digits
  1527. $text_record .= $$p_pagedata{'yyyy'} . $$p_pagedata{'size'};
  1528. foreach ('url', 'title', 'description') {
  1529. $$p_pagedata{$_} =~ s'= '=%20'og;
  1530. }
  1531. $text_record .= ' ' . $$p_pagedata{'lastmodtime'};
  1532. $text_record .= ' ' . $$p_pagedata{'lastindex'};
  1533. $text_record .= ' u= ' . $$p_pagedata{'url'};
  1534. $text_record .= ' t= ' . $$p_pagedata{'title'};
  1535. $text_record .= ' d= ' . $$p_pagedata{'description'};
  1536. $text_record .= ' uM=' . $$p_pagedata{'um'};
  1537. $text_record .= 'uT=' . $$p_pagedata{'ut'};
  1538. $text_record .= 'uD=' . $$p_pagedata{'ud'};
  1539. $text_record .= 'uK=' . $$p_pagedata{'uk'};
  1540. $text_record .= 'h=' . $$p_pagedata{'text'};
  1541. $text_record .= 'l=' . $$p_pagedata{'links'};
  1542. $text_record .= "\n";
  1543. last Err;
  1544. }
  1545. return ($err, $text_record);
  1546. }
  1547. sub compress_hash {
  1548. my ($p_pagedata) = @_;
  1549. return if ($$p_pagedata{'compressed'});
  1550. # Solidify time fields:
  1551. foreach ('lastindex', 'lastmodtime') {
  1552. $$p_pagedata{$_} = time() unless ($$p_pagedata{$_});
  1553. }
  1554. unless (($$p_pagedata{'dd'}) and ($$p_pagedata{'mm'}) and ($$p_pagedata{'yyyy'})) {
  1555. ($$p_pagedata{'dd'}, $$p_pagedata{'mm'}, $$p_pagedata{'yyyy'}) = (localtime($$p_pagedata{'lastmodtime'}))[3..5];
  1556. $$p_pagedata{'yyyy'} += 1900;
  1557. }
  1558. my %pairs = (
  1559. 'um' => 'url',
  1560. 'ut' => 'title',
  1561. 'ud' => 'description',
  1562. 'uk' => 'keywords',
  1563. 'text' => 'text',
  1564. 'links' => 'links',
  1565. );
  1566. my ($name, $value) = ();
  1567. while (($name, $value) = each %pairs) {
  1568. $$p_pagedata{$name} = &CompressStrip($$p_pagedata{$value});
  1569. }
  1570. $$p_pagedata{'compressed'} = 1;
  1571. }
  1572. sub StandardVersion {
  1573. my ($p_search_terms, %pagedata) = @_;
  1574. local $_;
  1575. foreach ('redirector', 'relevance', 'record_realm', 'context') {
  1576. $pagedata{$_} = '' unless (defined($pagedata{$_}));
  1577. }
  1578. unless ((defined($pagedata{'dd'})) and (defined($pagedata{'mm'})) and (defined($pagedata{'yyyy'}))) {
  1579. if ($pagedata{'lastindex'}) {
  1580. ($pagedata{'dd'}, $pagedata{'mm'}, $pagedata{'yyyy'}) = (localtime($pagedata{'lastmodtime'}))[3..5];
  1581. $pagedata{'yyyy'} += 1900;
  1582. }
  1583. }
  1584. $pagedata{'day'} = $pagedata{'dd'};
  1585. $pagedata{'month'} = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$pagedata{'mm'}];
  1586. $pagedata{'year'} = $pagedata{'yyyy'};
  1587. #changed 0056
  1588. $pagedata{'size'} = &FormatNumber( ($pagedata{'size'} + 1023) / 1024, 0, 1, 0, 1, $Rules{'ui: number format'} ) . 'KB';
  1589. if ($p_search_terms) {
  1590. # use two marker chars for start-pattern and end-pattern
  1591. # marker chars are those that are guaranteed to be stripped
  1592. my $sm1 = chr(10);
  1593. my $em1 = chr(13);
  1594. my $sm2 = chr(7);
  1595. my $em2 = chr(8);
  1596. my $Term = '';
  1597. foreach $Term (@$p_search_terms) {
  1598. $Term =~ s!\*!!g; #changed 0054
  1599. my $Temp = quotemeta(&Trim($Term)); #changed 0046
  1600. next if ($Temp =~ m!$sm1|$em1|$sm2|$em2!s);
  1601. $pagedata{'description'} =~ s!($Temp)!$sm1$1$em1!isg;
  1602. $pagedata{'context'} =~ s!($Temp)!$sm2$1$em2!isg;
  1603. }
  1604. $pagedata{'description'} =~ s!$sm1!<b class="hl1">!sg;
  1605. $pagedata{'description'} =~ s!$em1!</b>!sg;
  1606. $pagedata{'context'} =~ s!$sm2!<b class="hl2">!sg;
  1607. $pagedata{'context'} =~ s!$em2!</b>!sg;
  1608. }
  1609. if ($pagedata{'context'}) {
  1610. $pagedata{'context_line'} = "<br /><b>$str[35]:</b> $pagedata{'context'}";
  1611. }
  1612. else {
  1613. $pagedata{'context_line'} = '';
  1614. }
  1615. $pagedata{'admin_options'} = '' unless (defined($pagedata{'admin_options'}));
  1616. $pagedata{'url'} = &rewrite_url( 1, $pagedata{'url'} );
  1617. if ($pagedata{'url'} =~ m!^\w+\://([^/]+)!) {
  1618. $pagedata{'host'} = $1;
  1619. }
  1620. #revcompat - 0033
  1621. $pagedata{'target'} = '';
  1622. #/revcompat
  1623. #changed 0050
  1624. $pagedata{'url_terms'} = &url_encode($const{'terms'});
  1625. $pagedata{'url_url'} = &url_encode($pagedata{'url'});
  1626. $pagedata{'html_url'} = $pagedata{'url'} = &he($pagedata{'url'});
  1627. #changed 0053 - all const avail
  1628. my ($n,$v);

Large files files are truncated, but you can click here to view the full file