<?php if (!defined('PmWiki')) exit();
/*
 * PageVariableExtensions - Page Variable extensions for PmWiki 2.1
 * Copyright 2006 by D.Faure (dfaure@cpan.org)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * See http://www.pmwiki.org/wiki/Cookbook/PageVariableExtensions for info.
 */
$RecipeInfo['PageVariableExtensions']['Version'] = '20061029';

if(IsEnabled($EnableUrlSetVar, 0)) {
  $pagename = ResolvePageName($pagename);
  foreach($_REQUEST as $k => $v) {
    if(!preg_match('/^set_(.+)$/i', $k, $m)) continue;
    SetProperty($pagename, $m[1], $v);
    $FmtPV["\${$m[1]}"] = "@\$page['=p_$m[1]']";
    unset(${$k});
  }
}

SDVA($PageVarSetters, array(
'if'           => 'SetPageVarCond',
'time'         => 'SetPageVarTime',
'http_get'     => 'SetPageVarHTTPGetter',
'http_post'    => 'SetPageVarHTTPGetter',
'http_request' => 'SetPageVarHTTPGetter',
'http_cookie'  => 'SetPageVarCookieGetter',
'session_data' => 'SetPageVarSessionGetter',
));

function SetPageVarCond($pagename, $func, $param, $default) {
  $opt = ParseArgs($default);
  return $opt[''][CondText($pagename, "if $param", 'TRUE') ? 0 : 1];
}

function SetPageVarTime($pagename, $func, $param, $default) {
  $opt = ParseArgs($param);
  global $Now; #$Now = time();
  if(isset($opt[''])) {
    $n = isset($opt[''][1])? $opt[''][1] : $Now;
    return strtotime($opt[''][0], $n);
  }
  $h_ = isset($opt['H'])? $opt['H'] : date("H", $Now);
  $mi = isset($opt['M'])? $opt['M'] : date("i", $Now);
  $s_ = isset($opt['S'])? $opt['S'] : date("s", $Now);
  $d_ = isset($opt['d'])? $opt['d'] : date("d", $Now);
  $mo = isset($opt['m'])? $opt['m'] : date("m", $Now);
  $y_ = isset($opt['Y'])? $opt['Y'] : date("Y", $Now);
  return mktime($h_, $mi, $s_, $mo, $d_, $y_);
}

function SetPageVarHTTPGetter($pagename, $func, $param, $default) {
  $v = $GLOBALS[strtoupper(substr($func, 4))][$param];
  return isset($v) ? $v : $default;
}

function SetPageVarCookieGetter($pagename, $func, $param, $default) {
  global $CookiePrefix;
  return SetPageVarHTTPGetter($pagename, $func, $CookiePrefix . $param, $default);
}

function SetPageVarSessionGetter($pagename, $func, $param, $default) {
  @session_start();
  $v = $_SESSION[$param];
  return isset($v) ? $v : $default;
}

# {$var} initializer
Markup('!{$var}', '<{$var}',
  "/\\(:set\\s+(.+?):\\)/ei", "PZZ(SetPageVars(\$pagename,PSS('$1')))");

function SetPageVars($pagename, $args) {
  global $SaveProperties, $MarkupTable, $PCache, $FmtPV, $PageVarSetters;
  $opt = ParseArgs($args);
  unset($opt[''], $opt['#']);
  foreach($opt as $n => $v) {
    if($n == '+') {
      foreach($opt[$n] as $r) $SaveProperties[] = $r;
      $SaveProperties = array_unique($SaveProperties);
      continue;
    }
    else if($n == '-') {
      $page = &$PCache[$pagename];
      foreach($opt[$n] as $r) unset($page["=p_$r"], $FmtPV["\${$r}"]);
      continue;
    }    
    $v = preg_replace($MarkupTable['{$var}']['pat'], $MarkupTable['{$var}']['rep'], $v);
    if(preg_match('/^(\\([^)]+\\)|\\[[^]]+\\])\s*(.*)/', $v, $m)) {
      if(!preg_match('/^=(\\S+)\s+(.*)/', trim(substr($m[1], 1, -1)), $t))
        continue;
      $f = $PageVarSetters[$t[1]];
      $v = isset($f) ? $f($pagename, $t[1], $t[2], $m[2]) : $m[2];
    }
    SetProperty($pagename, $n, $v);
    $FmtPV["\${$n}"] = "@\$page['=p_$n']";
  }
}

# timestamp {$var}
$FmtPV['$Now'] = $Now;

# extended {$var} substitutions
$MarkupTable['{$var}']['pat'] = ($VersionNum < 2001900) ?
  '/\\{(!?[-\\w.\\/]*)(\\$\\w+)(:[^\\}]*)?\\}/e' :
  '/\\{(\\*|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w+)(:[^\\}]*)?\\}/e';
$MarkupTable['{$var}']['rep'] = "htmlspecialchars(ExtendedPageVar(\$pagename,'$2','$1',PSS('$3')),ENT_NOQUOTES)";

SDVA($PageVarFuncs, array(
'ireplace' => 'str_replace($funcparm[0],$funcparm[1],$value)',
'istr' => 'stristr($value,$funcparm[0])',
'len' => 'strlen($value)',
'replace' => 'str_replace($funcparm[0],$funcparm[1],$value)',
'rev' => 'strrev($value)',
'rot13' => 'str_rot13($value)',
'str' => 'strstr($value,$funcparm[0])',
'sub' => 'substr($value,$funcparm[0],isset($funcparm[1])?$funcparm[1]:strlen($value))',
'tolower' => 'strtolower($value)',
'toupper' => 'strtoupper($value)',
'ucfirst' => 'ucfirst($value)',
'ftime' => 'tweaked_strftime($funcparm[0],$value)',
'gmftime' => 'tweaked_strftime($funcparm[0],$value, true)',
'fdate' => 'strfdate($funcparm[0],$value)',
'regmatch' => 'preg_match($funcparm[0],$value)?"true":"false"',
'regreplace' => 'tweaked_preg_replace($funcparm[0],$funcparm[1],$value)',
'+' => '$value + $funcparm[0]',
'-' => '$value - $funcparm[0]',
'*' => '$value * $funcparm[0]',
'/' => '$value / $funcparm[0]',
'asspaced' => '$GLOBALS["AsSpacedFunction"]($value)',
'aspagename' => 'MakePageName(isset($funcparm[0])?$funcparm[0]:$pagename,$value)',
'aswiki' => 'preg_replace(array_keys($GLOBALS["MakePageNamePatterns"]), array_values($GLOBALS["MakePageNamePatterns"]), $value)',
));

define('_DBG_VAR', "print_r");

function ExtendedPageVar($pagename, $var, $pn = '', $funcspec = '') {
  global $PageVarFuncs;
  $value = PageVar($pagename, $var, $pn);
  if($funcspec) {
    $funcs = preg_split("/:(?=(\\w+|[\\*\\/+-]))/", $funcspec, -1, PREG_SPLIT_NO_EMPTY);
    foreach($funcs as $f) {
      if (!preg_match("/(\\S+)(\\s+.*)?\\s*$/", $f, $m)) break;
      @list($funcstr, $funcname, $p) = $m;
      if (isset($PageVarFuncs[$funcname])) {
        $p = ParseArgs($p);
        $funcparm = str_replace(array('&lt;', '&gt;', '&amp;'),
                                array('<', '>', '&'), $p['']);
        $funcparm = preg_replace("/<(!?[-\\w.\\/]*)(\\$\\w+)>/e",
                                 "PageVar('$pagename', '$2', '$1')", $funcparm);
        $value = @eval("return ($PageVarFuncs[$funcname]);");
      }
    }
  }
  return $value;
}

function tweaked_strftime($format, $ts = null, $gmt = false) {
  if (!$ts) $ts = time();
  if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    $dfun = $gmt ? 'gmdate' : 'date';
    $mapping = array(
    '%C' => sprintf("%02d", $dfun("Y", $ts) / 100),
    '%D' => '%m/%d/%y',
    '%e' => sprintf("%' 2d", $dfun("j", $ts)),
    '%g' => sprintf("%02d", $dfun("o", $ts) % 100),
    '%G' => $dfun("o", $ts),
    '%h' => '%b',
    '%n' => "\n",
    '%r' => $dfun("h:i:s", $ts) . " %p",
    '%R' => $dfun("H:i", $ts),
    '%t' => "\t",
    '%T' => '%H:%M:%S',
    '%u' => ($w = $dfun("w", $ts)) ? $w : 7,
    '%V' => $dfun("W", $ts),
    );
    $format = str_replace(array_keys($mapping),
                          array_values($mapping), $format);
  }
  return $gmt ? gmstrftime($format, $ts) : strftime($format, $ts);
}

function strfdate($format, $date) {
  $date = preg_replace('/\\D/', '', $date);
  if(!preg_match('/(\\d{4})(\\d{2})(\\d{2})/', $date, $m)) {
    $now = time();
    $m[1] = date('Y', $now); $m[2] = date('m', $now); $m[3] = date('d', $now); 
  }
  $date = mktime(0, 0, 0, $m[2], $m[3], $m[1]);
  return tweaked_strftime($format, $date);
}

function tweaked_preg_replace($pattern, $replacement, $string) {
  $p = strrpos($pattern, $pattern{0});
  $pattern = substr($pattern, 0, $p)
           . str_replace('e', '', substr($pattern, $p));
  return preg_replace($pattern, $replacement, $string);
}

Markup('setcookie', 'directives',
  '/\\(:cookie\\s+(.+?):\\)/ei', "PZZ(HTTPCookieSetter(\$pagename,PSS('$1')))");

function HTTPCookieSetter($pagename, $args) {
  global $CookiePrefix;
  $opt = ParseArgs($args);
  unset($opt['#'], $opt['+'], $opt['-']);
  if(!isset($opt['path'])) $opt['path'] = '/';
  setcookie($CookiePrefix . $opt['name'],
            $opt['value'], $opt['expire'], $opt['path'], $opt['domain']);
}

Markup('setsessiondata', 'directives',
  '/\\(:session\\s+(.+?):\\)/ei', "PZZ(SessionDataSetter(\$pagename,PSS('$1')))");

function SessionDataSetter($pagename, $args) {
  $opt = ParseArgs($args);
  unset($opt['#'], $opt['+']);
  @session_start();
  foreach($opt as $n => $v) {
    if($n == '-') {
      foreach($opt[$n] as $r) unset($_SESSION[$r]);
      continue;
    }
    $_SESSION[$n] = $v;
  }
}