JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
clean up my urls
[wfpl.git] / encode.php
index c3c71a7..9a9bdbc 100644 (file)
@@ -2,26 +2,56 @@
 
 #  Copyright (C) 2005 Jason Woofenden
 #
-#  This file is part of wfpl.
-#
-#  wfpl is free software; you can redistribute it and/or modify it
-#  under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2, or (at your option)
-#  any later version.
-#
-#  wfpl is distributed in the hope that it will be useful, but
-#  WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  General Public License for more details.
-#
+#  This program is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  
 #  You should have received a copy of the GNU General Public License
-#  along with wfpl; see the file COPYING.  If not, write to the
-#  Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-#  MA 02111-1307, USA.
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
-# This file contains basic encodings
+# This file contains basic encodings. These are used by the encoder. You can
+# specify any template tag to be encoded with this syntax: ~variable encoding~
+#
+# this example: <p>~foo html~</p>
+# will encode foo (using enc_html()) before displaying it, so that characters
+# such as < will display properly.
 
+function enc_cap($str) {
+       $str = ucfirst($str);
+       return $str;
+}
+
+# quote for placing between single quotes in php
+function enc_phpsq($str) {
+       $str = str_replace("\\", "\\\\", $str);
+       $str = str_replace("'", "\\'", $str);
+       return $str;
+}
+
+function enc_jsdq($str) {
+       $str = enc_sql($str);
+       $str = str_replace("\n", "\\n", $str);
+       $str = str_replace("\r", "\\r", $str);
+       return $str;
+}
+
+# encode for putting within double-quotes in SQL
+function enc_sql($str) {
+       $str = str_replace("\\", "\\\\", $str);
+       $str = str_replace('"', "\\\"", $str);
+       return $str;
+}
+
+# Encode for output in html. does nothing with whitespace
+#
+# Example: <p>~foo html~</p>
 function enc_html($str) {
        $str = str_replace('&', '&amp;', $str);
        $str = str_replace('<', '&lt;', $str);
@@ -29,21 +59,419 @@ function enc_html($str) {
        return $str;
 }
 
+# Encode for output in html. Convert newlines to <br>
+#
+# Example: <p>~foo htmlbr~</p>
+function enc_htmlbr($str) {
+       $str = enc_html($str);
+       $str = str_replace("\n", "<br>\n", $str);
+       return $str;
+}
+
+# Encode for output in html. Preserves newlines and indentation by converting
+# newlines to <br> and spaces/tabs at the begining of lines to &nbsp;s
+#
+# Example: <p>~foo htmlbrtab~</p>
+function enc_htmlbrtab($str) {
+       $str = enc_htmlbr($str);
+       $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);');
+       $str = preg_replace_callback("|^[ \t]+|m", $whitespace_to_nbsp, $str);
+       return $str;
+}
+
+# Encode for output in html. Spaces converted to &nbsp; and \n to <br>
+#
+# Example: <option value="12">~foo htmlbrnbsp~</option>
+function enc_htmlbrnbsp($str) {
+       $str = enc_htmlbr($str);
+       $str = str_replace(' ', '&nbsp;', $str);
+       return $str;
+}
+
+# Encode for output in html. Spaces converted to &nbsp;
+#
+# Example: <option value="12">~foo htmlnbsp~</option>
+function enc_htmlnbsp($str) {
+       $str = enc_html($str);
+       $str = str_replace(' ', '&nbsp;', $str);
+       return $str;
+}
 
-# html attributes (eg  <input value="...."
+
+# HTML attribute.
+#
+# Example: <input name="foo" value="~foo attr~">
 function enc_attr($str) {
        $str = str_replace('&', '&amp;', $str);
        $str = str_replace('"', '&quot;', $str);
        return $str;
 }
 
-# this is a stupid hack to work around html's stupid syntax for checkboxes
+# URI agument value.
+#
+# Example:  <a href="http://example.com?foo=~foo url_val attr~">http://example.com?foo=~foo url_val~</a>
+function enc_url_val($str) {
+       return rawurlencode($str);
+}
+
+# FIXME
+function enc_url_path($str) {
+       $str = rawurlencode($str);
+       $str = str_replace('%2F', '/', $str);
+       return $str;
+}
+
+
+# This is a hack to work around html's stupid syntax for checkboxes.
+#
+# Place the template marker just before a " somewhere.
+#
+# Example: <input type="checkbox" name="foo~foo checked~">
 function enc_checked($str) {
-       if($str == 'Yes') {
+       if($str && $str !== 'No' && $str !== 'False' && $str !== 'false') {
                return '" checked="checked';
        } else {
                return '';
        }
 }
-       
 
+# 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".
+# Example template:  Subscribe to mailing list?: ~subscribe yesno~
+function enc_yesno($str) {
+       if($str && $str !== 'No' && $str !== 'False' && $str !== 'false') {
+               return 'Yes';
+       } else {
+               return 'No';
+       }
+}
+
+
+# add a tab at the begining of each line
+function enc_tab($str) {
+       if('' . $str === '') {
+               return '';
+       }
+       return "\t" . implode("\n\t", explode("\n", $str));
+}
+
+function enc_uppercase($str) {
+       return strtoupper($str);
+}
+function enc_upper($str) { # depricated
+       return enc_uppercase($str);
+}
+
+function enc_lowercase($str) {
+       return strtolower($str);
+}
+
+# pass date in the form 2008-05-23
+# ercodes date as 05/23/2008
+function enc_mmddyyyy($yyyy_mm_dd) {
+       if($yyyy_mm_dd == '') {
+               return '';
+       }
+       if(strlen($yyyy_mm_dd) != 10) {
+               return date('m/d/Y');
+       }
+       return substr($yyyy_mm_dd, 5, 2) . '/' . substr($yyyy_mm_dd, 8, 2) . '/' . substr($yyyy_mm_dd, 0, 4);
+}
+
+# depricated. call enc_mmddyyyy() instead
+function enc_mdy($str) {
+       return enc_mmddyyyy($str);
+}
+
+# pass unix timestamp or "2012-12-20 22:23:34"
+function enc_mmddyyyyhhmm($str) {
+       if(is_numeric($str)) {
+               return date('m/d/Y g:ia', (int)$str);
+       } else {
+               return enc_mmddyyyy(substr($str, 0, 10)) . substr($str, 10, 6);
+       }
+}
+
+# takes decimal number of hours
+# returns hh:mm
+function enc_hhmm($str) {
+       if(strlen($str) == 0) {
+               return '';
+       }
+       $hours = floor($str);
+       $minutes = round(($str - $hours) * 60);
+       $str = sprintf("%d:%02d", $hours, $minutes);
+       return $str;
+}
+
+# takes decimal number of hours
+# returns hh:mm followed by "am" or "pm" with no space
+function enc_12hr($str) {
+       if(strlen($str) == 0) {
+               return '';
+       }
+       $hours = floor($str);
+       $minutes = round(($str - $hours) * 60);
+       $suffix = 'am';
+       if($hours >= 12.0) {
+               $suffix = 'pm';
+               if($hours > 12.0) {
+                       $hours -= 12.0;
+               }
+       }
+       $str = sprintf("%d:%02d", $hours, $minutes);
+       $str .= $suffix;
+       return $str;
+}
+
+
+
+# These are depricated! All but PULLDOWN_HASH still work, but you should update your code.
+define('PULLDOWN_AUTO', 0); define('PULLDOWN_ARRAY', 1); define('PULLDOWN_HASH', 2); define('PULLDOWN_2D', 3);
+
+
+# call this function before you run() the template so enc_options() knows what
+# to do
+#
+# Parameters:
+#
+#   name: the name of the html control
+#
+#   options: an array of options to display in the pulldown/selectbox. Each
+#   element can be either a string, or an array with two elements (first the
+#   value to post, and second the value to display in the pulldown)
+#
+#   multiple: UNTESTED set to true for multiple-select boxes. 
+
+function pulldown($name, $in_options, $multiple = false) {
+       if($multiple === PULLDOWN_HASH) {
+               die('Webmaster error: PULLDOWN_HASH is depricated. Pass array(a,b) not a=>b');
+       }
+       if($multiple !== true) {
+               # Probably due to API change (removing 3rd argument) but don't bother
+               # emitting a warning, because the above warning handles the only
+               # important case.
+               $multiple = false;
+       }
+       $options = array();
+       foreach($in_options as $option) {
+               if(is_array($option)) {
+                       $options[] = $option;
+               } else {
+                       $options[] = array($option, $option);
+               }
+       }
+       $GLOBALS[$name . '_options'] = array(
+               'options' => $options,
+               'multiple' => $multiple);
+}
+
+# output a bunch of <option> tags
+function enc_options($values, $name) {
+       if(!isset($GLOBALS[$name . '_options'])) {
+               die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
+       }
+       if($GLOBALS[$name . '_options']['multiple']) { # FIXME test this
+               $values = explode(', ', $values);
+       }
+       return encode_options($values, $GLOBALS[$name . '_options']['options']);
+}
+
+# for radios and pulldowns:
+# pass posted value
+# returns what the user sees in the pulldown or on the radio button caption
+function enc_pulled($str, $name) {
+       if(!isset($GLOBALS[$name . '_options'])) {
+               die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
+       }
+       foreach($GLOBALS[$name . '_options']['options'] as &$kv) {
+               if($kv[0] == $str) {
+                       return $kv[1];
+               }
+       }
+       return $str;
+}
+
+function enc_radio_n($str, $name, $n) {
+       if(!isset($GLOBALS[$name . '_options'])) {
+               die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
+       }
+
+       if(!isset($GLOBALS[$name . '_options']['options'][$n])) {
+               die("Template error: pulldown('$name') does not have element # $n");
+       }
+
+       $value = enc_attr($GLOBALS[$name . '_options']['options'][$n][0]);
+
+       if($str === $value) {
+               $value .= '" checked="checked';
+       }
+
+       return $value;
+}
+function enc_radio_0($str, $name) { return enc_radio_n($str, $name, 0); }
+function enc_radio_1($str, $name) { return enc_radio_n($str, $name, 1); }
+function enc_radio_2($str, $name) { return enc_radio_n($str, $name, 2); }
+function enc_radio_3($str, $name) { return enc_radio_n($str, $name, 3); }
+function enc_radio_4($str, $name) { return enc_radio_n($str, $name, 4); }
+function enc_radio_5($str, $name) { return enc_radio_n($str, $name, 5); }
+function enc_radio_6($str, $name) { return enc_radio_n($str, $name, 6); }
+function enc_radio_7($str, $name) { return enc_radio_n($str, $name, 7); }
+
+
+function enc_radio_caption_n($str, $name, $n) {
+       if(!isset($GLOBALS[$name . '_options'])) {
+               die("pulldown('$name') must be called before this template can be run. See wfpl/encode.php");
+       }
+
+       if(!isset($GLOBALS[$name . '_options']['options'][$n])) {
+               die("Template error: pulldown('$name') does not have element #$n");
+       }
+
+       return $GLOBALS[$name . '_options']['options'][$n][1];
+}
+function enc_radio_caption_0($str, $name) { return enc_radio_caption_n($str, $name, 0); }
+function enc_radio_caption_1($str, $name) { return enc_radio_caption_n($str, $name, 1); }
+function enc_radio_caption_2($str, $name) { return enc_radio_caption_n($str, $name, 2); }
+function enc_radio_caption_3($str, $name) { return enc_radio_caption_n($str, $name, 3); }
+function enc_radio_caption_4($str, $name) { return enc_radio_caption_n($str, $name, 4); }
+function enc_radio_caption_5($str, $name) { return enc_radio_caption_n($str, $name, 5); }
+function enc_radio_caption_6($str, $name) { return enc_radio_caption_n($str, $name, 6); }
+function enc_radio_caption_7($str, $name) { return enc_radio_caption_n($str, $name, 7); }
+
+
+# use this function along with a special template to generate the html for pulldowns and multiple select boxes.
+#
+# Parameters:
+#
+#    selected: can be a string or (for multiple-selects) an array
+#
+#    options: see documentation for pulldown() above
+function encode_options($selected, $options) {
+       if(!is_array($selected)) {
+               $selected = array($selected);
+       }
+
+       $out = '';
+       foreach($options as $option) {
+               list($value, $display, $arg3) = $option;
+               $out .= '<option';
+
+               if($arg3 == 'disabled') {
+                       $out .= ' disabled';
+               } elseif(in_array($value, $selected)) {
+                       $out .= ' selected';
+               }
+
+               if($value !== $display || strpos($value, ' ') !== false) {
+                       $out .= ' value="';
+                       $out .= enc_attr($value);
+                       $out .= '"';
+               }
+                       
+               $out .= '>';
+
+               $out .= enc_htmlnbsp($display);
+
+               $out .= "</option>\n";
+       }
+
+       return $out;
+}
+
+$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"));
+
+# display <option>s
+function enc_states($str) {
+       $ret = '';
+
+       return encode_options($str, $GLOBALS['wfpl_states_assoc']);
+}
+
+$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"));
+
+# display <option>s
+function enc_provinces($str) {
+       $ret = '';
+
+       return encode_options($str, $GLOBALS['wfpl_provinces_assoc']);
+}
+
+# returns "odd", then "even", then "odd" etc.
+function enc_evenodd($values, $name) {
+       if(!isset($GLOBALS['wfpl_even_odds'])) {
+               $GLOBALS['wfpl_even_odds'] = array();
+       }
+
+       if($GLOBALS['wfpl_even_odds'][$name]) {
+               $GLOBALS['wfpl_even_odds'][$name] = false;
+               return 'even';
+       } else {
+               $GLOBALS['wfpl_even_odds'][$name] = true;
+               return 'odd';
+       }
+}
+
+function enc_image_src($str) {
+       list($src, $width, $height, $a, $b, $c) = explode(' ', $str);
+       return $src;
+}
+
+function enc_image_width($str) {
+       list($src, $width, $height, $a, $b, $c) = explode(' ', $str);
+       return $width;
+}
+
+function enc_image_height($str) {
+       list($src, $width, $height, $a, $b, $c) = explode(' ', $str);
+       return $height;
+}
+
+function enc_thumb_src($str) {
+       list($a, $b, $c, $src, $width, $height) = explode(' ', $str);
+       return $src;
+}
+
+function enc_thumb_width($str) {
+       list($a, $b, $c, $src, $width, $height) = explode(' ', $str);
+       return $width;
+}
+function enc_thumb_height($str) {
+       list($a, $b, $c, $src, $width, $height) = explode(' ', $str);
+       return $height;
+}
+
+# example template: Length: ~length html~ day~length s~
+function enc_s($str) {
+       if($str == '1') {
+               return '';
+       }
+
+       return 's';
+}
+
+# turn http/ftp (s) urls into html links (and encode everything for html)
+# does not encode without protocol (eg "www.foo.com")
+# does not linkify email addresses
+function enc_linkify($str) {
+       $ret = '';
+       $even = true;
+       $pieces = preg_split("/((?:ht|f)tps?:\/\/[^ \,\"\n\r\t<]+)/is", $str, null, PREG_SPLIT_DELIM_CAPTURE);
+       foreach($pieces as $piece) {
+               if($even) {
+                       $ret .= enc_html($piece);
+               } else {
+                       $ret .= '<a href="' . enc_attr($piece) . '">' . enc_html($piece) . '</a>';
+               }
+               $even = !$even;
+       }
+       return $ret;
+}
+
+# turns a filename into the unix timestamp of that files modification date
+function enc_mtime($dummy, $filename) {
+       $stat = stat($filename);
+       if ($stat === false) {
+               return '';
+       }
+       return '' . $stat['mtime'];
+}