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