JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
a395a10ef3e8558dc23b7a11214e811741b7d89d
[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 function enc_json($str) {
36         return json_encode($str);
37 }
38
39 # encode for putting within double-quotes in SQL
40 function enc_sql($str) {
41         $str = str_replace("\\", "\\\\", $str);
42         $str = str_replace('"', "\\\"", $str);
43         return $str;
44 }
45
46 # Encode for output in html. does nothing with whitespace
47 #
48 # Example: <p>~foo html~</p>
49 function enc_html($str) {
50         $str = str_replace('&', '&amp;', $str);
51         $str = str_replace('<', '&lt;', $str);
52         $str = str_replace('>', '&gt;', $str);
53         return $str;
54 }
55
56 # Encode for output in html. Convert newlines to <br>
57 #
58 # Example: <p>~foo htmlbr~</p>
59 function enc_htmlbr($str) {
60         $str = enc_html($str);
61         $str = str_replace("\n", "<br>\n", $str);
62         return $str;
63 }
64
65 # Encode for output in html. Preserves newlines and indentation by converting
66 # newlines to <br> and spaces/tabs at the begining of lines to &nbsp;s
67 #
68 # Example: <p>~foo htmlbrtab~</p>
69 function enc_htmlbrtab($str) {
70         $str = enc_htmlbr($str);
71         $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);');
72         $str = preg_replace_callback("|^[ \t]+|m", $whitespace_to_nbsp, $str);
73         return $str;
74 }
75
76 # Encode for output in html. Spaces converted to &nbsp; and \n to <br>
77 #
78 # Example: <option value="12">~foo htmlbrnbsp~</option>
79 function enc_htmlbrnbsp($str) {
80         $str = enc_htmlbr($str);
81         $str = str_replace(' ', '&nbsp;', $str);
82         return $str;
83 }
84
85 # Encode for output in html. Spaces converted to &nbsp;
86 #
87 # Example: <option value="12">~foo htmlnbsp~</option>
88 function enc_htmlnbsp($str) {
89         $str = enc_html($str);
90         $str = str_replace(' ', '&nbsp;', $str);
91         return $str;
92 }
93
94
95 # HTML attribute.
96 #
97 # Example: <input name="foo" value="~foo attr~">
98 function enc_attr($str) {
99         $str = str_replace('&', '&amp;', $str);
100         $str = str_replace('"', '&quot;', $str);
101         return $str;
102 }
103
104 # URI agument value.
105 #
106 # Example:  <a href="http://example.com?foo=~foo url_val attr~">http://example.com?foo=~foo url_val~</a>
107 function enc_url_val($str) {
108         return rawurlencode($str);
109 }
110
111 # FIXME
112 function enc_url_path($str) {
113         $str = rawurlencode($str);
114         $str = str_replace('%2F', '/', $str);
115         return $str;
116 }
117
118
119 # This is a hack to work around html's stupid syntax for checkboxes.
120 #
121 # Place the template marker just before a " somewhere.
122 #
123 # Example: <input type="checkbox" name="foo~foo checked~">
124 function enc_checked($str) {
125         if($str && $str !== 'No' && $str !== 'False' && $str !== 'false') {
126                 return '" checked="checked';
127         } else {
128                 return '';
129         }
130 }
131
132 # 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".
133 # Example template:  Subscribe to mailing list?: ~subscribe yesno~
134 function enc_yesno($str) {
135         if($str && $str !== 'No' && $str !== 'False' && $str !== 'false') {
136                 return 'Yes';
137         } else {
138                 return 'No';
139         }
140 }
141
142
143 # add a tab at the begining of each line
144 function enc_tab($str) {
145         if('' . $str === '') {
146                 return '';
147         }
148         return "\t" . implode("\n\t", explode("\n", $str));
149 }
150
151 function enc_uppercase($str) {
152         return strtoupper($str);
153 }
154 function enc_upper($str) { # depricated
155         return enc_uppercase($str);
156 }
157
158 function enc_lowercase($str) {
159         return strtolower($str);
160 }
161
162 # pass date in the form 2008-05-23
163 # ercodes date as 05/23/2008
164 function enc_mmddyyyy($yyyy_mm_dd) {
165         if($yyyy_mm_dd == '') {
166                 return '';
167         }
168         if(strlen($yyyy_mm_dd) != 10) {
169                 return date('m/d/Y');
170         }
171         return substr($yyyy_mm_dd, 5, 2) . '/' . substr($yyyy_mm_dd, 8, 2) . '/' . substr($yyyy_mm_dd, 0, 4);
172 }
173
174 # depricated. call enc_mmddyyyy() instead
175 function enc_mdy($str) {
176         return enc_mmddyyyy($str);
177 }
178
179 # pass unix timestamp or "2012-12-20 22:23:34"
180 function enc_mmddyyyyhhmm($str) {
181         if(is_numeric($str)) {
182                 return date('m/d/Y g:ia', (int)$str);
183         } else {
184                 return enc_mmddyyyy(substr($str, 0, 10)) . substr($str, 10, 6);
185         }
186 }
187
188 # takes decimal number of hours
189 # returns hh:mm
190 function enc_hhmm($str) {
191         if(strlen($str) == 0) {
192                 return '';
193         }
194         $hours = floor($str);
195         $minutes = round(($str - $hours) * 60);
196         $str = sprintf("%d:%02d", $hours, $minutes);
197         return $str;
198 }
199
200 # takes decimal number of hours
201 # returns hh:mm followed by "am" or "pm" with no space
202 function enc_12hr($str) {
203         if(strlen($str) == 0) {
204                 return '';
205         }
206         $hours = floor($str);
207         $minutes = round(($str - $hours) * 60);
208         $suffix = 'am';
209         if($hours >= 12.0) {
210                 $suffix = 'pm';
211                 if($hours > 12.0) {
212                         $hours -= 12.0;
213                 }
214         }
215         $str = sprintf("%d:%02d", $hours, $minutes);
216         $str .= $suffix;
217         return $str;
218 }
219
220
221
222 # These are depricated! All but PULLDOWN_HASH still work, but you should update your code.
223 define('PULLDOWN_AUTO', 0); define('PULLDOWN_ARRAY', 1); define('PULLDOWN_HASH', 2); define('PULLDOWN_2D', 3);
224
225
226 # call this function before you run() the template so enc_options() knows what
227 # to do
228 #
229 # Parameters:
230 #
231 #   name: the name of the html control
232 #
233 #   options: an array of options to display in the pulldown/selectbox. Each
234 #   element can be either a string, or an array with two elements (first the
235 #   value to post, and second the value to display in the pulldown)
236 #
237 #   multiple: UNTESTED set to true for multiple-select boxes. 
238
239 function pulldown($name, $in_options, $multiple = false) {
240         if($multiple === PULLDOWN_HASH) {
241                 die('Webmaster error: PULLDOWN_HASH is depricated. Pass array(a,b) not a=>b');
242         }
243         if($multiple !== true) {
244                 # Probably due to API change (removing 3rd argument) but don't bother
245                 # emitting a warning, because the above warning handles the only
246                 # important case.
247                 $multiple = false;
248         }
249         $options = array();
250         foreach($in_options as $option) {
251                 if(is_array($option)) {
252                         $options[] = $option;
253                 } else {
254                         $options[] = array($option, $option);
255                 }
256         }
257         $GLOBALS[$name . '_options'] = array(
258                 'options' => $options,
259                 'multiple' => $multiple);
260 }
261
262 # output a bunch of <option> tags
263 function enc_options($values, $name) {
264         if(!isset($GLOBALS[$name . '_options'])) {
265                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
266         }
267         if($GLOBALS[$name . '_options']['multiple']) { # FIXME test this
268                 $values = explode(', ', $values);
269         }
270         return encode_options($values, $GLOBALS[$name . '_options']['options']);
271 }
272
273 # for radios and pulldowns:
274 # pass posted value
275 # returns what the user sees in the pulldown or on the radio button caption
276 function enc_pulled($str, $name) {
277         if(!isset($GLOBALS[$name . '_options'])) {
278                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
279         }
280         foreach($GLOBALS[$name . '_options']['options'] as &$kv) {
281                 if($kv[0] == $str) {
282                         return $kv[1];
283                 }
284         }
285         return $str;
286 }
287
288 function enc_radio_n($str, $name, $n) {
289         if(!isset($GLOBALS[$name . '_options'])) {
290                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
291         }
292
293         if(!isset($GLOBALS[$name . '_options']['options'][$n])) {
294                 die("Template error: pulldown('$name') does not have element # $n");
295         }
296
297         $value = enc_attr($GLOBALS[$name . '_options']['options'][$n][0]);
298
299         if($str === $value) {
300                 $value .= '" checked="checked';
301         }
302
303         return $value;
304 }
305 function enc_radio_0($str, $name) { return enc_radio_n($str, $name, 0); }
306 function enc_radio_1($str, $name) { return enc_radio_n($str, $name, 1); }
307 function enc_radio_2($str, $name) { return enc_radio_n($str, $name, 2); }
308 function enc_radio_3($str, $name) { return enc_radio_n($str, $name, 3); }
309 function enc_radio_4($str, $name) { return enc_radio_n($str, $name, 4); }
310 function enc_radio_5($str, $name) { return enc_radio_n($str, $name, 5); }
311 function enc_radio_6($str, $name) { return enc_radio_n($str, $name, 6); }
312 function enc_radio_7($str, $name) { return enc_radio_n($str, $name, 7); }
313 function enc_radio_8($str, $name) { return enc_radio_n($str, $name, 8); }
314 function enc_radio_9($str, $name) { return enc_radio_n($str, $name, 9); }
315 function enc_radio_10($str, $name) { return enc_radio_n($str, $name, 10); }
316 function enc_radio_11($str, $name) { return enc_radio_n($str, $name, 11); }
317 function enc_radio_12($str, $name) { return enc_radio_n($str, $name, 12); }
318 function enc_radio_13($str, $name) { return enc_radio_n($str, $name, 13); }
319 function enc_radio_14($str, $name) { return enc_radio_n($str, $name, 14); }
320 function enc_radio_15($str, $name) { return enc_radio_n($str, $name, 15); }
321 function enc_radio_16($str, $name) { return enc_radio_n($str, $name, 16); }
322 function enc_radio_17($str, $name) { return enc_radio_n($str, $name, 17); }
323 function enc_radio_18($str, $name) { return enc_radio_n($str, $name, 18); }
324 function enc_radio_19($str, $name) { return enc_radio_n($str, $name, 19); }
325 function enc_radio_20($str, $name) { return enc_radio_n($str, $name, 20); }
326
327
328 function enc_radio_caption_n($str, $name, $n) {
329         if(!isset($GLOBALS[$name . '_options'])) {
330                 die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
331         }
332
333         if(!isset($GLOBALS[$name . '_options']['options'][$n])) {
334                 die("Template error: pulldown('$name') does not have element #$n");
335         }
336
337         return $GLOBALS[$name . '_options']['options'][$n][1];
338 }
339 function enc_radio_caption_0($str, $name) { return enc_radio_caption_n($str, $name, 0); }
340 function enc_radio_caption_1($str, $name) { return enc_radio_caption_n($str, $name, 1); }
341 function enc_radio_caption_2($str, $name) { return enc_radio_caption_n($str, $name, 2); }
342 function enc_radio_caption_3($str, $name) { return enc_radio_caption_n($str, $name, 3); }
343 function enc_radio_caption_4($str, $name) { return enc_radio_caption_n($str, $name, 4); }
344 function enc_radio_caption_5($str, $name) { return enc_radio_caption_n($str, $name, 5); }
345 function enc_radio_caption_6($str, $name) { return enc_radio_caption_n($str, $name, 6); }
346 function enc_radio_caption_7($str, $name) { return enc_radio_caption_n($str, $name, 7); }
347 function enc_radio_caption_8($str, $name) { return enc_radio_caption_n($str, $name, 8); }
348 function enc_radio_caption_9($str, $name) { return enc_radio_caption_n($str, $name, 9); }
349 function enc_radio_caption_10($str, $name) { return enc_radio_caption_n($str, $name, 10); }
350 function enc_radio_caption_11($str, $name) { return enc_radio_caption_n($str, $name, 11); }
351 function enc_radio_caption_12($str, $name) { return enc_radio_caption_n($str, $name, 12); }
352 function enc_radio_caption_13($str, $name) { return enc_radio_caption_n($str, $name, 13); }
353 function enc_radio_caption_14($str, $name) { return enc_radio_caption_n($str, $name, 14); }
354 function enc_radio_caption_15($str, $name) { return enc_radio_caption_n($str, $name, 15); }
355 function enc_radio_caption_16($str, $name) { return enc_radio_caption_n($str, $name, 16); }
356 function enc_radio_caption_17($str, $name) { return enc_radio_caption_n($str, $name, 17); }
357 function enc_radio_caption_18($str, $name) { return enc_radio_caption_n($str, $name, 18); }
358 function enc_radio_caption_19($str, $name) { return enc_radio_caption_n($str, $name, 19); }
359 function enc_radio_caption_20($str, $name) { return enc_radio_caption_n($str, $name, 20); }
360
361
362 # use this function along with a special template to generate the html for pulldowns and multiple select boxes.
363 #
364 # Parameters:
365 #
366 #    selected: can be a string or (for multiple-selects) an array
367 #
368 #    options: see documentation for pulldown() above
369 function encode_options($selected, $options) {
370         if(!is_array($selected)) {
371                 $selected = array($selected);
372         }
373
374         $out = '';
375         foreach($options as $option) {
376                 list($value, $display) = $option;
377                 $out .= '<option';
378
379                 if(isset($option[2]) && $option[2] == 'disabled') {
380                         $out .= ' disabled';
381                 } elseif(in_array($value, $selected)) {
382                         $out .= ' selected';
383                 }
384
385                 if($value !== $display || strpos($value, ' ') !== false) {
386                         $out .= ' value="';
387                         $out .= enc_attr($value);
388                         $out .= '"';
389                 }
390                         
391                 $out .= '>';
392
393                 $out .= enc_htmlnbsp($display);
394
395                 $out .= "</option>\n";
396         }
397
398         return $out;
399 }
400
401 $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"));
402
403 # display <option>s
404 function enc_states($str) {
405         $ret = '';
406
407         return encode_options($str, $GLOBALS['wfpl_states_assoc']);
408 }
409
410 $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"));
411
412 # display <option>s
413 function enc_provinces($str) {
414         $ret = '';
415
416         return encode_options($str, $GLOBALS['wfpl_provinces_assoc']);
417 }
418
419 # returns "odd", then "even", then "odd" etc.
420 function enc_evenodd($values, $name) {
421         if(!isset($GLOBALS['wfpl_even_odds'])) {
422                 $GLOBALS['wfpl_even_odds'] = array();
423         }
424
425         if($GLOBALS['wfpl_even_odds'][$name]) {
426                 $GLOBALS['wfpl_even_odds'][$name] = false;
427                 return 'even';
428         } else {
429                 $GLOBALS['wfpl_even_odds'][$name] = true;
430                 return 'odd';
431         }
432 }
433
434 function wfpl_nth_word($str, $n) {
435         $a = explode(' ', $str);
436         return isset($a[$n]) ? $a[$n] : null;
437 }
438
439 # encoding is a space separated list of:
440 # image_filename width height thumb_filename thumb_width thumb_height
441 function enc_image_src($str) { return wfpl_nth_word($str, 0); }
442 function _enc_image_src_at_width($str, $width) {
443         $src = enc_image_src($str);
444         if ($src) {
445                 return
446                         substr($src, 0, -4)
447                         . 'w'
448                         . $width
449                         . substr($src, -4);
450         }
451         return '';
452 }
453 # define these width constants in your config.php
454 function enc_image_src_full($str) { return _enc_image_src_at_width($str, WFPL_IMAGE_WIDTH_FULL); }
455 function enc_image_src_small($str) { return _enc_image_src_at_width($str, WFPL_IMAGE_WIDTH_SMALL); }
456 function enc_image_src_thumb($str) { return _enc_image_src_at_width($str, WFPL_IMAGE_WIDTH_THUMB); }
457 function enc_image_width($str) { return wfpl_nth_word($str, 1); }
458 function enc_image_height($str) { return wfpl_nth_word($str, 2); }
459 function enc_image_aspect($str) {
460         $a = explode(' ', $str);
461         if (count($a) < 3) {
462                 return '';
463         }
464         return ''.(round(100000 * ((int)$a[2]) / ((int)$a[1]) / 1000)).'%';
465 }
466 # obsolete:
467 function enc_thumb_src($str) { return wfpl_nth_word($str, 3); }
468 function enc_thumb_width($str) { return wfpl_nth_word($str, 4); }
469 function enc_thumb_height($str) { return wfpl_nth_word($str, 5); }
470
471 # example template: Length: ~length html~ day~length s~
472 function enc_s($str) {
473         if($str == '1') {
474                 return '';
475         }
476
477         return 's';
478 }
479
480 # turn http/ftp (s) urls into html links (and encode everything for html)
481 # does not encode without protocol (eg "www.foo.com")
482 # does not linkify email addresses
483 function enc_linkify($str) {
484         $ret = '';
485         $even = true;
486         $pieces = preg_split("/((?:ht|f)tps?:\/\/[^ \,\"\n\r\t<]+)/is", $str, null, PREG_SPLIT_DELIM_CAPTURE);
487         foreach($pieces as $piece) {
488                 if($even) {
489                         $ret .= enc_html($piece);
490                 } else {
491                         $ret .= '<a href="' . enc_attr($piece) . '">' . enc_html($piece) . '</a>';
492                 }
493                 $even = !$even;
494         }
495         return $ret;
496 }
497
498 # turns a filename into the unix timestamp of that files modification date
499 function enc_mtime($dummy, $filename) {
500         $stat = stat($filename);
501         if ($stat === false) {
502                 return '';
503         }
504         return '' . $stat['mtime'];
505 }