diff options
Diffstat (limited to 'devel-utf8/it.class')
-rw-r--r-- | devel-utf8/it.class | 846 |
1 files changed, 0 insertions, 846 deletions
diff --git a/devel-utf8/it.class b/devel-utf8/it.class deleted file mode 100644 index 624f601..0000000 --- a/devel-utf8/it.class +++ /dev/null @@ -1,846 +0,0 @@ -<?php -/* -** $Id$ -** -** Copyright (C) 1995-2007 by the ITools Authors. -** This file is part of ITools - the Internet Tools Library -** -** ITools 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. -** -** ITools 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 this program. If not, see <http://www.gnu.org/licenses/>. -** -** it.class - static functions -*/ - -class it -{ -/** - * Create config class with static members initialized (e.g. $home). - * NOTE: PHP5 ONLY - * @param $p Static members to be generated in newly created class - * service: Class name of created class (default: from caller path) - * home: Home directory of application (default: from caller path) - * site: Domain name of application (default: from caller path) - * db: Database of application (default: from caller path) - */ -static function createconfig($p = array()) -{ - $stack = debug_backtrace(); - $filename = $stack[0]['file']; - preg_match('!/www/((\w+)[^/]+)!', $filename, $parts); - - $p += array( - 'home' => $parts[0], - 'site' => $parts[1], - 'db' => strtr($parts[1], ".-", "__"), - 'service' => $parts[2], - ); - - if (class_exists($p['service'] . "_tools")) - $extends = "extends {$p['service']}_tools "; - - $code = array("class {$p['service']} $extends{"); - - foreach ($p as $name => $value) - $code[] = "static \$$name = " . var_export($value, true) . ";"; - - $code[] = "}"; - eval(join("\n", $code)); -} - - -/** - * Clone an object and return copy, works for all PHP versions - */ -static function &cloneobj(&$object) -{ - $result = (is_object($object) && version_compare(zend_version(), 2, '>=')) ? clone($object) : $object; - - return $result; # PHP internals need a tmp var to return by ref -} - - -/** - * Append all arguments to a logfile (tab separated). Date will be added to filename and line - * @param $name Name of logfile. Will be in log/ of service unless it starts with / - * @param $line1 Line to append (varargs) - */ -static function log($name /* ... */) -{ - $args = func_get_args(); - $line = date("Y-m-d H:i:s") . "\t" . implode("\t", array_slice($args, 1)) . "\n"; - $basefn = substr($name, 0, 1) == "/" ? $name : $GLOBALS['ULTRAHOME'] . "/log/$name"; - $fullfn = $basefn . "-" . date('Ymd'); - - if (substr($fullfn, 0, 1) == "/") - { - if (!file_exists($fullfn)) - { - $tmp = getmypid(); - @touch("$fullfn.$tmp"); - @chgrp("$fullfn.$tmp", "www"); - @rename("$fullfn.$tmp", $fullfn); - @unlink($basefn); - @symlink($fullfn, $basefn); - } - - file_put_contents($fullfn, $line, FILE_APPEND); - } -} - - -/** - * Store timings for appending to log/timer_log-* in auto_append.php - */ -static function timerlog($label = '') -{ - if ($GLOBALS['debug_timerlog']) - { - $s = $GLOBALS['ULTRATIME']; - $e = gettimeofday(); - $msec= ($e['sec'] - $s['sec']) * 1000 + ($e['usec'] - $s['usec']) / 1000; - $GLOBALS['ULTRATIMERLOG'] .= sprintf(" %s:%d", $label, $msec); - } -} - - -/** - * Send verbose error report to browser or (if display_errors is off) by email to .diffnotice gods, file owner or SERVER_ADMIN - * All params optional. Single string parameter means 'title'. - * @param $p['title'] error title, one line - * @param $p['body'] error body, multiline - * @param $p['to'] comma separated recipient list - * @param $p['id'] identifier of error. if given, only subsequent errors of same id will trigger message - * @param $p['graceperiod'] number of seconds within which additional errors are ignored if id is set - * @param $p['timewindow'] number of seconds after graceperiod within which the second error must occur if id is set - * @param $p['backtraceskip'] number of stack levels to drop - * @param $p['blockmail'] number of seconds to block mails after having sent a mail [3600] - * @param $p['blockmailid'] block mail for $p['blockmail'] seconds with same id. Default: $p['to'] - * @param $p['omitdebuginfo'] Do not add stack dump, locals and environment to output [false] - */ -static function error($p = array(), $body = null, $to = null) # $body and $to deprecated -{ - if (!is_array($p)) - $p = array('title' => $p, 'body' => $body, 'to' => $to); - - if ($_SERVER['REMOTE_ADDR']) - $url = ($_SERVER['HTTPS'] ? "https://" : "http://") . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - else - $url = $_SERVER['SCRIPT_NAME']; - - $gods = strtr(trim(@file_get_contents($GLOBALS['ULTRAHOME'] . "/.diffnotice")), array("\n"=>', ')); - if (!$p['to']) - unset($p['to']); # allow defaults to kick in - $p += array( - 'title' => "it::error", - 'to' => $gods ? $gods : (get_current_user() ? get_current_user() : $_SERVER['SERVER_ADMIN']), - 'graceperiod' => 60, - 'timewindow' => 25*3600, - 'backtraceskip' => 0, - 'blockmail' => 3600, - 'omitdebuginfo' => false, - ); - $p += array('blockmailid' => md5($p['to'])); - - @mkdir("/tmp/alertdata"); - @chmod("/tmp/alertdata", 0777); - - $toscreen = ini_get('display_errors') || (defined("STDOUT") && posix_isatty(STDOUT)) || EDC('astwin') || EDC('asdevel'); - @fseek(STDOUT, 0, SEEK_END); # Work around PHP bug 49819: posix_isatty seeks to start - - if ($toscreen && !it::is_live()) - $GLOBALS['debug_noredir'] = 1; - - if (!$toscreen) # this error can only be sent by mail: find out if we want to suppress it - { - if (!$p['id']) - $sendmail = true; - else - { - $errstampfn = "/tmp/alertdata/errstamp_" . urlencode($p['id']); - $errstampage = time() - @filemtime($errstampfn); - $sendmail = $errstampage >= $p['graceperiod'] && $errstampage <= $p['graceperiod'] + $p['timewindow']; - if ($errstampage > $p['graceperiod']) - { - @unlink($errstampfn); - @touch($errstampfn); - } - } - - if ($sendmail) - { - $lastsentfn = "/tmp/alertdata/lastsent_" . getmyuid() . "." . $p['blockmailid']; - $now = time(); - clearstatcache(); - $lastsenttime = @filemtime($lastsentfn); - $sendmail = $now - $lastsenttime > $p['blockmail']; - if ($sendmail) - { - @unlink($lastsentfn); - @touch($lastsentfn); - } - } - } - - if ($toscreen || $sendmail) - { - $trace = it_debug::backtrace($p['backtraceskip']); # moved in here for performance in mass error case - - if (strlen($p['body']) > 500000) - { - file_put_contents($datafn = "/tmp/alertdata/error-" . substr(md5($p['body']), 0, 2), $p['body']); - $p['body'] = "Body: " . getenv('HOSTNAME') . ":$datafn"; - } - - $body = ($p['body'] ? trim($p['body'])."\n\n" : "") . ($url && !$toscreen? "{$p['title']}\n\nUrl: $url\n\n" : "") . ($trace ? ($sendmail?"" :" ")."Trace: $trace\n\n" : ""); - - if ($sendmail) # we're mailing: send maximum info - { - $p['title'] = "Alert: " . $p['title'] . " (on " . getenv('HOSTNAME') . ")"; - - if (!$p['omitdebuginfo']) - { - $locals = print_r(array_diff_key((array)$p['locals'], array("GLOBALS", "_GET", "_POST", "_COOKIE")), true); - - if ($trace && ($fulltrace = array_slice(debug_backtrace(), $p['backtraceskip']))) - while (strlen(print_r($fulltrace, true)) > 100000) - array_pop($fulltrace); - - $body .= "Host: " . getenv('HOSTNAME') . "\n\n"; - $body .= $locals && strlen($locals) < 100000 ? "Locals: $locals\n\n" : ""; - $body .= $p['id'] ? "Filter: graceperiod={$p['graceperiod']} timewindow={$p['timewindow']}\n\n" : ""; - $body .= "Time: " . it::date() . "\n\n"; - $body .= $_GET ? "\$_GET: " . var_export($_GET, true) . "\n\n" : ""; - $body .= $_POST ? "\$_POST: " . var_export($_POST, true) . "\n\n" : ""; - $body .= $_COOKIE ? "\$_COOKIE: " . var_export($_COOKIE, true) . "\n\n" : ""; - $body .= $_SERVER ? "\$_SERVER: " . var_export($_SERVER, true) . "\n\n" : ""; - $body .= $fulltrace ? "Stack: " . print_r($fulltrace, true) . "\n\n" : ""; - $body = it::replace(array('(pw|passw|password|secret)\] => .*' => '$1] => ********'), $body); - } - - it::mail(array('To' => $p['to'], 'Subject' => substr($p['title'], 0, 80), 'Body' => $body) + (($cc = $GLOBALS['it_defaultconfig']['error_cc']) ? array('Cc' => $cc) : array())); - } - else if ($_SERVER['REMOTE_ADDR']) # toscreen mode: web - echo "<pre>{$p['title']}\n".rtrim($body)."</pre>"; - else # toscreen mode: shell (outputs to stderr) - error_log($p['title'] . " in " . ($trace ? $trace : "{$p['file']}:{$p['line']} Url: $url") . " " . (EDC('verbose') ? D($p['locals']) : "")); - } - - if ($_SERVER['REMOTE_ADDR']) - error_log("it::error: " . $p['title'] . " Url: $url"); - - if (($fh = fopen("/tmp/alertdata/alert.log", "a"))) - { - fputs($fh, it::date() . " " . $p['title'] . " in " . ($trace ? $trace : "{$p['file']}:{$p['line']} Url: $url") . "\n"); - fclose($fh); - @chmod("/tmp/alertdata/alert.log", 0777); - } -} - - -/** - * Same as it::error(), plus exit - * @see error() - */ -static function fatal($title='', $body='', $to='') -{ - $p = is_array($title) ? $title : array('title' => $title, 'body' => $body, 'to' => $to); - $p['backtraceskip']++; - it::error($p); - exit(1); -} - - -/** - * Print message to stderr and exit with error code - */ -static function bail($message = "Bailed.\n") -{ - fputs(STDERR, $message); - exit(1); -} - - -/** - * Check wether I am on a live server for this service. Honors 'aslive' and 'asdevel' debug vars - * @return true if servertype is 'live' - */ -static function is_live() -{ - return (preg_match("/^live/", $GLOBALS['ULTRASERVERTYPE']) || !$GLOBALS['ULTRASERVERTYPE'] || EDC('aslive')) && !EDC('asdevel'); -} - - -/** - * Check wether I am on a development server for this service. Honors 'aslive' and 'asdevel' debug vars - * @return true if servertype is 'devel' - */ -static function is_devel() -{ - return (preg_match("/^devel/", $GLOBALS['ULTRASERVERTYPE']) || EDC('asdevel')) && !EDC('aslive'); -} - - -/** - * Convert a string to ASCII-only chars, map/strip ISO-8859-1 accents - * @param $text Text to convert - * @return mapped/stripped version of $text contains only chars [0..127] - */ -static function toascii($text) -{ - return strtr(strtr($text, - 'ÇéâàåçêëèïîìÅÉôòûùÿøØáíóúñÑÁÂÀãÃÊËÈÍÎÏÓÔõÕÚÛÙýÝ', - 'CeaaaceeeiiiAEoouuyooaiounNAAAaAEEEIIIOOoOUUUyY'), - array('ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'Ä' => 'Ae', 'Ö' => 'Oe', 'Ü' => 'Ue', 'æ' => 'ae', 'Æ' => 'Ae', 'ß' => 'ss')); -} - - -/** - * Convert regex for preg (adds and escapes delimiter, adds modifiers) - * @param $pattern Regex to convert - * @param $p['casesensitive'] Regex is case sensitive (omit modifier i) - * @param $p['multiline'] add modifier m: ^ and $ match \n - * @param $p['singleline'] add modifier s: . matches \n - * @param $p['utf8'] add modifier u. This is the default if default_charset is utf-8, override with $p['utf8'] = false - * @param $p['extended'] add modifier x (non signifcant whitespace) - * @return converted regex to use with preg - */ -static function convertregex($pattern, $p = null) -{ - if ($p['exec']) - it::fatal("Option exec to it::replace has been removed for security reasons"); - - return '/' . strtr($pattern, array('/' => '\/')) . '/' . - (!$p['casesensitive'] ? 'i' : '') . - ($p['multiline'] ? 'm' : '') . - ($p['singleline'] ? 's' : '') . - ($p['extended'] ? 'x' : '') . - ((!isset($p['utf8']) && ini_get('default_charset') == 'utf-8' || $p['utf8']) ? 'u' : ''); -} - - -/** - * Try to match string against regex. Case insensitive by default. - * @param $pattern Regex to match against - * @param $string String to match - * @param $p['offset_capture'] Set flag preg_offset_capture (returns offsets with the matches). - * @param $p['all'] Return every match as array instead of first match. - * @param $p['locale'] Use given locale (default: de_CH), mainly affects handling of iso-latin chars - * @param $p contains pattern modifiers, @see convertregex() - * @return Matched string or false - */ -static function match($pattern, $string, $p = null) -{ - if (!preg_match('/\\\\[wb]|[!\x80-\xff]|\[\[:/i', $pattern) && !$p) - $r = preg_match('!' . $pattern . '!i' . (ini_get('default_charset') == 'utf-8' ? 'u' : ''), $string, $m); # fast path for simple patterns - else - { - $flags = $p['offset_capture'] ? PREG_OFFSET_CAPTURE : 0; - - $oldlocale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, $p['locale'] ? $p['locale'] : "de_CH"); - - if ($p['all']) - $r = preg_match_all(it::convertregex($pattern, $p), $string, $m, $flags | PREG_PATTERN_ORDER, $p['offset']); - else - $r = preg_match(it::convertregex($pattern, $p), $string, $m, $flags, $p['offset']); - - setlocale(LC_CTYPE, $oldlocale); - } - - if (!$r) # no match - { - if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) - it::error("Exceeded pcre.backtrack_limit of " . ini_get('pcre.backtrack_limit') . " bytes"); - - $result = $p['all'] ? array() : null; - } - else if (count($m) == 1) # no capture - $result = $m[0]; - else if (count($m) == 2) # one capture - $result = $m[1]; - else if ($p['all'] && !$p['pattern_order']) # captures, reorder pattern_order to set_order but without first element - $result = call_user_func_array('array_map', array_merge(array(null), array_slice($m, 1))); - else # captures, don't return first element (matched string) - $result = array_slice($m, 1); - - return $result; -} - -/** - * Replace parts of a string matched by a pattern with according replacement string. See convertregex for named parameters. - * @param $replacementes Array with patterns as keys and replacement strings as values. - * @param $string String to change. - * @return New string. - */ -static function replace($replacements, $string, $p = array()) -{ - foreach ($replacements as $pattern => $dummy) - $patterns[] = !preg_match('/\\\\[wb]|[!\x80-\xff]|\[\[:/i', $pattern) && !$p ? "!$pattern!i" : it::convertregex($complex = $pattern, $p); - - if (!$complex && !$p) - $result = preg_replace($patterns, $replacements, $string); - else - { - $oldlocale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'de_CH'); - $result = preg_replace($patterns, $replacements, $string, isset($p['limit']) ? $p['limit'] : -1); - setlocale(LC_CTYPE, $oldlocale); - } - - return $result; -} - -/** - * Extract key => value pairs from assoc array by key - * @param $array array to filter - * @param $keys array or comma separated list of keys to keep - * @param $p['reorder'] reorder pairs to the order of the $keys array - */ -static function filter_keys($array, $keys, $p = array()) -{ - $result = array(); - if (is_string($keys)) - $keys = explode(",", $keys); - if ($p['reorder']) - { - foreach ((array)$keys as $key) - $result[$key] = $array[$key]; - } - else - { - $keep = array_flip((array)$keys); - foreach ($array as $key => $val) - if (isset($keep[$key])) - $result[$key] = $val; - } - - return $result; -} - - -/** - * Construct shell command using it::shell_command, log it, execute it and return output as string. - * Keywords {keyword} are replace a la ET(), {-opts} takes an array and - * inserts options a la it_html attributes (value, true, false or null) - * @param $cmd Format string with {keywords} replace a la ET() - * @param $values (zero, one or more arrays can be passed) - * @return output of command. shell errors not detectable, see error_log in /www/server/logs - */ -static function exec(/* $cmd, $values1 = array(), ... */) -{ - $args = func_get_args(); - $cmd = call_user_func_array('it::shell_command', $args); - - $s = gettimeofday(); - $result = EDC('noexec') ? "" : (string)shell_exec($cmd); - $e = gettimeofday(); - $msec= intval(($e['sec'] - $s['sec']) * 1000 + ($e['usec'] - $s['usec']) / 1000); - - @it::log('exec', "$msec\t$cmd"); - - return $result; -} - -/** - * Construct shell command - * Keywords {keyword} are replace a la ET(), {-opts} takes an array and - * inserts options a la it_html attributes (value, true, false or null) - * @param $cmd Format string with {keywords} replace a la ET() - * @param $values (zero, one or more arrays can be passed) - * @return output of command. shell errors not detectable, see error_log in /www/server/logs - */ -static function shell_command(/* $cmd, $values1 = array(), ... */) -{ - $args = func_get_args(); - $cmd = array_shift($args); - $values = array(); - - # Merge values into one array - foreach ($args as $arg) - $values += (array)$arg; - - #for escapeshellarg in it::_exec_quotevalue - $oldlocale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'de_CH'); - foreach (it::match('({(-?)([a-z]\w*)})', $cmd, array('all' => true)) as $tags) - { - list($tag, $option, $key) = $tags; - $parts = array(); - - if ($option) - { - foreach ((array)$values["-$key"] as $key => $value) - { - if ($value === true || $value === false || $value === null) - $parts[] = $value ? $key : ""; - else foreach ((array)$value as $val) - $parts[] = "$key " . it::_exec_quotevalue($val, "cmd=$cmd key=$key val=$val"); - } - } - else - { - foreach ((array)$values[$key] as $value) - $parts[] = it::_exec_quotevalue($value, "cmd=$cmd key=$key val=$value"); - } - - $replacements[$tag] = join(" ", $parts); - } - - $cmd = strtr($cmd, (array)$replacements); # Use strtr behaviour of going through source string once - setlocale(LC_CTYPE, $oldlocale); - return $cmd; -} - -#fails with C locale!!! -static function _exec_quotevalue($value, $errmsg = "") -{ - $result = strval($value); - - if (it::match('^-', $result)) - it::fatal("leading - in value: " . $errmsg); - - return preg_match('#^[-a-zA-Z0-9./_:,]+$#', $result) ? $result : escapeshellarg($result); -} - - -/** - * Convert an image to a given size and type (ensures input is an image) - * @param $p['in'] Input filename (mandatory) - * @param $p['out'] Output filename (mandatory) - * @param $p['size'] Width x height of resulting image, e.g. "160x60" - * @param $p['type'] Output file type, e.g. "jpg" - * @param $p['types'] Comma separated list of accepted input types, default "bmp,eps,gif,jp2,jpg,png,svg,tif" - * @param $p['-opts'] Custom command line options to ImageMagick convert - * @return Success of convert as true/false - */ -static function imageconvert($p) -{ - if (!(($imagetype = @exif_imagetype($p['in'])) && ($type = image_type_to_extension($imagetype, false)))) - { - if (@get_class(it_xml::create(fopen($p['in'], "r"), array('prefix' => "_imageconvert_", 'safety' => 0))) == "_imageconvert_svg") - $type = "svg"; # Accept SVG files if they are valid XML and root tag is svg - else - list(, $type) = explode(' ', strtolower(it::exec('identify 2>/dev/null {in}', $p))); # for things like eps - } - - # emulate -auto-orient which is not supported by GM - if ($p['-opts']['-auto-orient']) { - $exif = @exif_read_data($p['in'], 'IFD0'); - switch ($exif['Orientation']) { - case 2: $p['-opts']['-flop'] = true; break; - case 3: $p['-opts']['-rotate'] = 180; break; - case 4: $p['-opts']['-flip'] = true; break; - case 6: $p['-opts']['-rotate'] = 90; break; - case 8: $p['-opts']['-rotate'] = 270; break; - } - unset($p['-opts']['-auto-orient']); - } - - $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps")); - $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif"); - $p['-opts'] = array('-thumbnail' => $p['size']) + (array)$p['-opts']; - $ultratimeout = file_exists("/opt/ultra/bin/ultratimeout") ? "/opt/ultra/bin/ultratimeout 30 " : ""; - - if (in_array($type, explode(',', $p['types']))) # Valid type? - $cmdoutput = it::exec($ultratimeout . 'gm convert 2>&1 -flatten -quality 75 {-opts} {in} {type}:{out} || echo "SHELL ERROR $?"', $p); - - return $cmdoutput === ""; -} - - -/** - * Parse command line options with Usage given as template and return assoc array. Example: (like grep --help) - * Usage: myprogram.php [OPTIONS] PATTERN - * -s, --short Use short ouput - * -f, --file=FILE Use FILE for input - * -x EXTENSION Ignore EXTENSION - * Mandatory arguments from the Usage: line are returned under their (lowercased!) name. - * All non-option arguments are returned in 'args' - * Option text must be indented; if long and short option present, value is stored in long option - * Options without arguments store true or false under their key - * Options -h and --help will be handled internally by printing usage and exiting - * When printing, the usage will be de-indented so the first line starts in the first column - * Two or more blanks must be in front of option explanation - * @param $helplines Usage parsed to determine options - * @return Associative array of options - */ -static function getopt($helplines) -{ - $GLOBALS['it_stdin'] = array( - 'fd' => null, - 'args' => array(), - 'filename' => "", - 'line' => 0, - ); - - $result = array('args' => array()); - - if ($indentation = it::match('^\s+', $helplines)) - $helplines = it::replace(array($indentation => "\n"), $helplines); - - foreach(explode("\n", trim($helplines)) as $helpline) - { - $shortoptname = $shortoptarg = $longoptname = $longoptarg = ""; - foreach (explode(',', $helpline) as $optdesc) - { - $optdesc = trim($optdesc); - if ($matches = (array)it::match('^--(\w[\w-]*)(=[A-Z])?', $optdesc)) - list($longoptname, $longoptarg) = $matches; - elseif ($matches = (array)it::match('^-(\w)( [A-Z])?', $optdesc)) - list($shortoptname, $shortoptarg) = $matches; - } - - if ($longoptname || $shortoptname) - { - if ($longoptname && ($shortoptname || $shortoptname === "0")) - $alias[$shortoptname] = $longoptname; - - $witharg[$longoptname ? $longoptname : $shortoptname] = $longoptarg || $shortoptarg; - } - } - $witharg['debug'] = true; - - $mandatoryargs = array(); - if ($tmp = trim(it::replace(array("\n.*" => "", "^\S+\s+\S+\s*" => "", "\[.*?\]\s*" => ""), trim($helplines)))) - $mandatoryargs = preg_split('/\s+/', $tmp); - - foreach (array_slice($_SERVER['argv'], 1) as $arg) - { - if ($eat) - { - if (it::match('^--?\w', $arg)) # Already next option => Missing argument? - $err = true; - else - $result[array_shift($eat)] = $arg; - } - elseif ($matches = (array)it::match('^--(\w[\w-]*)(=.*)?', $arg)) - { - list($optname, $val) = $matches; - if (!isset($witharg[$optname]) || isset($val) && !$witharg[$optname]) - $err = true; - else if($witharg[$optname] && !$val) - $eat[] = $optname; - else - $result[$optname] = $val ? substr($val, 1) : true; - } - else if (($letters = it::match('^-(\w+)', $arg)) || $letters === "0") - { - foreach (explode("\n", trim(chunk_split($letters, 1, "\n"))) as $letter) - { - $optname = $alias[$letter] ? $alias[$letter] : $letter; - if ($witharg[$optname]) - $eat[] = $optname; - else if (!isset($witharg[$optname])) - $err = true; - else - $result[$optname] = true; - } - } - elseif($mandatoryargs) - $result[strtolower(array_shift($mandatoryargs))] = $arg; - else - $result['args'][] = $arg; - } - - if ($err || $eat || $result['h'] || $result['help'] || $mandatoryargs) - { - fputs(($result['h'] || $result['help'] ? STDOUT : STDERR), trim($helplines) . "\n"); - exit(1); - } - - if ($result['debug']) - { - foreach (preg_split('/[.,]/', $result['debug']) as $ultrad) - { - $ultravar = preg_split('/[-=:]/', $ultrad); - $GLOBALS["debug_$ultravar[0]"] = isset($ultravar[1]) ? $ultravar[1] : 1; - } - } - - $GLOBALS['it_stdin']['args'] = $result['args'] ? $result['args'] : array("-"); - it::_stdin_next(); - - if ($result['verbose']) - $GLOBALS['debug_verbose']++; - - return $result; -} - -static function _stdin_next() -{ - if ($result = $GLOBALS['it_stdin']['args']) - { - $GLOBALS['it_stdin']['filename'] = array_shift($GLOBALS['it_stdin']['args']); - $GLOBALS['it_stdin']['fd'] = ($GLOBALS['it_stdin']['filename'] == "-") ? STDIN : @fopen($GLOBALS['it_stdin']['filename'], "r"); - $GLOBALS['it_stdin']['line'] = 0; - } - - return $result; -} - -/** - * Get one line from stdin (or files given on command line) a la Perl <>. - * Note: You need to call getopt() before using this function. - * @return Line (including newline) or false on eof - */ -static function gets() -{ - do { - $result = fgets($GLOBALS['it_stdin']['fd']); - } while (($result === false) && it::_stdin_next()); - - $GLOBALS['it_stdin']['line']++; - return $result; -} - -/** - * Output formatted and localized date - * @param format optional format (default is 2007-01-02 03:04:05). - * Other formats are "date", "datetime", "time". - * Formats can be qualified with language, e.g. "date:en" - * Special formats without language support are "icsdate", "icsdatetime". - * @param stamp optional unix timestamp (default is now). - * If it contains nondigits, it is fed to strtotime - */ -static function date($format = "", $stamp = null) -{ - if (!isset($stamp)) - $stamp = time(); - else if (is_string($stamp) && !ctype_digit($stamp)) - $stamp = strtotime($stamp); - - list($name, $language) = explode(":", $format); - - if ($format && !$language) - $language = T_lang(); - - $formats = array( - "" => "Y-m-d H:i:s", - "date" => "d.m.Y", - "datetime" => "d.m.Y H:i", - "time" => "H:i", - "date:en" => "m/d/Y", - "datetime:en" => "m/d/Y H:i", - "icsdate" => "Ymd", - ); - - if (!($formatstring = $formats["$name:$language"]) && !($formatstring = $formats[$name])) - { - if ($format == "icsdatetime") # Special icsdate or icsdatetime format? Use UTC time format for Google Calendar to be happy - return gmdate("Ymd", $stamp) . "T" . gmdate("His", $stamp) . "Z"; - else - $formatstring = $format; - } - - return date($formatstring, $stamp); -} - -/** - * Iterate over an array, replacing every element by expression - * @param $expression The expression to apply, may contain $k for keys and $v for values - * @param $array The array to iterate over - */ -static function map($expression, $array) -{ - static $cache = array(); - - if (!($func = $cache[$expression])) - $func = $cache[$expression] = create_function('$k,$v', "return $expression;"); - - foreach ($array as $k => $v) - $result[$k] = $func($k, $v); - - return (array)$result; -} - -/** - * Send a mail. - * @param $p Header => Content pairs with Body => for the mail body - * @param $p['forcemail'] Send this mail even if we're on a twin or devel machine - * @return nothing useful - */ -static function mail($p) -{ - $headers = $p; - unset($headers['forcemail'], $headers['Body']); - $mail = new it_mail($headers); - $mail->add_body($p['Body']); - - return $mail->send($p); -} - -/** - * Reads a file and returns it as string or in one of several formats. Two params: filename and flags - * @param $filename name of file to read or - for stdin - * @param $p['keyval'] each line of the file is one tab-separated key/value pair, return assoc array - * @param $p['lines'] return file as array of lines without newline - */ -static function file_get($filename, $p = array()) -{ - if (($data = file_get_contents($filename == "-" ? "php://stdin" : $filename)) !== false) - { - if ($p['keyval']) - { - foreach (explode("\n", rtrim($data, "\n")) as $line) - { - $arr = explode("\t", $line, 2); - $result[$arr[0]] = $arr[1]; - } - } - else if ($p['lines']) - $result = explode("\n", rtrim($data, "\n")); - else - $result = $data; - } - - return $result; -} - -/** - * Write data to a file with several serialization modes - * @param $filename name of file to write or - for stdout - * @param $data data to write - * @param $p['keyval'] $data must be an assoc array and is written as tab-separated lines - * @param $p['lines'] write array of lines, appending newline - */ -static function file_put($filename, $data, $p = array()) -{ - if ($p['keyval']) - $data = join("", it::map('"$k\t$v\n"', $data)); - else if ($p['lines']) - $data = count((array)$data) ? join("\n", (array)$data) ."\n" : ""; - - return ($out = fopen($filename == "-" ? "php://stdout" : $filename, "w")) && (fputs($out, $data) === strlen($data)) && fclose($out); -} - -/** - * Create an it_pipe from a file - * @param $fn filename to read. if omitted, stdin is used. - */ -function cat($fn = null) -{ - return new it_pipe(array('fn' => $fn)); -} - -/** - * Create an it_pipe from a command or a lines array - * @param $cmd command to execute, or if it is an array, the lines to use - * @param $args named arguments to fill into cmd. see it::exec for usage - */ -function pipe($cmd, $args = array()) -{ - return new it_pipe(is_string($cmd) ? array('cmd' => $cmd, 'args' => $args) : array('data' => $cmd)); -} - -} -?> |