root/trunk/php/mt.php

Revision 3581, 32.4 kB (checked in by fumiakiy, 8 months ago)

Bumping up numbers to match the current state.

Line 
1<?php
2# Movable Type (r) Open Source (C) 2004-2009 Six Apart, Ltd.
3# This program is distributed under the terms of the
4# GNU General Public License, version 2.
5#
6# $Id: mt.php 2703 2008-07-03 22:19:49Z bchoate $
7
8define('VERSION', '4.25');
9define('VERSION_ID', '4.25');
10define('PRODUCT_VERSION', '4.25');
11
12$PRODUCT_NAME = '__PRODUCT_NAME__';
13if($PRODUCT_NAME == '__PRODUCT' . '_NAME__')
14    $PRODUCT_NAME = 'Movable Type';
15
16define('PRODUCT_NAME', $PRODUCT_NAME);
17
18global $Lexicon;
19$Lexicon = array();
20
21class MT {
22    var $mime_types = array(
23        '__default__' => 'text/html',
24        'css' => 'text/css',
25        'txt' => 'text/plain',
26        'rdf' => 'text/xml',
27        'rss' => 'text/xml',
28        'xml' => 'text/xml',
29    );
30    var $blog_id;
31    var $db;
32    var $config;
33    var $debugging = false;
34    var $caching = false;
35    var $conditional = false;
36    var $log = array();
37    var $warning = array();
38    var $id;
39    var $request;
40    var $http_error;
41    var $cfg_file;
42    var $cache_driver;
43
44    /***
45     * Constructor for MT class. Also declares a global variable
46     * '$mt' and assigns itself to that. There can only be one
47     * instance of this class.
48     */
49    function MT($blog_id = null, $cfg_file = null) {
50        error_reporting(E_ALL ^ E_NOTICE);
51        global $mt;
52        if (isset($mt)) {
53            die("Only one instance of the MT class can be created.");
54        }
55        $this->id = md5(uniqid('MT',true));
56        $this->init($blog_id, $cfg_file);
57    }
58
59    function init($blog_id = null, $cfg_file = null) {
60        if (isset($blog_id)) {
61            $this->blog_id = $blog_id;
62        }
63
64        if (!file_exists($cfg_file)) {
65            $mtdir = dirname(dirname(__FILE__));
66            $cfg_file = $mtdir . DIRECTORY_SEPARATOR . "mt-config.cgi";
67        }
68
69        $this->configure($cfg_file);
70        $this->init_addons();
71        $this->configure_from_db();
72
73        $lang = substr(strtolower($this->config('DefaultLanguage')), 0, 2);
74        if (!@include_once("l10n_$lang.php"))
75            include_once("l10n_en.php");
76
77        if (extension_loaded('mbstring')) {
78            $charset = $this->config('PublishCharset');
79            mb_internal_encoding($charset);
80            mb_http_output($charset);
81        }
82    }
83
84    function init_addons() {
85        $mtdir = dirname(dirname(__FILE__));
86        $path = $mtdir . DIRECTORY_SEPARATOR . "addons";
87        if (is_dir($path)) {
88            $ctx =& $this->context();
89            if ($dh = opendir($path)) {
90                while (($file = readdir($dh)) !== false) {
91                    if ($file == "." || $file == "..") {
92                        continue;
93                    }
94                    $plugin_dir = $path . DIRECTORY_SEPARATOR . $file
95                        . DIRECTORY_SEPARATOR . 'php';
96                    if (is_dir($plugin_dir))
97                        $ctx->add_plugin_dir($plugin_dir);
98                }
99                closedir($dh);
100            }
101        }
102    }
103
104    function init_plugins() {
105        $plugin_paths = $this->config('PluginPath');
106        $ctx =& $this->context();
107
108        foreach ($plugin_paths as $path) {
109            if ($dh = @opendir($path)) {
110                 while (($file = readdir($dh)) !== false) {
111                     if ($file == "." || $file == "..")
112                         continue;
113                     $plugin_dir = $path . DIRECTORY_SEPARATOR . $file
114                         . DIRECTORY_SEPARATOR . 'php';
115                     if (is_dir($plugin_dir))
116                         $ctx->add_plugin_dir($plugin_dir);
117                 }
118                 closedir($dh);
119            }
120        }
121
122        $plugin_dir = $this->config('PHPDir') . DIRECTORY_SEPARATOR
123            . 'plugins';
124        if (is_dir($plugin_dir))
125            $ctx->add_plugin_dir($plugin_dir);
126
127        # Load any php directories found during the 'init_addons' loop
128        foreach ($ctx->plugins_dir as $plugin_dir)
129            if (is_dir($plugin_dir))
130                $this->load_plugin($plugin_dir);
131    }
132
133    function load_plugin($plugin_dir) {
134        $ctx =& $this->context();
135        // global filters have to be handled differently from
136        // tag attributes, so this causes them to be recognized
137        // as they should...
138        if ($dh = opendir($plugin_dir)) {
139            while (($file = readdir($dh)) !== false) {
140                if (preg_match('/^modifier\.(.+?)\.php$/', $file, $matches)) {
141                    $ctx->add_global_filter($matches[1]);
142                } elseif (preg_match('/^init\.(.+?)\.php$/', $file, $matches)) {
143                    // load 'init' plugin file
144                    require_once($file);
145                }
146            }
147            closedir($dh);
148        }
149    }
150
151    /***
152     * Retreives a handle to the database and assigns it to
153     * the member variable 'db'.
154     */
155    function &db() {
156        if (isset($this->db)) return $this->db;
157
158        require_once("mtdb_".$this->config('DBDriver').".php");
159        $mtdbclass = 'MTDatabase_'.$this->config('DBDriver');
160        $this->db = new $mtdbclass($this->config('DBUser'),
161            $this->config('DBPassword'), $this->config('Database'),
162            $this->config('DBHost'), $this->config('DBPort'), $this->config('DBSocket'));
163        return $this->db;
164    }
165
166    /***
167     * Retreives a handle to the cache driver.
168     */
169    function &cache_driver() {
170        if (isset($this->cache_driver)) return $this->cache_driver;
171   
172        # Check for memcached enabled
173        $servers  = $this->config['MemcachedServers'];
174        if (isset($servers)) {
175            if (extension_loaded('memcache')) {
176                require_once("mtcache_memcached.php");
177                $this->cache_driver = new MTCache_memcached($servers);
178            }
179        } else {
180            require_once("mtcache_session.php");
181            $this->cache_driver = new MTCache_session();
182        }
183        return $this->cache_driver;
184    }
185
186    function config($id, $value = null) {
187        $id = strtolower($id);
188        if (isset($value))
189            $this->config[$id] = $value;
190        return $this->config[$id];
191    }
192
193    /***
194     * Loads configuration data from mt.cfg and mt-db-pass.cgi files.
195     * Stores content in the 'config' member variable.
196     */
197    function configure($file = null) {
198        if (isset($this->config)) return $config;
199
200        $this->cfg_file = $file;
201
202        $cfg = array();
203        $type_array = array('pluginpath', 'alttemplate', 'outboundtrackbackdomains', 'memcachedservers');
204        $type_hash  = array('commenterregistration');
205        if ($fp = file($file)) {
206            foreach ($fp as $line) {
207                // search through the file
208                if (!ereg('^\s*\#',$line)) {
209                    // ignore lines starting with the hash symbol
210                    if (preg_match('/^\s*(\S+)\s+(.*)$/', $line, $regs)) {
211                        $key = strtolower(trim($regs[1]));
212                        $value = trim($regs[2]);
213                        if (in_array($key, $type_array)) {
214                            $cfg[$key][] = $value;
215                        }
216                        elseif (in_array($key, $type_hash)) {
217                            $hash = preg_split('/\=/', $value, 2);
218                            $cfg[$key][strtolower(trim($hash[0]))] = trim($hash[1]);
219                        } else {
220                            $cfg[$key] = $value;
221                        }
222                    }
223                }
224            }
225        } else {
226            die("Unable to open configuration file $file");
227        }
228
229        // setup directory locations
230        // location of mt.php
231        $cfg['phpdir'] = realpath(dirname(__FILE__));
232        // path to MT directory
233        $cfg['mtdir'] = realpath(dirname($file));
234        // path to handlers
235        $cfg['phplibdir'] = $cfg['phpdir'] . DIRECTORY_SEPARATOR . 'lib';
236
237        $cfg['dbhost'] or $cfg['dbhost'] = 'localhost'; // default to localhost
238        $driver = $cfg['objectdriver'];
239        $driver = preg_replace('/^DB[ID]::/', '', $driver);
240        $driver or $driver = 'mysql';
241        $cfg['dbdriver'] = strtolower($driver);
242   
243        if ((strlen($cfg['database'])<1 || strlen($cfg['dbuser'])<1)) {
244            if (($cfg['dbdriver'] != 'sqlite') && ($cfg['dbdriver'] != 'mssqlserver')) {
245                die("Unable to read database or username");
246            }
247        }
248
249        // Changes dbdriver from native to PDO, if we can.
250        // * PHP Version >= 5.0
251        // * DBDriver == sqlite / with out UseSQLite2
252        // * PDO and PDO_SQLITE extensions loaded
253        if (version_compare(PHP_VERSION, '5.0') > 0
254            && $cfg['dbdriver'] == 'sqlite'
255            && !isset($cfg['usesqlite2'])
256            && extension_loaded('pdo')
257            && extension_loaded('pdo_sqlite'))
258        {
259            $cfg['dbdriver'] = 'pdo_sqlite';
260        }
261        $this->config =& $cfg;
262        $this->config_defaults();
263
264        // read in the database password
265        if (!isset($cfg['dbpassword'])) {
266            $db_pass_file = $cfg['mtdir'] . DIRECTORY_SEPARATOR . 'mt-db-pass.cgi';
267            if (file_exists($db_pass_file)) {
268                $password = implode('', file($db_pass_file));
269                $password = trim($password, "\n\r\0");
270                $cfg['dbpassword'] = $password;
271            }
272        }
273
274        // set up include path
275        // add MT-PHP 'plugins' and 'lib' directories to the front
276        // of the existing PHP include path:
277        if (strtoupper(substr(PHP_OS, 0,3) == 'WIN')) {
278            $path_sep = ';';
279        } else {
280            $path_sep = ':';
281        }
282        ini_set('include_path',
283            $cfg['phpdir'] . DIRECTORY_SEPARATOR . "lib" . $path_sep .
284            $cfg['phpdir'] . DIRECTORY_SEPARATOR . "extlib" . $path_sep .
285            $cfg['phpdir'] . DIRECTORY_SEPARATOR . "extlib" . DIRECTORY_SEPARATOR . "smarty" . DIRECTORY_SEPARATOR . "libs" . $path_sep .
286            ini_get('include_path')
287        );
288    }
289
290    function configure_from_db() {
291        $cfg =& $this->config;
292        $mtdb =& $this->db();
293        $db_config = $mtdb->fetch_config();
294        if ($db_config) {
295            $data = $db_config['config_data'];
296            $data = preg_split('/[\r?\n]/', $data);
297            foreach ($data as $line) {
298                // search through the file
299                if (!ereg('^\s*\#',$line)) {
300                    // ignore lines starting with the hash symbol
301                    if (preg_match('/^\s*(\S+)\s+(.*)$/', $line, $regs)) {
302                        $key = strtolower(trim($regs[1]));
303                        $value = trim($regs[2]);
304                        if (($key === 'pluginswitch') || ($key === 'pluginschemaversion')) { # special case for hash
305                            if (preg_match('/^(.+)=(.+)$/', $value, $match))
306                                $cfg[$key][trim($match[1])] = trim($match[2]);
307                        } else {
308                            $cfg[$key] or $cfg[$key] = $value;
309                        }
310                    }
311                }
312            }
313            if ($cfg['dbdriver'] == 'mysql' or $cfg['dbdriver'] == 'postgres') {
314                if ($cfg['sqlsetnames']) {
315                    $Charset = array( 
316                        'postgres' => array('utf-8' => 'UNICODE', 'shift_jis' => 'SJIS', 'euc-jp' => 'EUC_JP'),
317                        'mysql' => array('utf-8' => 'utf8', 'shift_jis' => 'sjis', 'euc-jp' => 'ujis'));
318                    $lang = $Charset[$cfg['dbdriver']][strtolower($cfg['publishcharset'])];
319                    if ($lang) {
320                        $mtdb->query("SET NAMES '$lang'");
321                    }
322                }
323            }           
324        }
325    }
326
327    function config_defaults() {
328        $cfg =& $this->config;
329        // assign defaults:
330        if (substr($cfg['cgipath'], strlen($cfg['cgipath']) - 1, 1) != '/')
331            $cfg['cgipath'] .= '/'; 
332        isset($cfg['staticwebpath']) or
333            $cfg['staticwebpath'] = $cfg['cgipath'] . 'mt-static/';
334        isset($cfg['publishcharset']) or
335            $cfg['publishcharset'] = 'utf-8';
336        isset($cfg['trackbackscript']) or
337            $cfg['trackbackscript'] = 'mt-tb.cgi';
338        isset($cfg['adminscript']) or
339            $cfg['adminscript'] = 'mt.cgi';
340        isset($cfg['commentscript']) or
341            $cfg['commentscript'] = 'mt-comments.cgi';
342        isset($cfg['atomscript']) or
343            $cfg['atomscript'] = 'mt-atom.cgi';
344        isset($cfg['xmlrpcscript']) or
345            $cfg['xmlrpcscript'] = 'mt-xmlrpc.cgi';
346        isset($cfg['searchscript']) or
347            $cfg['searchscript'] = 'mt-search.cgi';
348        isset($cfg['defaultlanguage']) or
349            $cfg['defaultlanguage'] = 'en_US';
350        isset($cfg['globalsanitizespec']) or
351            $cfg['globalsanitizespec'] = 'a href,b,i,br/,p,strong,em,ul,ol,li,blockquote,pre';
352        isset($cfg['signonurl']) or
353            $cfg['signonurl'] = 'https://www.typekey.com/t/typekey/login?';
354        isset($cfg['signoffurl']) or
355            $cfg['signoffurl'] = 'https://www.typekey.com/t/typekey/logout?';
356        isset($cfg['identityurl']) or
357            $cfg['identityurl'] = 'http://profile.typekey.com/';
358        isset($cfg['publishcommentericon']) or
359            $cfg['publishcommentericon'] = '1';
360        isset($cfg['allowcomments']) or
361            $cfg['allowcomments'] = '1';
362        isset($cfg['allowpings']) or
363            $cfg['allowpings'] = '1';
364        isset($cfg['indexbasename']) or
365            $cfg['indexbasename'] = 'index';
366        isset($cfg['typekeyversion']) or
367            $cfg['typekeyversion'] = '1.1';
368        isset($cfg['assetcachedir']) or
369            $cfg['assetcachedir'] = 'assets_c';
370        isset($cfg['userpicthumbnailsize']) or
371            $cfg['userpicthumbnailsize'] = '100';
372        isset($cfg['pluginpath']) or
373            $cfg['pluginpath'] = array($this->config('MTDir') . DIRECTORY_SEPARATOR . 'plugins');
374        isset($cfg['timeoffset']) or
375            $cfg['timeoffset'] = '0';
376        isset($cfg['includesdir']) or
377            $cfg['includesdir'] = 'includes_c';
378        isset($cfg['searchmaxresults']) or
379            $cfg['searchmaxresults'] = '20';
380        isset($cfg['maxresults']) or
381            $cfg['maxresults'] = $cfg['searchmaxresults'];
382        isset($cfg['singlecommunity']) or
383            $cfg['singlecommunity'] = '0';
384        isset($cfg['usersessioncookiename']) or
385            $cfg['usersessioncookiename'] = 'DEFAULT';
386        isset($cfg['usersessioncookiedomain']) or
387            $cfg['usersessioncookiedomain'] = '<$MTBlogHost exclude_port="1"$>';
388        isset($cfg['usersessioncookiepath']) or
389            $cfg['usersessioncookiepath'] = 'DEFAULT';
390        isset($cfg['usersessioncookietimeout']) or
391            $cfg['usersessioncookietimeout'] = 60*60*4;
392        isset($cfg['commenterregistration']) or
393            $cfg['commenterregistration'] = array('allow' => 1 );
394    }
395
396    function configure_paths($blog_site_path) {
397        if (preg_match('/^\./', $blog_site_path)) {
398            // relative address, so tack on the MT dir in front
399            $blog_site_path = $this->config('MTDir') .
400                DIRECTORY_SEPARATOR . $blog_site_path;
401        }
402        $this->config('PHPTemplateDir') or
403            $this->config('PHPTemplateDir', $blog_site_path .
404            DIRECTORY_SEPARATOR . 'templates');
405        $this->config('PHPCacheDir') or
406            $this->config('PHPCacheDir', $blog_site_path .
407            DIRECTORY_SEPARATOR . 'cache');
408
409        $ctx =& $this->context();
410        $ctx->template_dir = $this->config('PHPTemplateDir');
411        $ctx->compile_dir = $ctx->template_dir . '_c';
412        $ctx->cache_dir = $this->config('PHPCacheDir');
413    }
414
415    /***
416     * Mainline handler function.
417     */
418    function view($blog_id = null) {
419        require_once("MTUtil.php");
420
421        $blog_id or $blog_id = $this->blog_id;
422
423        $ctx =& $this->context();
424        $this->init_plugins();
425        $ctx->caching = $this->caching;
426
427        // Some defaults...
428        $mtdb =& $this->db();
429        $ctx->mt->db =& $mtdb;
430
431        // Set up our customer error handler
432        set_error_handler(array(&$this, 'error_handler'));
433
434        // User-specified request through request variable
435        $path = $this->request;
436
437        // Apache request
438        if (!$path && $_SERVER['REQUEST_URI']) {
439            $path = $_SERVER['REQUEST_URI'];
440            // strip off any query string...
441            $path = preg_replace('/\?.*/', '', $path);
442            // strip any duplicated slashes...
443            $path = preg_replace('!/+!', '/', $path);
444        }
445
446        // IIS request by error document...
447        if (preg_match('/IIS/', $_SERVER['SERVER_SOFTWARE'])) {
448            // assume 404 handler
449            if (preg_match('/^\d+;(.*)$/', $_SERVER['QUERY_STRING'], $matches)) {
450                $path = $matches[1];
451                $path = preg_replace('!^http://[^/]+!', '', $path);
452                if (preg_match('/\?(.+)?/', $path, $matches)) {
453                    $_SERVER['QUERY_STRING'] = $matches[1];
454                    $path = preg_replace('/\?.*$/', '', $path);
455                }
456            }
457        }
458
459        // now set the path so it may be queried
460        $this->request = $path;
461
462        // When we are invoked as an ErrorDocument, the parameters are
463        // in the environment variables REDIRECT_*
464        if (isset($_SERVER['REDIRECT_QUERY_STRING'])) {
465            // todo: populate $_GET and QUERY_STRING with REDIRECT_QUERY_STRING
466            $_SERVER['QUERY_STRING'] = getenv('REDIRECT_QUERY_STRING');
467        }
468
469        if (preg_match('/\.(\w+)$/', $path, $matches)) {
470            $req_ext = strtolower($matches[1]);
471        }
472
473        $this->blog_id = $blog_id;
474
475        $data =& $this->resolve_url($path);
476        if (!$data) {
477            // 404!
478            $this->http_error = 404;
479            header("HTTP/1.1 404 Not found");
480            return $ctx->error($this->translate("Page not found - [_1]", $path), E_USER_ERROR);
481        }
482
483        $info =& $data['fileinfo'];
484        $fi_path = $info['fileinfo_url'];
485        $fid = $info['fileinfo_id'];
486        $at = $info['fileinfo_archive_type'];
487        $ts = $info['fileinfo_startdate'];
488        $tpl_id = $info['fileinfo_template_id'];
489        $cat = $info['fileinfo_category_id'];
490        $auth = $info['fileinfo_author_id'];
491        $entry_id = $info['fileinfo_entry_id'];
492        $blog_id = $info['fileinfo_blog_id'];
493        $blog =& $data['blog'];
494        if ($at == 'index') {
495            $at = null;
496            $ctx->stash('index_archive', true);
497        } else {
498            $ctx->stash('index_archive', false);
499        }
500        $tts = $data['template']['template_modified_on'];
501        if ($tts) {
502            $tts = offset_time(datetime_to_timestamp($tts), $blog);
503        }
504        $ctx->stash('template_timestamp', $tts);
505        $ctx->stash('template_created_on', $data['template']['template_created_on']);
506
507        $page_layout = $data['blog']['blog_page_layout'];
508        $columns = get_page_column($page_layout);
509        $vars =& $ctx->__stash['vars'];
510        $vars['page_columns'] = $columns;
511        $vars['page_layout'] = $page_layout;
512
513        if (isset($data['template']['template_identifier']))
514            $vars[$data['template']['template_identifier']] = 1;
515
516        $this->configure_paths($blog['blog_site_path']);
517
518        // start populating our stash
519        $ctx->stash('blog_id', $blog_id);
520        $ctx->stash('local_blog_id', $blog_id);
521        $ctx->stash('blog', $blog);
522        $ctx->stash('build_template_id', $tpl_id);
523
524        // conditional get support...
525        if ($this->caching) {
526            $this->cache_modified_check = true;
527        }
528        if ($this->conditional) {
529            $last_ts = $blog['blog_children_modified_on'];
530            $last_modified = $ctx->_hdlr_date(array('ts' => $last_ts, 'format' => '%a, %d %b %Y %H:%M:%S GMT', 'language' => 'en', 'utc' => 1), $ctx);
531            $this->doConditionalGet($last_modified);
532        }
533
534        $cache_id = $blog_id.';'.$fi_path;
535        if (!$ctx->is_cached('mt:'.$tpl_id, $cache_id)) {
536            if (isset($at) && ($at != 'Category')) {
537                global $_archivers;
538                require_once("archive_lib.php");
539                global $_archivers;
540                if (!isset($_archivers[$at])) {
541                    // 404
542                    $this->http_errr = 404;
543                    header("HTTP/1.1 404 Not Found");
544                    return $ctx->error($this->translate("Page not found - [_1]", $at), E_USER_ERROR);
545                }
546                $archiver = $_archivers[$at];
547                $archiver->template_params($ctx);
548            }
549
550            if ($cat) {
551                $archive_category = $mtdb->fetch_category($cat);
552                $ctx->stash('category', $archive_category);
553                $ctx->stash('archive_category', $archive_category);
554            }
555            if ($auth) {
556                $archive_author = $mtdb->fetch_author($auth);
557                $ctx->stash('author', $archive_author);
558                $ctx->stash('archive_author', $archive_author);
559            }
560            if (isset($at)) {
561                if (($at != 'Category') && isset($ts)) {
562                    list($ts_start, $ts_end) = $archiver->get_range($ctx, $ts);
563                    $ctx->stash('current_timestamp', $ts_start);
564                    $ctx->stash('current_timestamp_end', $ts_end);
565                }
566                $ctx->stash('current_archive_type', $at);
567            }
568   
569            if (isset($entry_id) && ($entry_id) && ($at == 'Individual' || $at == 'Page')) {
570                if ($at == 'Individual') {
571                    $entry =& $mtdb->fetch_entry($entry_id);
572                } elseif($at == 'Page') {
573                    $entry =& $mtdb->fetch_page($entry_id);
574                }
575                $ctx->stash('entry', $entry);
576                $ctx->stash('current_timestamp', $entry['entry_authored_on']);
577            }
578
579            if ($at == 'Category') {
580                $vars =& $ctx->__stash['vars'];
581                $vars['archive_class']            = "category-archive";
582                $vars['category_archive']         = 1;
583                $vars['archive_template']         = 1;
584                $vars['archive_listing']          = 1;
585                $vars['module_category_archives'] = 1;
586            }
587        }
588
589        $output = $ctx->fetch('mt:'.$tpl_id, $cache_id);
590
591        $this->http_error = 200;
592        header("HTTP/1.1 200 OK");
593        // content-type header-- need to supplement with charset
594        $content_type = $ctx->stash('content_type');
595
596        if (!isset($content_type)) {
597            $content_type = $this->mime_types['__default__'];
598            if ($req_ext && (isset($this->mime_types[$req_ext]))) {
599                $content_type = $this->mime_types[$req_ext];
600            }
601        }
602        $charset = $this->config('PublishCharset');
603        if (isset($charset)) {
604            if (!preg_match('/charset=/', $content_type))
605                $content_type .= '; charset=' . $charset;
606        }
607        header("Content-Type: $content_type");
608
609        // finally, issue output
610        $output = preg_replace('/^\s*/', '', $output);
611        echo $output;
612
613        // if warnings found, show it.
614        if (!empty($this->warning)) {
615            $this->_dump($this->warning);
616        }
617
618        if ($this->debugging) {
619            $this->log("Queries: ".$mtdb->num_queries);
620            $this->log("Queries executed:");
621            $queries = $mtdb->savedqueries;
622            foreach ($queries as $q) {
623                $this->log($q);
624            }
625            $this->log_dump();
626        }
627        restore_error_handler();
628    }
629
630    function &resolve_url($path) {
631        $data =& $this->db->resolve_url($path, $this->blog_id);
632        if ( isset($data)
633            && isset($data['fileinfo']['fileinfo_entry_id'])
634            && is_numeric($data['fileinfo']['fileinfo_entry_id'])
635        ) {
636            if (strtolower($data['templatemap']['templatemap_archive_type']) == 'page') {
637                $entry = $this->db->fetch_page($data['fileinfo']['fileinfo_entry_id']);
638            } else {
639                $entry = $this->db->fetch_entry($data['fileinfo']['fileinfo_entry_id']);
640            }
641            require_once('function.mtentrystatus.php');
642            if (!isset($entry) || $entry['entry_status'] != STATUS_RELEASE)
643                return;
644        }
645        return $data;
646    }
647
648    function doConditionalGet($last_modified) {
649        // Thanks to Simon Willison...
650        //   http://simon.incutio.com/archive/2003/04/23/conditionalGet
651        // A PHP implementation of conditional get, see
652        //   http://fishbowl.pastiche.org/archives/001132.html
653        $etag = '"'.md5($last_modified).'"';
654        // Send the headers
655        header("Last-Modified: $last_modified");
656        header("ETag: $etag");
657        // See if the client has provided the required headers
658        $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
659            stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
660            false;
661        $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
662            stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : 
663            false;
664        if (!$if_modified_since && !$if_none_match) {
665            return;
666        }
667        // At least one of the headers is there - check them
668        if ($if_none_match && $if_none_match != $etag) {
669            return; // etag is there but doesn't match
670        }
671        if ($if_modified_since && $if_modified_since != $last_modified) {
672            return; // if-modified-since is there but doesn't match
673        }
674        // Nothing has changed since their last request - serve a 304 and exit
675        header('HTTP/1.1 304 Not Modified');
676        exit;
677    }
678
679    function display($tpl, $cid = null) {
680        $ctx =& $this->context();
681        $this->init_plugins();
682        $blog =& $ctx->stash('blog');
683        if (!$blog) {
684            $db =& $this->db();
685            $ctx->mt->db =& $db;
686            $blog =& $db->fetch_blog($this->blog_id);
687            $ctx->stash('blog', $blog);
688            $ctx->stash('blog_id', $this->blog_id);
689            $ctx->stash('local_blog_id', $this->blog_id);
690            $this->configure_paths($blog['blog_site_path']);
691        }
692        return $ctx->display($tpl, $cid);
693    }
694
695    function fetch($tpl, $cid = null) {
696        $ctx =& $this->context();
697        $this->init_plugins();
698        $blog =& $ctx->stash('blog');
699        if (!$blog) {
700            $db =& $this->db();
701            $ctx->mt->db =& $db;
702            $blog =& $db->fetch_blog($this->blog_id);
703            $ctx->stash('blog', $blog);
704            $ctx->stash('blog_id', $this->blog_id);
705            $ctx->stash('local_blog_id', $this->blog_id);
706            $this->configure_paths($blog['blog_site_path']);
707        }
708        return $ctx->fetch($tpl, $cid);
709    }
710
711    function _dump($dump) {
712        if ($_SERVER['REMOTE_ADDR']) {
713            // web view...
714            echo "<div class=\"debug\" style=\"border:1px solid red; margin:0.5em; padding: 0 1em; text-align:left; background-color:#ddd; color:#000\"><pre>";
715            echo implode("\n", $dump);
716            echo "</pre></div>\n\n";
717        } else {
718            // console view...
719            $stderr = fopen('php://stderr', 'w'); 
720            fwrite($stderr,implode("\n", $dump)); 
721            echo (implode("\n", $dump)); 
722            fclose($stderr);
723        }
724    }
725
726    function log_dump() {
727        $this->_dump($this->log);
728    }
729
730    function error_handler($errno, $errstr, $errfile, $errline) {
731        if ($errno & (E_ALL ^ E_NOTICE)) {
732            if (version_compare(phpversion(), '4.3.0', '>=')) {
733                $charset = $this->config('PublishCharset');
734                $errstr = htmlentities($errstr, ENT_COMPAT, $charset);
735                $errfile = htmlentities($errfile, ENT_COMPAT, $charset);
736            } else {
737                $errstr = htmlentities($errstr, ENT_COMPAT);
738                $errfile = htmlentities($errfile, ENT_COMPAT);
739            }
740            $mtphpdir = $this->config('PHPDir');
741            $ctx =& $this->context();
742            $ctx->stash('blog_id', $this->blog_id);
743            $ctx->stash('local_blog_id', $this->blog_id);
744            $ctx->stash('blog', $this->db->fetch_blog($this->blog_id));
745            $ctx->stash('error_message', $errstr."<!-- file: $errfile; line: $errline; code: $errno -->");
746            $ctx->stash('error_code', $errno);
747            $http_error = $this->http_error;
748            if (!$http_error) {
749                $http_error = 500;
750            }
751            $ctx->stash('http_error', $http_error);
752            $ctx->stash('error_file', $errfile);
753            $ctx->stash('error_line', $errline);
754            $ctx->template_dir = $mtphpdir . DIRECTORY_SEPARATOR . 'tmpl';
755            $ctx->caching = 0;
756            $ctx->stash('StaticWebPath', $this->config('StaticWebPath'));
757            $ctx->stash('PublishCharset', $this->config('PublishCharset'));
758            $charset = $this->config('PublishCharset');
759            $out = $ctx->tag('Include', array('type' => 'dynamic_error', 'dynamic_error' => 1, 'system_template' => 1));
760            if (isset($out)) {
761                header("Content-type: text/html; charset=".$charset);
762                echo $out;
763            } else {
764                header("HTTP/1.1 500 Server Error");
765                header("Content-type: text/plain");
766                echo "Error executing error template.";
767            }
768            exit;
769        }
770    }
771
772    /***
773     * Retrieves a context and rendering object.
774     */
775    function &context() {
776        static $ctx;
777        if (isset($ctx)) return $ctx;
778
779        require_once('MTViewer.php');
780        $ctx = new MTViewer($this);
781        $ctx->mt =& $this;
782        $mtphpdir = $this->config('PHPDir');
783        $mtlibdir = $this->config('PHPLibDir');
784        $ctx->compile_check = 1;
785        $ctx->caching = false;
786        $ctx->plugins_dir[] = $mtlibdir;
787        $ctx->plugins_dir[] = $mtphpdir . DIRECTORY_SEPARATOR . "plugins";
788        if ($this->debugging) {
789            $ctx->debugging_ctrl = 'URL';
790            $ctx->debug_tpl = $mtphpdir . DIRECTORY_SEPARATOR .
791                'extlib' . DIRECTORY_SEPARATOR .
792                'smarty' . DIRECTORY_SEPARATOR . "libs" . DIRECTORY_SEPARATOR .
793                'debug.tpl';
794        }
795        #if (isset($this->config('SafeMode')) && ($this->config('SafeMode'))) {
796        #    // disable PHP support
797        #    $ctx->php_handling = SMARTY_PHP_REMOVE;
798        #}
799        return $ctx;
800    }
801
802    function log($msg = null) {
803        $this->log[] = $msg;
804    }
805
806    function translate($str, $params = null) {
807        if ( ( $params !== null ) && ( !is_array($params) ) )
808            $params = array( $params );
809        return translate_phrase($str, $params);
810    }
811
812    function translate_templatized_item($str) {
813        return translate_phrase($str[1]);
814    }
815
816    function translate_templatized($tmpl) {
817        $cb = array($this, 'translate_templatized_item');
818        $out = preg_replace_callback('/<(?:_|mt)_trans phrase="(.+?)".*?>/i', $cb, $tmpl);
819        return $out;
820    }
821
822    function warning_log($str) {
823        $this->warning[] = $str;
824    }
825}
826
827function is_valid_email($addr) {
828    if (preg_match('/[ |\t|\r|\n]*\"?([^\"]+\"?@[^ <>\t]+\.[^ <>\t][^ <>\t]+)[ |\t|\r|\n]*/', $addr, $matches)) {
829        return $matches[1];
830    } else {
831        return 0;
832    }
833}
834
835$spam_protect_map = array(':' => '&#58;', '@' => '&#64;', '.' => '&#46;');
836function spam_protect($str) {
837    global $spam_protect_map;
838    return strtr($str, $spam_protect_map);
839}
840
841function datetime_to_timestamp($dt) {
842    $dt = preg_replace('/[^0-9]/', '', $dt);
843    $ts = mktime(substr($dt, 8, 2), substr($dt, 10, 2), substr($dt, 12, 2), substr($dt, 4, 2), substr($dt, 6, 2), substr($dt, 0, 4));
844    return $ts;
845}
846
847function offset_time($ts, $blog = null, $dir = null) {
848    if (isset($blog)) {
849        if (!is_array($blog)) {
850            global $mt;
851            $blog = $mt->db->fetch_blog($blog);
852        }
853        $offset = $blog['blog_server_offset'];
854    } else {
855        global $mt;
856        $offset = $mt->config('TimeOffset');
857    }
858    intval($offset) or $offset = 0;
859    $tsa = localtime($ts);
860
861    if ($tsa[8]) {  // daylight savings offset
862        $offset++;
863    }
864    if ($dir == '-') {
865        $offset *= -1;
866    }
867    $ts += $offset * 3600;
868    return $ts;
869}
870function _strip_index($url, $blog) {
871    global $mt;
872    $index = $mt->config('IndexBasename');
873    $ext = $blog['blog_file_extension'];
874    if ($ext != '') $ext = '.' . $ext;
875    $index = preg_quote($index . $ext);
876    $url = preg_replace("/\/$index(#.*)?$/", '/$1', $url);
877    return $url;
878}
879
880function translate_phrase_param($str, $params = null) {
881    if (is_array($params) && (strpos($str, '[_') !== false)) {
882        for ($i = 1; $i <= count($params); $i++) {
883            $str = preg_replace("/\\[_$i\\]/", $params[$i-1], $str);
884        }
885    }
886    return $str;
887}
888?>
Note: See TracBrowser for help on using the browser.