JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
upload.php cleanup: really don't make dot files
[wfpl.git] / encode.php
1 <?php
2
3 # This program is in the public domain within the United States. Additionally,
4 # we waive copyright and related rights in the work worldwide through the CC0
5 # 1.0 Universal public domain dedication, which can be found at
6 # http://creativecommons.org/publicdomain/zero/1.0/
7
8
9 # This file contains basic encodings. These are used by the encoder. You can
10 # specify any template tag to be encoded with this syntax: ~variable encoding~
11 #
12 # this example: <p>~foo html~</p>
13 # will encode foo (using enc_html()) before displaying it, so that characters
14 # such as < will display properly.
15
16 function enc_cap($str) {
17         $str = ucfirst($str);
18         return $str;
19 }
20
21 # quote for placing between single quotes in php
22 function enc_phpsq($str) {
23         $str = str_replace("\\", "\\\\", $str);
24         $str = str_replace("'", "\\'", $str);
25         return $str;
26 }
27
28 function enc_jsdq($str) {
29         $str = enc_sql($str);
30         $str = str_replace("\n", "\\n", $str);
31         $str = str_replace("\r", "\\r", $str);
32         return $str;
33 }
34
35 # encode for putting within double-quotes in SQL
36 function enc_sql($str) {
37         $str = str_replace("\\", "\\\\", $str);
38         $str = str_replace('"', "\\\"", $str);
39         return $str;
40 }
41
42 # Encode for output in html. does nothing with whitespace
43 #
44 # Example: <p>~foo html~</p>
45 function enc_html($str) {
46         $str = str_replace('&', '&amp;', $str);
47         $str = str_replace('<', '&lt;', $str);
48         $str = str_replace('>', '&gt;', $str);
49         return $str;
50 }
51
52 # Encode for output in html. Convert newlines to <br>
53 #
54 # Example: <p>~foo htmlbr~</p>
55 function enc_htmlbr($str) {
56         $str = enc_html($str);
57         $str = str_replace("\n", "<br>\n", $str);
58         return $str;
59 }
60
61 # Encode for output in html. Preserves newlines and indentation by converting
62 # newlines to <br> and spaces/tabs at the begining of lines to &nbsp;s
63 #
64 # Example: <p>~foo htmlbrtab~</p>
65 function enc_htmlbrtab($str) {
66         $str = enc_htmlbr($str);
67         $whitespace_to_nbsp = create_function('$matches', '$count = 0; $chars = str_split($matches[0]); foreach ($chars as $c) { if ($c == " ") { $count += 1; } else if ($c == "\t") { $count += 8; } } return str_repeat("&nbsp;", $count);');
68         $str = preg_replace_callback("|^[ \t]+|m", $whitespace_to_nbsp, $str);
69         return $str;
70 }
71
72 # Encode for output in html. Spaces converted to &nbsp; and \n to <br>
73 #
74 # Example: <option value="12">~foo htmlbrnbsp~</option>
75 function enc_htmlbrnbsp($str) {
76         $str = enc_htmlbr($str);
77         $str = str_replace(' ', '&nbsp;', $str);
78         return $str;
79 }
80
81 # Encode for output in html. Spaces converted to &nbsp;
82 #
83 # Example: <option value="12">~foo htmlnbsp~</option>
84 function enc_htmlnbsp($str) {
85         $str = enc_html($str);
86         $str = str_replace(' ', '&nbsp;', $str);
87         return $str;
88 }
89
90
91 # HTML attribute.
92 #
93 # Example: <input name="foo" value="~foo attr~">
94 function enc_attr($str) {
95         $str = str_replace('&', '&amp;', $str);
96         $str = str_replace('"', '&quot;', $str);
97         return $str;
98 }
99
100 # URI agument value.
101 #
102 # Example:  <a href="http://example.com?foo=~foo url_val attr~">http://example.com?foo=~foo url_val~</a>
103 function enc_url_val($str) {
104         return rawurlencode($str);
105 }
106
107 # FIXME
108 function enc_url_path($str) {
109         $str = rawurlencode($str);
110         $str = str_replace('%2F', '/', $str);
111         return $str;
112 }
113
114
115 # This is a hack to work around html's stupid syntax for checkboxes.
116 #
117 # Place the template marker just before a " somewhere.
118 #
119 # Example: <input type="checkbox" name="foo~foo checked~">
120 function enc_checked($str) {
121         if($str && $str !== 'No' && $str !== 'False' && $str !== 'false') {
122                 return '" checked="checked';
123         } else {
124                 return '';
125         }
126 }
127
128 # normally, checkboxes values from get/post to 0 or 1, and stored in the database this way. enc_yesno() can be used in your templates to display this as "Yes" or "No".
129 # Example template:  Subscribe to mailing list?: ~subscribe yesno~
130 function enc_yesno($str) {
131         if($str && $str !== 'No' && $str !== 'False' && $str !== 'false') {
132                 return 'Yes';
133         } else {
134                 return 'No';
135         }
136 }
137
138
139 # add a tab at the begining of each line
140 function enc_tab($str) {
141         if('' . $str === '') {
142                 return '';
143         }
144         return "\t" . implode("\n\t", explode("\n", $str));
145 }
146
147 function enc_uppercase($str) {
148         return strtoupper($str);
149 }
150 function enc_upper($str) { # depricated
151         return enc_uppercase($str);
152 }
153
154 function enc_lowercase($str) {
155         return strtolower($str);
156 }
157
158 # pass date in the form 2008-05-23
159 # ercodes date as 05/23/2008
160 function enc_mmddyyyy($yyyy_mm_dd) {
161         if($yyyy_mm_dd == '') {
162                 return '';
163         }
164         if(strlen($yyyy_mm_dd) != 10) {
165                 return date('m/d/Y');
166         }
167         return substr($yyyy_mm_dd, 5, 2) . '/' . substr($yyyy_mm_dd, 8, 2) . '/' . substr($yyyy_mm_dd, 0, 4);
168 }
169
170 # depricated. call enc_mmddyyyy() instead
171 function enc_mdy($str) {
172         return enc_mmddyyyy($str);
173 }
174
175 # pass unix timestamp or "2012-12-20 22:23:34"
176 function enc_mmddyyyyhhmm($str) {
177         if(is_numeric($str)) {
178                 return date('m/d/Y g:ia', (int)$str);
179         } else {
180                 return enc_mmddyyyy(substr($str, 0, 10)) . substr($str, 10, 6);
181         }
182 }
183
184 # takes decimal number of hours
185 # returns hh:mm
186 function enc_hhmm($str) {
187         if(strlen($str) == 0) {
188                 return '';
189         }
190         $hours = floor($str);
191         $minutes = round(($str - $hours) * 60);
192         $str = sprintf("%d:%02d", $hours, $minutes);
193         return $str;
194 }
195
196 # takes decimal number of hours
197 # returns hh:mm followed by "am" or "pm" with no space
198 function enc_12hr($str) {
199         if(strlen($str) == 0) {
200                 return '';
201         }
202         $hours = floor($str);
203         $minutes = round(($str - $hours) * 60);
204         $suffix = 'am';
205         if($hours >= 12.0) {
206                 $suffix = 'pm';
207                 if($hours > 12.0) {
208                         $hours -= 12.0;
209                 }
210         }
211         $str = sprintf("%d:%02d", $hours, $minutes);
212         $str .= $suffix;
213         return $str;
214 }
215
216
217
218 # These are depricated! All but PULLDOWN_HASH still work, but you should update your code.
219 define('PULLDOWN_AUTO', 0); define('PULLDOWN_ARRAY', 1); define('PULLDOWN_HASH', 2); define('PULLDOWN_2D', 3);
220
221
222 # call this function before you run() the template so enc_options() knows what
223 # to do
224 #
225 # Parameters:
226 #
227 #   name: the name of the html control
228 #
229 #   options: an array of options to display in the pulldown/selectbox. Each
230 #   element can be either a string, or an array with two elements (first the
231 #   value to post, and second the value to display in the pulldown)
232 #
233 #   multiple: UNTESTED set to true for multiple-select boxes. 
234
235 function pulldown($name, $in_options, $multiple = false) {
236         if($multiple === PULLDOWN_HASH) {
237                 die('Webmaster error: PULLDOWN_HASH is depricated. Pass array(a,b) not a=>b');
238         }
239         if($multiple !== true) {
240                 # Probably due to API change (removing 3rd argument) but don't bother
241                 # emitting a warning, because the above warning handles the only
242                 # important case.
243                 $multiple = false;
244         }
245         $options = array();
246         foreach($in_options as $option) {
247                 if(is_array($option)) {
248                         $options[] = $option;
249                 } else {
250                         $options[] = array($option, $option);
251                 }
252         }
253         $GLOBALS[$name . '_options'] = array(
254                 'options' => $options,
255                 'multiple' => $multiple);
256 }
257
258 # output a bunch of <option> tags
259 function enc_options($values, $name) {
260         if(!isset($GLOBALS[$name . '_options'])) {
261                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
262         }
263         if($GLOBALS[$name . '_options']['multiple']) { # FIXME test this
264                 $values = explode(', ', $values);
265         }
266         return encode_options($values, $GLOBALS[$name . '_options']['options']);
267 }
268
269 # for radios and pulldowns:
270 # pass posted value
271 # returns what the user sees in the pulldown or on the radio button caption
272 function enc_pulled($str, $name) {
273         if(!isset($GLOBALS[$name . '_options'])) {
274                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
275         }
276         foreach($GLOBALS[$name . '_options']['options'] as &$kv) {
277                 if($kv[0] == $str) {
278                         return $kv[1];
279                 }
280         }
281         return $str;
282 }
283
284 function enc_radio_n($str, $name, $n) {
285         if(!isset($GLOBALS[$name . '_options'])) {
286                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
287         }
288
289         if(!isset($GLOBALS[$name . '_options']['options'][$n])) {
290                 die("Template error: pulldown('$name') does not have element # $n");
291         }
292
293         $value = enc_attr($GLOBALS[$name . '_options']['options'][$n][0]);
294
295         if($str === $value) {
296                 $value .= '" checked="checked';
297         }
298
299         return $value;
300 }
301 function enc_radio_0($str, $name) { return enc_radio_n($str, $name, 0); }
302 function enc_radio_1($str, $name) { return enc_radio_n($str, $name, 1); }
303 function enc_radio_2($str, $name) { return enc_radio_n($str, $name, 2); }
304 function enc_radio_3($str, $name) { return enc_radio_n($str, $name, 3); }
305 function enc_radio_4($str, $name) { return enc_radio_n($str, $name, 4); }
306 function enc_radio_5($str, $name) { return enc_radio_n($str, $name, 5); }
307 function enc_radio_6($str, $name) { return enc_radio_n($str, $name, 6); }
308 function enc_radio_7($str, $name) { return enc_radio_n($str, $name, 7); }
309 function enc_radio_8($str, $name) { return enc_radio_n($str, $name, 8); }
310 function enc_radio_9($str, $name) { return enc_radio_n($str, $name, 9); }
311 function enc_radio_10($str, $name) { return enc_radio_n($str, $name, 10); }
312 function enc_radio_11($str, $name) { return enc_radio_n($str, $name, 11); }
313 function enc_radio_12($str, $name) { return enc_radio_n($str, $name, 12); }
314 function enc_radio_13($str, $name) { return enc_radio_n($str, $name, 13); }
315 function enc_radio_14($str, $name) { return enc_radio_n($str, $name, 14); }
316 function enc_radio_15($str, $name) { return enc_radio_n($str, $name, 15); }
317 function enc_radio_16($str, $name) { return enc_radio_n($str, $name, 16); }
318 function enc_radio_17($str, $name) { return enc_radio_n($str, $name, 17); }
319 function enc_radio_18($str, $name) { return enc_radio_n($str, $name, 18); }
320 function enc_radio_19($str, $name) { return enc_radio_n($str, $name, 19); }
321 function enc_radio_20($str, $name) { return enc_radio_n($str, $name, 20); }
322
323
324 function enc_radio_caption_n($str, $name, $n) {
325         if(!isset($GLOBALS[$name . '_options'])) {
326                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
327         }
328
329         if(!isset($GLOBALS[$name . '_options']['options'][$n])) {
330                 die("Template error: pulldown('$name') does not have element #$n");
331         }
332
333         return $GLOBALS[$name . '_options']['options'][$n][1];
334 }
335 function enc_radio_caption_0($str, $name) { return enc_radio_caption_n($str, $name, 0); }
336 function enc_radio_caption_1($str, $name) { return enc_radio_caption_n($str, $name, 1); }
337 function enc_radio_caption_2($str, $name) { return enc_radio_caption_n($str, $name, 2); }
338 function enc_radio_caption_3($str, $name) { return enc_radio_caption_n($str, $name, 3); }
339 function enc_radio_caption_4($str, $name) { return enc_radio_caption_n($str, $name, 4); }
340 function enc_radio_caption_5($str, $name) { return enc_radio_caption_n($str, $name, 5); }
341 function enc_radio_caption_6($str, $name) { return enc_radio_caption_n($str, $name, 6); }
342 function enc_radio_caption_7($str, $name) { return enc_radio_caption_n($str, $name, 7); }
343 function enc_radio_caption_8($str, $name) { return enc_radio_caption_n($str, $name, 8); }
344 function enc_radio_caption_9($str, $name) { return enc_radio_caption_n($str, $name, 9); }
345 function enc_radio_caption_10($str, $name) { return enc_radio_caption_n($str, $name, 10); }
346 function enc_radio_caption_11($str, $name) { return enc_radio_caption_n($str, $name, 11); }
347 function enc_radio_caption_12($str, $name) { return enc_radio_caption_n($str, $name, 12); }
348 function enc_radio_caption_13($str, $name) { return enc_radio_caption_n($str, $name, 13); }
349 function enc_radio_caption_14($str, $name) { return enc_radio_caption_n($str, $name, 14); }
350 function enc_radio_caption_15($str, $name) { return enc_radio_caption_n($str, $name, 15); }
351 function enc_radio_caption_16($str, $name) { return enc_radio_caption_n($str, $name, 16); }
352 function enc_radio_caption_17($str, $name) { return enc_radio_caption_n($str, $name, 17); }
353 function enc_radio_caption_18($str, $name) { return enc_radio_caption_n($str, $name, 18); }
354 function enc_radio_caption_19($str, $name) { return enc_radio_caption_n($str, $name, 19); }
355 function enc_radio_caption_20($str, $name) { return enc_radio_caption_n($str, $name, 20); }
356
357
358 # use this function along with a special template to generate the html for pulldowns and multiple select boxes.
359 #
360 # Parameters:
361 #
362 #    selected: can be a string or (for multiple-selects) an array
363 #
364 #    options: see documentation for pulldown() above
365 function encode_options($selected, $options) {
366         if(!is_array($selected)) {
367                 $selected = array($selected);
368         }
369
370         $out = '';
371         foreach($options as $option) {
372                 list($value, $display) = $option;
373                 $out .= '<option';
374
375                 if(isset($option[2]) && $option[2] == 'disabled') {
376                         $out .= ' disabled';
377                 } elseif(in_array($value, $selected)) {
378                         $out .= ' selected';
379                 }
380
381                 if($value !== $display || strpos($value, ' ') !== false) {
382                         $out .= ' value="';
383                         $out .= enc_attr($value);
384                         $out .= '"';
385                 }
386                         
387                 $out .= '>';
388
389                 $out .= enc_htmlnbsp($display);
390
391                 $out .= "</option>\n";
392         }
393
394         return $out;
395 }
396
397 $GLOBALS['wfpl_states_assoc'] = array(array("AL", "Alabama"), array("AK", "Alaska"), array("AZ", "Arizona"), array("AR", "Arkansas"), array("CA", "California"), array("CO", "Colorado"), array("CT", "Connecticut"), array("DE", "Delaware"), array("FL", "Florida"), array("GA", "Georgia"), array("HI", "Hawaii"), array("ID", "Idaho"), array("IL", "Illinois"), array("IN", "Indiana"), array("IA", "Iowa"), array("KS", "Kansas"), array("KY", "Kentucky"), array("LA", "Louisiana"), array("ME", "Maine"), array("MD", "Maryland"), array("MA", "Massachusetts"), array("MI", "Michigan"), array("MN", "Minnesota"), array("MS", "Mississippi"), array("MO", "Missouri"), array("MT", "Montana"), array("NE", "Nebraska"), array("NV", "Nevada"), array("NH", "New Hampshire"), array("NJ", "New Jersey"), array("NM", "New Mexico"), array("NY", "New York"), array("NC", "North Carolina"), array("ND", "North Dakota"), array("OH", "Ohio"), array("OK", "Oklahoma"), array("OR", "Oregon"), array("PA", "Pennsylvania"), array("RI", "Rhode Island"), array("SC", "South Carolina"), array("SD", "South Dakota"), array("TN", "Tennessee"), array("TX", "Texas"), array("UT", "Utah"), array("VT", "Vermont"), array("VA", "Virginia"), array("WA", "Washington"), array("DC", "Washington, DC"), array("WV", "West Virginia"), array("WI", "Wisconsin"), array("WY", "Wyoming"));
398
399 # display <option>s
400 function enc_states($str) {
401         $ret = '';
402
403         return encode_options($str, $GLOBALS['wfpl_states_assoc']);
404 }
405
406 $GLOBALS['wfpl_provinces_assoc'] = array(array("AB", "Alberta"), array("BC", "British Columbia"), array("MB", "Manitoba"), array("NF", "Newfoundland"), array("NB", "New Brunswick"), array("NS", "Nova Scotia"), array("NT", "Northwest Territories"), array("NU", "Nunavut"), array("ON", "Ontario"), array("PE", "Prince Edward Island"), array("QC", "Quebec"), array("SK", "Saskatchewan"), array("YT", "Yukon Territory"));
407
408 # display <option>s
409 function enc_provinces($str) {
410         $ret = '';
411
412         return encode_options($str, $GLOBALS['wfpl_provinces_assoc']);
413 }
414
415 # returns "odd", then "even", then "odd" etc.
416 function enc_evenodd($values, $name) {
417         if(!isset($GLOBALS['wfpl_even_odds'])) {
418                 $GLOBALS['wfpl_even_odds'] = array();
419         }
420
421         if($GLOBALS['wfpl_even_odds'][$name]) {
422                 $GLOBALS['wfpl_even_odds'][$name] = false;
423                 return 'even';
424         } else {
425                 $GLOBALS['wfpl_even_odds'][$name] = true;
426                 return 'odd';
427         }
428 }
429
430 function wfpl_nth_word($str, $n) {
431         $a = explode(' ', $str);
432         return isset($a[$n]) ? $a[$n] : null;
433 }
434
435 # encoding is a space separated list of:
436 # image_filename width height thumb_filename thumb_width thumb_height
437 function enc_image_src($str) { return wfpl_nth_word($str, 0); }
438 function enc_image_width($str) { return wfpl_nth_word($str, 1); }
439 function enc_image_height($str) { return wfpl_nth_word($str, 2); }
440 function enc_thumb_src($str) { return wfpl_nth_word($str, 3); }
441 function enc_thumb_width($str) { return wfpl_nth_word($str, 4); }
442 function enc_thumb_height($str) { return wfpl_nth_word($str, 5); }
443
444 # example template: Length: ~length html~ day~length s~
445 function enc_s($str) {
446         if($str == '1') {
447                 return '';
448         }
449
450         return 's';
451 }
452
453 # turn http/ftp (s) urls into html links (and encode everything for html)
454 # does not encode without protocol (eg "www.foo.com")
455 # does not linkify email addresses
456 function enc_linkify($str) {
457         $ret = '';
458         $even = true;
459         $pieces = preg_split("/((?:ht|f)tps?:\/\/[^ \,\"\n\r\t<]+)/is", $str, null, PREG_SPLIT_DELIM_CAPTURE);
460         foreach($pieces as $piece) {
461                 if($even) {
462                         $ret .= enc_html($piece);
463                 } else {
464                         $ret .= '<a href="' . enc_attr($piece) . '">' . enc_html($piece) . '</a>';
465                 }
466                 $even = !$even;
467         }
468         return $ret;
469 }
470
471 # turns a filename into the unix timestamp of that files modification date
472 function enc_mtime($dummy, $filename) {
473         $stat = stat($filename);
474         if ($stat === false) {
475                 return '';
476         }
477         return '' . $stat['mtime'];
478 }