From 7773c26f15b2907dfb9fc7cd998271e3eaf81b80 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 19 Jul 2016 10:55:27 +0200 Subject: [PATCH 1/2] fixing broken message ID --- i18n/de.json | 2 +- i18n/fr.json | 2 +- i18n/pl.json | 2 +- i18n/sl.json | 2 +- i18n/zh.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/de.json b/i18n/de.json index 3d705ee2..60353d9f 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -27,7 +27,7 @@ "Paste was properly deleted.": "Text wurde erfolgreich gelöscht.", "PrivateBin": "PrivateBin", - "PrivateBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": + "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": "PrivateBin ist ein minimalistischer, quelloffener \"Pastebin\"-artiger Dienst, bei dem der Server keinerlei Kenntnis der Inhalte hat. Die Daten werden im Browser mit 256 Bit AES ver- und entschlüsselt. Weitere Informationen sind auf der Projektseite zu finden.", "Because ignorance is bliss": "Unwissenheit ist ein Segen", diff --git a/i18n/fr.json b/i18n/fr.json index 0622f9ef..50d56023 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -27,7 +27,7 @@ "Paste was properly deleted.": "Le paste a été correctement supprimé.", "PrivateBin": "PrivateBin", - "PrivateBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": + "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": "PrivateBin est un 'pastebin' (ou gestionnaire d'extraits de texte et de code source) minimaliste et open source, dans lequel le serveur n'a aucune connaissance des données envoyées. Les données sont chiffrées/déchiffrées dans le navigateur par un chiffrage AES 256 bits. Plus d'informations sur la page du projet.", "Because ignorance is bliss": "Parce que l'ignorance est le bonheur", diff --git a/i18n/pl.json b/i18n/pl.json index 72217fc2..6a1a63e8 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -27,7 +27,7 @@ "Paste was properly deleted.": "Wklejka usunięta poprawnie.", "PrivateBin": "PrivateBin", - "PrivateBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": + "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": "PrivateBin jest minimalistycznym, otwartoźródłowym serwisem typu pastebin, w którym serwer nie ma jakichkolwiek informacji o tym, co jest wklejane. Dane są szyfrowane i deszyfrowane w przeglądarce z użyciem 256-bitowego klucza AES. Więcej informacji na stronie projektu.", "Because ignorance is bliss": "Ponieważ ignorancja jest cnotą", diff --git a/i18n/sl.json b/i18n/sl.json index bcc4791b..a159bf8b 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -27,7 +27,7 @@ "Paste was properly deleted.": "Prilepek je uspešno izbrisan.", "PrivateBin": "PrivateBin", - "PrivateBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": + "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": "PrivateBin je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani v brskalniku z uporabo 256 bitnega AES. Več informacij na < href=\"https://github.com/PrivateBin/PrivateBin/wiki\">spletni strani projekta..", "Because ignorance is bliss": "Ker kar ne veš ne boli.", diff --git a/i18n/zh.json b/i18n/zh.json index 6c572d03..6a407697 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -27,7 +27,7 @@ "Paste was properly deleted.": "粘贴已被正确删除。", "PrivateBin": "PrivateBin", - "PrivateBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": + "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": "PrivateBin是一个极简,开源,对粘贴内容毫不知情的在线粘贴板,数据在浏览器内进行AES-256加密。更多信息请查看项目主页。", "Because ignorance is bliss": "因为无知是福", From c5606a47fe4de7afd5d49f33f00ef104cfc10c66 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 19 Jul 2016 14:02:26 +0200 Subject: [PATCH 2/2] refactoring away RainTPL and templating, resolves #36 --- lib/RainTPL.php | 1164 ----------------- lib/privatebin.php | 6 +- lib/view.php | 59 + ...rap-compact.html => bootstrap-compact.php} | 214 +-- tpl/bootstrap-dark-page.html | 212 --- tpl/bootstrap-dark-page.php | 252 ++++ tpl/bootstrap-dark.html | 212 --- tpl/bootstrap-dark.php | 252 ++++ tpl/bootstrap-page.html | 212 --- tpl/bootstrap-page.php | 252 ++++ tpl/bootstrap.html | 212 --- tpl/bootstrap.php | 252 ++++ tpl/page.html | 121 -- tpl/page.php | 157 +++ tst/{RainTPL.php => view.php} | 29 +- 15 files changed, 1369 insertions(+), 2237 deletions(-) delete mode 100644 lib/RainTPL.php create mode 100644 lib/view.php rename tpl/{bootstrap-compact.html => bootstrap-compact.php} (50%) delete mode 100644 tpl/bootstrap-dark-page.html create mode 100644 tpl/bootstrap-dark-page.php delete mode 100644 tpl/bootstrap-dark.html create mode 100644 tpl/bootstrap-dark.php delete mode 100644 tpl/bootstrap-page.html create mode 100644 tpl/bootstrap-page.php delete mode 100644 tpl/bootstrap.html create mode 100644 tpl/bootstrap.php delete mode 100644 tpl/page.html create mode 100644 tpl/page.php rename tst/{RainTPL.php => view.php} (83%) diff --git a/lib/RainTPL.php b/lib/RainTPL.php deleted file mode 100644 index dc09054e..00000000 --- a/lib/RainTPL.php +++ /dev/null @@ -1,1164 +0,0 @@ - - * - * True: php tags are enabled into the template - * False: php tags are disabled into the template and rendered as html - * - * @var bool - */ - static $php_enabled = false; - - - /** - * Debug mode flag - * - * True: debug mode is used, syntax errors are displayed directly in template. Execution of script is not terminated. - * False: exception is thrown on found error. - * - * @var bool - */ - static $debug = false; - - // ------------------------- - - - // ------------------------- - // RAINTPL VARIABLES - // ------------------------- - - /** - * Is the array where RainTPL keep the variables assigned - * - * @var array - */ - public $var = array(); - - /** - * variables to keep the template directories and info - * - * @var array - */ - protected $tpl = array(); // - - /** - * static cache enabled / disabled - * - * @var bool - */ - protected $cache = false; - - /** - * identify only one cache - * - * @var string - */ - protected $cache_id = ''; - - /** - * takes all the config to create the md5 of the file - * - * @var array the file - */ - protected static $config_name_sum = array(); - - // ------------------------- - - - - /** - * default cache expire time = hour - * - * @const int - */ - const CACHE_EXPIRE_TIME = 3600; - - - - /** - * Assign variable - * eg. $t->assign('name','mickey'); - * - * @access public - * @param mixed $variable_name Name of template variable or associative array name/value - * @param mixed $value value assigned to this variable. Not set if variable_name is an associative array - */ - public function assign( $variable, $value = null ){ - if( is_array( $variable ) ) - $this->var += $variable; - else - $this->var[ $variable ] = $value; - } - - - - /** - * Draw the template - * eg. $html = $tpl->draw( 'demo', TRUE ); // return template in string - * or $tpl->draw( $tpl_name ); // echo the template - * - * @access public - * @param string $tpl_name template to load - * @param boolean $return_string true=return a string, false=echo the template - * @return string - */ - public function draw( $tpl_name, $return_string = false ){ - - try { - // compile the template if necessary and set the template filepath - $this->check_template( $tpl_name ); - } catch (RainTpl_Exception $e) { - $output = $this->printDebug($e); - die($output); - } - - // Cache is off and, return_string is false - // Rain just echo the template - - if( !$this->cache && !$return_string ){ - extract( $this->var ); - include $this->tpl['compiled_filename']; - unset( $this->tpl ); - } - - - // cache or return_string are enabled - // rain get the output buffer to save the output in the cache or to return it as string - - else{ - - //---------------------- - // get the output buffer - //---------------------- - ob_start(); - extract( $this->var ); - include $this->tpl['compiled_filename']; - $raintpl_contents = ob_get_clean(); - //---------------------- - - - // save the output in the cache - if( $this->cache ) - file_put_contents( $this->tpl['cache_filename'], "" . $raintpl_contents ); - - // free memory - unset( $this->tpl ); - - // return or print the template - if( $return_string ) return $raintpl_contents; else echo $raintpl_contents; - - } - - } - - - - /** - * If exists a valid cache for this template it returns the cache - * - * @access public - * @param string $tpl_name Name of template (set the same of draw) - * @param int $expiration_time Set after how many seconds the cache expire and must be regenerated - * @param string $cache_id Suffix to be used when writing file to cache (optional) - * @return string it return the HTML or null if the cache must be recreated - */ - public function cache( $tpl_name, $expire_time = self::CACHE_EXPIRE_TIME, $cache_id = '' ){ - - // set the cache_id - $this->cache_id = $cache_id; - - if( !$this->check_template( $tpl_name ) && file_exists( $this->tpl['cache_filename'] ) && ( time() - filemtime( $this->tpl['cache_filename'] ) < $expire_time ) ) - return substr( file_get_contents( $this->tpl['cache_filename'] ), 43 ); - else{ - //delete the cache of the selected template - if (file_exists($this->tpl['cache_filename'])) - unlink($this->tpl['cache_filename'] ); - $this->cache = true; - } - } - - - - /** - * Configure the settings of RainTPL - * - * @access public - * @static - * @param array|string $setting array of settings or setting name - * @param mixed $value content to set in the setting (optional) - */ - public static function configure( $setting, $value = null ){ - if( is_array( $setting ) ) - foreach( $setting as $key => $value ) - self::configure( $key, $value ); - else if( property_exists( __CLASS__, $setting ) ){ - self::$$setting = $value; - self::$config_name_sum[ $setting ] = $value; // take trace of all config - } - } - - - - /** - * Check if has to compile the template - * - * @access protected - * @param string $tpl_name template name to check - * @throws RainTpl_NotFoundException - * @return bool return true if the template has changed - */ - protected function check_template( $tpl_name ){ - - if( !isset($this->tpl['checked']) ){ - - $tpl_basename = basename( $tpl_name ); // template basename - $tpl_basedir = strpos($tpl_name,"/") ? dirname($tpl_name) . '/' : null; // template basedirectory - $tpl_dir = PATH . self::$tpl_dir . $tpl_basedir; // template directory - $this->tpl['tpl_filename'] = $tpl_dir . $tpl_basename . '.' . self::$tpl_ext; // template filename - $temp_compiled_filename = PATH . self::$cache_dir . $tpl_basename . "." . md5( $tpl_dir . serialize(self::$config_name_sum)); - $this->tpl['compiled_filename'] = $temp_compiled_filename . '.rtpl.php'; // cache filename - $this->tpl['cache_filename'] = $temp_compiled_filename . '.s_' . $this->cache_id . '.rtpl.php'; // static cache filename - - // if the template doesn't exsist throw an error - if( self::$check_template_update && !file_exists( $this->tpl['tpl_filename'] ) ){ - $e = new RainTpl_NotFoundException( 'Template '. $tpl_basename .' not found!' ); - throw $e->setTemplateFile($this->tpl['tpl_filename']); - } - - // file doesn't exsist, or the template was updated, Rain will compile the template - if( !file_exists( $this->tpl['compiled_filename'] ) || ( self::$check_template_update && filemtime($this->tpl['compiled_filename']) < filemtime( $this->tpl['tpl_filename'] ) ) ){ - $this->compileFile( $tpl_basedir, $this->tpl['tpl_filename'], PATH . self::$cache_dir, $this->tpl['compiled_filename'] ); - return true; - } - $this->tpl['checked'] = true; - } - } - - - - /** - * execute stripslaches() on the xml block. Invoqued by preg_replace_callback function below - * - * @access protected - * @param string $capture - * @return string - */ - protected function xml_reSubstitution($capture) { - return "'; ?>"; - } - - - - /** - * Compile and write the compiled template file - * - * @access protected - * @param string $tpl_basedir - * @param string $tpl_filename - * @param string $cache_dir - * @param string $compiled_filename - * @throws RainTpl_Exception - * @return void - */ - protected function compileFile( $tpl_basedir, $tpl_filename, $cache_dir, $compiled_filename ){ - - //read template file - $this->tpl['source'] = $template_code = file_get_contents( $tpl_filename ); - - //xml substitution - $template_code = preg_replace( "/<\?xml(.*?)\?>/s", "##XML\\1XML##", $template_code ); - - //disable php tag - if( !self::$php_enabled ) - $template_code = str_replace( array(""), array("<?","?>"), $template_code ); - - //xml re-substitution - $template_code = preg_replace_callback ( "/##XML(.*?)XML##/s", array($this, 'xml_reSubstitution'), $template_code ); - - //compile template - $template_compiled = "" . $this->compileTemplate( $template_code, $tpl_basedir ); - - - // fix the php-eating-newline-after-closing-tag-problem - $template_compiled = str_replace( "?>\n", "?>\n\n", $template_compiled ); - - // create directories - if( !is_dir( $cache_dir ) ) - mkdir( $cache_dir, 0755, true ); - - if( !is_writable( $cache_dir ) ) - throw new RainTpl_Exception ('Cache directory ' . $cache_dir . ' doesn\'t have write permission. Set write permission or set RAINTPL_CHECK_TEMPLATE_UPDATE to false. More details on http://www.raintpl.com/Documentation/Documentation-for-PHP-developers/Configuration/'); - - //write compiled file - file_put_contents( $compiled_filename, $template_compiled ); - } - - - - /** - * Compile template - * - * @access protected - * @param string $template_code - * @param string $tpl_basedir - * @return string - */ - protected function compileTemplate( $template_code, $tpl_basedir ){ - - //tag list - $tag_regexp = array( 'loop' => '(\{loop(?: name){0,1}="\${0,1}[^"]*"\})', - 'loop_close' => '(\{\/loop\})', - 'if' => '(\{if(?: condition){0,1}="[^"]*"\})', - 'elseif' => '(\{elseif(?: condition){0,1}="[^"]*"\})', - 'else' => '(\{else\})', - 'if_close' => '(\{\/if\})', - 'function' => '(\{function="[^"]*"\})', - 'noparse' => '(\{noparse\})', - 'noparse_close'=> '(\{\/noparse\})', - 'ignore' => '(\{ignore\}|\{\*)', - 'ignore_close' => '(\{\/ignore\}|\*\})', - 'include' => '(\{include="[^"]*"(?: cache="[^"]*")?\})', - 'template_info'=> '(\{\$template_info\})', - 'function' => '(\{function="(\w*?)(?:.*?)"\})' - ); - - $tag_regexp = "/" . join( "|", $tag_regexp ) . "/"; - - //split the code with the tags regexp - $template_code = preg_split ( $tag_regexp, $template_code, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); - - //path replace (src of img, background and href of link) - $template_code = $this->path_replace( $template_code, $tpl_basedir ); - - //compile the code - $compiled_code = $this->compileCode( $template_code ); - - //return the compiled code - return $compiled_code; - - } - - - - /** - * Compile the code - * - * @access protected - * @param string $parsed_code - * @throws RainTpl_SyntaxException - * @return string - */ - protected function compileCode( $parsed_code ){ - - //variables initialization - $compiled_code = $open_if = $comment_is_open = $ignore_is_open = null; - $loop_level = 0; - - //read all parsed code - while( $html = array_shift( $parsed_code ) ){ - - //close ignore tag - if( !$comment_is_open && ( strpos( $html, '{/ignore}' ) !== FALSE || strpos( $html, '*}' ) !== FALSE ) ) - $ignore_is_open = false; - - //code between tag ignore id deleted - elseif( $ignore_is_open ){ - //ignore the code - } - - //close no parse tag - elseif( strpos( $html, '{/noparse}' ) !== FALSE ) - $comment_is_open = false; - - //code between tag noparse is not compiled - elseif( $comment_is_open ) - $compiled_code .= $html; - - //ignore - elseif( strpos( $html, '{ignore}' ) !== FALSE || strpos( $html, '{*' ) !== FALSE ) - $ignore_is_open = true; - - //noparse - elseif( strpos( $html, '{noparse}' ) !== FALSE ) - $comment_is_open = true; - - //include tag - elseif( preg_match( '/\{include="([^"]*)"(?: cache="([^"]*)"){0,1}\}/', $html, $code ) ){ - - //variables substitution - $include_var = $this->var_replace( $code[ 1 ], $left_delimiter = null, $right_delimiter = null, $php_left_delimiter = '".' , $php_right_delimiter = '."', $loop_level ); - - // if the cache is active - if( isset($code[ 2 ]) ){ - - //dynamic include - $compiled_code .= 'cache( $template = basename("'.$include_var.'") ) )' . - ' echo $cache;' . - 'else{' . - ' $tpl_dir_temp = self::$tpl_dir;' . - ' $tpl->assign( $this->var );' . - ( !$loop_level ? null : '$tpl->assign( "key", $key'.$loop_level.' ); $tpl->assign( "value", $value'.$loop_level.' );' ). - ' $tpl->draw( dirname("'.$include_var.'") . ( substr("'.$include_var.'",-1,1) != "/" ? "/" : "" ) . basename("'.$include_var.'") );'. - '} ?>'; - } - else{ - - //dynamic include - $compiled_code .= 'assign( $this->var );' . - ( !$loop_level ? null : '$tpl->assign( "key", $key'.$loop_level.' ); $tpl->assign( "value", $value'.$loop_level.' );' ). - '$tpl->draw( dirname("'.$include_var.'") . ( substr("'.$include_var.'",-1,1) != "/" ? "/" : "" ) . basename("'.$include_var.'") );'. - '?>'; - - - } - - } - - //loop - elseif( preg_match( '/\{loop(?: name){0,1}="\${0,1}([^"]*)"\}/', $html, $code ) ){ - - //increase the loop counter - $loop_level++; - - //replace the variable in the loop - $var = $this->var_replace( '$' . $code[ 1 ], $tag_left_delimiter=null, $tag_right_delimiter=null, $php_left_delimiter=null, $php_right_delimiter=null, $loop_level-1 ); - - //loop variables - $counter = "\$counter$loop_level"; // count iteration - $key = "\$key$loop_level"; // key - $value = "\$value$loop_level"; // value - - //loop code - $compiled_code .= " $value ){ $counter++; ?>"; - - } - - //close loop tag - elseif( strpos( $html, '{/loop}' ) !== FALSE ) { - - //iterator - $counter = "\$counter$loop_level"; - - //decrease the loop counter - $loop_level--; - - //close loop code - $compiled_code .= ""; - - } - - //if - elseif( preg_match( '/\{if(?: condition){0,1}="([^"]*)"\}/', $html, $code ) ){ - - //increase open if counter (for intendation) - $open_if++; - - //tag - $tag = $code[ 0 ]; - - //condition attribute - $condition = $code[ 1 ]; - - // check if there's any function disabled by black_list - $this->function_check( $tag ); - - //variable substitution into condition (no delimiter into the condition) - $parsed_condition = $this->var_replace( $condition, $tag_left_delimiter = null, $tag_right_delimiter = null, $php_left_delimiter = null, $php_right_delimiter = null, $loop_level ); - - //if code - $compiled_code .= ""; - - } - - //elseif - elseif( preg_match( '/\{elseif(?: condition){0,1}="([^"]*)"\}/', $html, $code ) ){ - - //tag - $tag = $code[ 0 ]; - - //condition attribute - $condition = $code[ 1 ]; - - //variable substitution into condition (no delimiter into the condition) - $parsed_condition = $this->var_replace( $condition, $tag_left_delimiter = null, $tag_right_delimiter = null, $php_left_delimiter = null, $php_right_delimiter = null, $loop_level ); - - //elseif code - $compiled_code .= ""; - } - - //else - elseif( strpos( $html, '{else}' ) !== FALSE ) { - - //else code - $compiled_code .= ''; - - } - - //close if tag - elseif( strpos( $html, '{/if}' ) !== FALSE ) { - - //decrease if counter - $open_if--; - - // close if code - $compiled_code .= ''; - - } - - //function - elseif( preg_match( '/\{function="(\w*)(.*?)"\}/', $html, $code ) ){ - - //tag - $tag = $code[ 0 ]; - - //function - $function = $code[ 1 ]; - - // check if there's any function disabled by black_list - $this->function_check( $tag ); - - if( empty( $code[ 2 ] ) ) - $parsed_function = $function . "()"; - else - // parse the function - $parsed_function = $function . $this->var_replace( $code[ 2 ], $tag_left_delimiter = null, $tag_right_delimiter = null, $php_left_delimiter = null, $php_right_delimiter = null, $loop_level ); - - //if code - $compiled_code .= ""; - } - - // show all vars - elseif ( strpos( $html, '{$template_info}' ) !== FALSE ) { - - //tag - $tag = '{$template_info}'; - - //if code - $compiled_code .= '"; print_r( $this->var ); echo ""; ?>'; - } - - - //all html code - else{ - - //variables substitution (es. {$title}) - $html = $this->var_replace( $html, $left_delimiter = '\{', $right_delimiter = '\}', $php_left_delimiter = '', $loop_level, $echo = true ); - //const substitution (es. {#CONST#}) - $html = $this->const_replace( $html, $left_delimiter = '\{', $right_delimiter = '\}', $php_left_delimiter = '', $loop_level, $echo = true ); - //functions substitution (es. {"string"|functions}) - $compiled_code .= $this->func_replace( $html, $left_delimiter = '\{', $right_delimiter = '\}', $php_left_delimiter = '', $loop_level, $echo = true ); - } - } - - if( $open_if > 0 ) { - $e = new RainTpl_SyntaxException('Error! You need to close an {if} tag in ' . $this->tpl['tpl_filename'] . ' template'); - throw $e->setTemplateFile($this->tpl['tpl_filename']); - } - return $compiled_code; - } - - - - /** - * Reduce a path - * - * eg. www/library/../filepath//file => www/filepath/file - * - * @param string $path - * @return string - */ - protected function reduce_path( $path ){ - $path = str_replace( "://", "@not_replace@", $path ); - $path = str_replace( "//", "/", $path ); - $path = str_replace( "@not_replace@", "://", $path ); - return preg_replace('/\w+\/\.\.\//', '', $path ); - } - - - - /** - * replace the path of image src, link href and a href - * - * url => template_dir/url - * url# => url - * http://url => http://url - * - * @access protected - * @param string $html - * @param string $tpl_basedir - * @return string html substitution - */ - protected function path_replace( $html, $tpl_basedir ){ - - if( self::$path_replace ){ - - $tpl_dir = self::$base_url . PATH . self::$tpl_dir . $tpl_basedir; - - // reduce the path - $path = $this->reduce_path($tpl_dir); - - $exp = $sub = array(); - - if( in_array( "img", self::$path_replace_list ) ){ - $exp = array( '/function_check( $tag ); - - $extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level ); - - - // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value - $is_init_variable = preg_match( "/^(\s*?)\=[^=](.*?)$/", $extra_var ); - - //function associate to variable - $function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null; - - //variable path split array (ex. $news.title o $news[title]) or object (ex. $news->title) - $temp = preg_split( "/\.|\[|\-\>/", $var ); - - //variable name - $var_name = $temp[ 0 ]; - - //variable path - $variable_path = substr( $var, strlen( $var_name ) ); - - //parentesis transform [ e ] in [" e in "] - $variable_path = str_replace( '[', '["', $variable_path ); - $variable_path = str_replace( ']', '"]', $variable_path ); - - //transform .$variable in ["$variable"] - $variable_path = preg_replace('/\.\$(\w+)/', '["$\\1"]', $variable_path ); - - //transform [variable] in ["variable"] - $variable_path = preg_replace('/\.(\w+)/', '["\\1"]', $variable_path ); - - //if there's a function - if( $function_var ){ - - // check if there's a function or a static method and separate, function by parameters - $function_var = str_replace("::", "@double_dot@", $function_var ); - - // get the position of the first : - if( $dot_position = strpos( $function_var, ":" ) ){ - - // get the function and the parameters - $function = substr( $function_var, 0, $dot_position ); - $params = substr( $function_var, $dot_position+1 ); - - } - else{ - - //get the function - $function = str_replace( "@double_dot@", "::", $function_var ); - $params = null; - - } - - // replace back the @double_dot@ with :: - $function = str_replace( "@double_dot@", "::", $function ); - $params = str_replace( "@double_dot@", "::", $params ); - - - } - else - $function = $params = null; - - $php_var = $var_name . $variable_path; - - // compile the variable for php - if( isset( $function ) ){ - if( $php_var ) - $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter; - else - $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $params ) )" : "$function()" ) . $php_right_delimiter; - } - else - $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter; - - $html = str_replace( $tag, $php_var, $html ); - - } - - return $html; - - } - - - - /** - * replace variables - * - * @access public - * @param string $html - * @param string $tag_left_delimiter - * @param string $tag_right_delimiter - * @param string $php_left_delimiter (optional) - * @param string $php_right_delimiter (optional) - * @param string $loop_level (optional) - * @param string $echo (optional) - * @return string - */ - public function var_replace( $html, $tag_left_delimiter, $tag_right_delimiter, $php_left_delimiter = null, $php_right_delimiter = null, $loop_level = null, $echo = null ){ - - //all variables - if( preg_match_all( '/' . $tag_left_delimiter . '\$(\w+(?:\.\${0,1}[A-Za-z0-9_]+)*(?:(?:\[\${0,1}[A-Za-z0-9_]+\])|(?:\-\>\${0,1}[A-Za-z0-9_]+))*)(.*?)' . $tag_right_delimiter . '/', $html, $matches ) ){ - - for( $parsed=array(), $i=0, $n=count($matches[0]); $i<$n; $i++ ) - $parsed[$matches[0][$i]] = array('var'=>$matches[1][$i],'extra_var'=>$matches[2][$i]); - - foreach( $parsed as $tag => $array ){ - - //variable name ex: news.title - $var = $array['var']; - - //function and parameters associate to the variable ex: substr:0,100 - $extra_var = $array['extra_var']; - - // check if there's any function disabled by black_list - $this->function_check( $tag ); - - $extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level ); - - // check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value - $is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var ); - - //function associate to variable - $function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null; - - //variable path split array (ex. $news.title o $news[title]) or object (ex. $news->title) - $temp = preg_split( "/\.|\[|\-\>/", $var ); - - //variable name - $var_name = $temp[ 0 ]; - - //variable path - $variable_path = substr( $var, strlen( $var_name ) ); - - //parentesis transform [ e ] in [" e in "] - $variable_path = str_replace( '[', '["', $variable_path ); - $variable_path = str_replace( ']', '"]', $variable_path ); - - //transform .$variable in ["$variable"] and .variable in ["variable"] - $variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path ); - - // if is an assignment also assign the variable to $this->var['value'] - if( $is_init_variable ) - $extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var; - - - - //if there's a function - if( $function_var ){ - - // check if there's a function or a static method and separate, function by parameters - $function_var = str_replace("::", "@double_dot@", $function_var ); - - - // get the position of the first : - if( $dot_position = strpos( $function_var, ":" ) ){ - - // get the function and the parameters - $function = substr( $function_var, 0, $dot_position ); - $params = substr( $function_var, $dot_position+1 ); - - } - else{ - - //get the function - $function = str_replace( "@double_dot@", "::", $function_var ); - $params = null; - - } - - // replace back the @double_dot@ with :: - $function = str_replace( "@double_dot@", "::", $function ); - $params = str_replace( "@double_dot@", "::", $params ); - } - else - $function = $params = null; - - //if it is inside a loop - if( $loop_level ){ - //verify the variable name - if( $var_name == 'key' ) - $php_var = '$key' . $loop_level; - elseif( $var_name == 'value' ) - $php_var = '$value' . $loop_level . $variable_path; - elseif( $var_name == 'counter' ) - $php_var = '$counter' . $loop_level; - else - $php_var = '$' . $var_name . $variable_path; - }else - $php_var = '$' . $var_name . $variable_path; - - // compile the variable for php - if( isset( $function ) ) - $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter; - else - $php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter; - - $html = str_replace( $tag, $php_var, $html ); - - - } - } - - return $html; - } - - - - /** - * Check if function is in black list (sandbox) - * - * @access protected - * @param string $code - * @throws RainTpl_SyntaxException - * @return void - */ - protected function function_check( $code ){ - - $preg = '#(\W|\s)' . implode( '(\W|\s)|(\W|\s)', self::$black_list ) . '(\W|\s)#'; - - // check if the function is in the black list (or not in white list) - if( count(self::$black_list) && preg_match( $preg, $code, $match ) ){ - - // find the line of the error - $line = 0; - $rows=explode("\n",$this->tpl['source']); - while( !strpos($rows[$line],$code) ) - $line++; - - // stop the execution of the script - $e = new RainTpl_SyntaxException('Unallowed syntax in ' . $this->tpl['tpl_filename'] . ' template'); - throw $e->setTemplateFile($this->tpl['tpl_filename']) - ->setTag($code) - ->setTemplateLine($line); - } - - } - - - - /** - * Prints debug info about exception or passes it further if debug is disabled. - * - * @access protected - * @param RainTpl_Exception $e - * @return string - */ - protected function printDebug(RainTpl_Exception $e){ - if (!self::$debug) { - throw $e; - } - $output = sprintf('

Exception: %s

%s

template: %s

', - get_class($e), - $e->getMessage(), - $e->getTemplateFile() - ); - if ($e instanceof RainTpl_SyntaxException) { - if (null !== $e->getTemplateLine()) { - $output .= '

line: ' . $e->getTemplateLine() . '

'; - } - if (null !== $e->getTag()) { - $output .= '

in tag: ' . htmlspecialchars($e->getTag()) . '

'; - } - if (null !== $e->getTemplateLine() && null !== $e->getTag()) { - $rows=explode("\n", htmlspecialchars($this->tpl['source'])); - $rows[$e->getTemplateLine()] = '' . $rows[$e->getTemplateLine()] . ''; - $output .= '

template code

' . implode('
', $rows) . ''; - } - } - $output .= sprintf('

trace

In %s on line %d

%s
', - $e->getFile(), $e->getLine(), - nl2br(htmlspecialchars($e->getTraceAsString())) - ); - return $output; - } -} - - - -/** - * Basic Rain tpl exception. - */ -class RainTpl_Exception extends Exception{ - /** - * Path of template file with error. - */ - protected $templateFile = ''; - - /** - * Returns path of template file with error. - * - * @return string - */ - public function getTemplateFile() - { - return $this->templateFile; - } - - /** - * Sets path of template file with error. - * - * @param string $templateFile - * @return RainTpl_Exception - */ - public function setTemplateFile($templateFile) - { - $this->templateFile = (string) $templateFile; - return $this; - } -} - - - -/** - * Exception thrown when template file does not exists. - */ -class RainTpl_NotFoundException extends RainTpl_Exception{ -} - -/** - * Exception thrown when syntax error occurs. - */ -class RainTpl_SyntaxException extends RainTpl_Exception{ - /** - * Line in template file where error has occured. - * - * @var int | null - */ - protected $templateLine = null; - - /** - * Tag which caused an error. - * - * @var string | null - */ - protected $tag = null; - - /** - * Returns line in template file where error has occured - * or null if line is not defined. - * - * @return int | null - */ - public function getTemplateLine() - { - return $this->templateLine; - } - - /** - * Sets line in template file where error has occured. - * - * @param int $templateLine - * @return RainTpl_SyntaxException - */ - public function setTemplateLine($templateLine) - { - $this->templateLine = (int) $templateLine; - return $this; - } - - /** - * Returns tag which caused an error. - * - * @return string - */ - public function getTag() - { - return $this->tag; - } - - /** - * Sets tag which caused an error. - * - * @param string $tag - * @return RainTpl_SyntaxException - */ - public function setTag($tag) - { - $this->tag = (string) $tag; - return $this; - } -} - -// -- end diff --git a/lib/privatebin.php b/lib/privatebin.php index baf9864f..aa0f68cb 100644 --- a/lib/privatebin.php +++ b/lib/privatebin.php @@ -423,10 +423,8 @@ class privatebin setcookie('lang', $languageselection); } - $page = new RainTPL; - $page::$path_replace = false; - // we escape it here because ENT_NOQUOTES can't be used in RainTPL templates - $page->assign('CIPHERDATA', htmlspecialchars($this->_data, ENT_NOQUOTES)); + $page = new view; + $page->assign('CIPHERDATA', $this->_data); $page->assign('ERROR', i18n::_($this->_error)); $page->assign('STATUS', i18n::_($this->_status)); $page->assign('VERSION', self::VERSION); diff --git a/lib/view.php b/lib/view.php new file mode 100644 index 00000000..45952006 --- /dev/null +++ b/lib/view.php @@ -0,0 +1,59 @@ +_variables[$name] = $value; + } + + /** + * render a template + * + * @access public + * @param string $template + * @throws Exception + * @return void + */ + public function draw($template) + { + $path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $template . '.php'; + if (!file_exists($path)) + { + throw new Exception('Template ' . $template . ' not found!', 80); + } + extract($this->_variables); + include $path; + } +} diff --git a/tpl/bootstrap-compact.html b/tpl/bootstrap-compact.php similarity index 50% rename from tpl/bootstrap-compact.html rename to tpl/bootstrap-compact.php index eefef691..084971e2 100644 --- a/tpl/bootstrap-compact.html +++ b/tpl/bootstrap-compact.php @@ -5,29 +5,37 @@ - {function="i18n::_('PrivateBin')"} + <?php echo i18n::_('PrivateBin'); ?> - {if="$SYNTAXHIGHLIGHTING"} - {if="strlen($SYNTAXHIGHLIGHTINGTHEME)"} - {/if}{/if} + + + - + - {if="$SYNTAXHIGHLIGHTING"} - {/if}{if="$MARKDOWN"} - {/if} - + + + + - - - - - + + + + + @@ -37,83 +45,102 @@
-
{if="strlen($NOTICE)"} +
{/if} + + {if="$FILEUPLOAD"} + {/if}{if="strlen($STATUS)"} + + {/if} - - - - + + + +
@@ -198,19 +238,19 @@
-

{function="i18n::_('PrivateBin')"} - {function="i18n::_('Because ignorance is bliss')"}

-

{$VERSION}

+

-

+

- {function="i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.')"} + in the browser using 256 bits AES. More information on the project page.'); ?>

- + diff --git a/tpl/bootstrap-dark-page.html b/tpl/bootstrap-dark-page.html deleted file mode 100644 index 7e2619aa..00000000 --- a/tpl/bootstrap-dark-page.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - {function="i18n::_('PrivateBin')"} - - - {if="$SYNTAXHIGHLIGHTING"} - {if="strlen($SYNTAXHIGHLIGHTINGTHEME)"} - {/if}{/if} - - - - - - {if="$SYNTAXHIGHLIGHTING"} - {/if}{if="$MARKDOWN"} - {/if} - - - - - - - - - - - - - -
{if="strlen($NOTICE)"} - {/if} - {if="$FILEUPLOAD"} - {/if}{if="strlen($STATUS)"} - {/if} - - - - - - -
-
-
- - - -

-
-
-
- -
-
-
-

{function="i18n::_('PrivateBin')"} - {function="i18n::_('Because ignorance is bliss')"}

-

{$VERSION}

-

- {function="i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.')"} -

-
-
- - - diff --git a/tpl/bootstrap-dark-page.php b/tpl/bootstrap-dark-page.php new file mode 100644 index 00000000..25150082 --- /dev/null +++ b/tpl/bootstrap-dark-page.php @@ -0,0 +1,252 @@ + + + + + + + + <?php echo i18n::_('PrivateBin'); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+ + + +

+
+
+
+ +
+
+
+

-

+

+

+ in the browser using 256 bits AES. More information on the project page.'); ?> +

+
+
+ + + diff --git a/tpl/bootstrap-dark.html b/tpl/bootstrap-dark.html deleted file mode 100644 index 543446f9..00000000 --- a/tpl/bootstrap-dark.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - {function="i18n::_('PrivateBin')"} - - - {if="$SYNTAXHIGHLIGHTING"} - {if="strlen($SYNTAXHIGHLIGHTINGTHEME)"} - {/if}{/if} - - - - - - {if="$SYNTAXHIGHLIGHTING"} - {/if}{if="$MARKDOWN"} - {/if} - - - - - - - - - - - - - -
{if="strlen($NOTICE)"} - {/if} - {if="$FILEUPLOAD"} - {/if}{if="strlen($STATUS)"} - {/if} - - - - - - -
-
-
- - - -

-
-
-
- -
-
-
-

{function="i18n::_('PrivateBin')"} - {function="i18n::_('Because ignorance is bliss')"}

-

{$VERSION}

-

- {function="i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.')"} -

-
-
- - - diff --git a/tpl/bootstrap-dark.php b/tpl/bootstrap-dark.php new file mode 100644 index 00000000..b3732968 --- /dev/null +++ b/tpl/bootstrap-dark.php @@ -0,0 +1,252 @@ + + + + + + + + <?php echo i18n::_('PrivateBin'); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+ + + +

+
+
+
+ +
+
+
+

-

+

+

+ in the browser using 256 bits AES. More information on the project page.'); ?> +

+
+
+ + + diff --git a/tpl/bootstrap-page.html b/tpl/bootstrap-page.html deleted file mode 100644 index f2e049a8..00000000 --- a/tpl/bootstrap-page.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - {function="i18n::_('PrivateBin')"} - - - {if="$SYNTAXHIGHLIGHTING"} - {if="strlen($SYNTAXHIGHLIGHTINGTHEME)"} - {/if}{/if} - - - - - - {if="$SYNTAXHIGHLIGHTING"} - {/if}{if="$MARKDOWN"} - {/if} - - - - - - - - - - - - - -
{if="strlen($NOTICE)"} - {/if} - {if="$FILEUPLOAD"} - {/if}{if="strlen($STATUS)"} - {/if} - - - - - - -
-
-
- - - -

-
-
-
- -
-
-
-

{function="i18n::_('PrivateBin')"} - {function="i18n::_('Because ignorance is bliss')"}

-

{$VERSION}

-

- {function="i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.')"} -

-
-
- - - diff --git a/tpl/bootstrap-page.php b/tpl/bootstrap-page.php new file mode 100644 index 00000000..1118076e --- /dev/null +++ b/tpl/bootstrap-page.php @@ -0,0 +1,252 @@ + + + + + + + + <?php echo i18n::_('PrivateBin'); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+ + + +

+
+
+
+ +
+
+
+

-

+

+

+ in the browser using 256 bits AES. More information on the project page.'); ?> +

+
+
+ + + diff --git a/tpl/bootstrap.html b/tpl/bootstrap.html deleted file mode 100644 index 9072d143..00000000 --- a/tpl/bootstrap.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - {function="i18n::_('PrivateBin')"} - - - {if="$SYNTAXHIGHLIGHTING"} - {if="strlen($SYNTAXHIGHLIGHTINGTHEME)"} - {/if}{/if} - - - - - - {if="$SYNTAXHIGHLIGHTING"} - {/if}{if="$MARKDOWN"} - {/if} - - - - - - - - - - - - - -
{if="strlen($NOTICE)"} - {/if} - {if="$FILEUPLOAD"} - {/if}{if="strlen($STATUS)"} - {/if} - - - - - - -
-
-
- - - -

-
-
-
- -
-
-
-

{function="i18n::_('PrivateBin')"} - {function="i18n::_('Because ignorance is bliss')"}

-

{$VERSION}

-

- {function="i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.')"} -

-
-
- - - diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php new file mode 100644 index 00000000..7d093da2 --- /dev/null +++ b/tpl/bootstrap.php @@ -0,0 +1,252 @@ + + + + + + + + <?php echo i18n::_('PrivateBin'); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+ + + +

+
+
+
+ +
+
+
+

-

+

+

+ in the browser using 256 bits AES. More information on the project page.'); ?> +

+
+
+ + + diff --git a/tpl/page.html b/tpl/page.html deleted file mode 100644 index 10fb4efd..00000000 --- a/tpl/page.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - {function="i18n::_('PrivateBin')"} - {if="$SYNTAXHIGHLIGHTING"} - {if="strlen($SYNTAXHIGHLIGHTINGTHEME)"} - {/if}{/if} - - - - - {if="$SYNTAXHIGHLIGHTING"} - {/if}{if="$MARKDOWN"} - {/if} - - - - - - - - - - - - -
-
- {function="i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.')"}
{if="strlen($NOTICE)"} - {$NOTICE}{/if} -
-

{function="i18n::_('PrivateBin')"}


-

{function="i18n::_('Because ignorance is bliss')"}


-

{$VERSION}

- -
{function="i18n::_('PrivateBin requires a modern browser to work.')"}
-
{function="i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:')"} - Firefox, - Opera, - Chrome, - Safari, - Edge... -
-
-
-
-
{$STATUS|htmlspecialchars}
- -
- - {if="$EXPIRECLONE"} - {/if} - - - - {if="$DISCUSSION"} - {/if}{if="$PASSWORD"} - {/if} - {if="strlen($LANGUAGESELECTION)"} -
- -
{/if} -
- {if="$FILEUPLOAD"} - - {/if} - - - - - -
-
-
- -
- - - diff --git a/tpl/page.php b/tpl/page.php new file mode 100644 index 00000000..e7677ce5 --- /dev/null +++ b/tpl/page.php @@ -0,0 +1,157 @@ + + + + + + <?php echo i18n::_('PrivateBin'); ?> + + + + + + + + + + + + + + + + + + + + + + +
+
+ in the browser using 256 bits AES. More information on the project page.'); ?>
+ +
+


+


+

+ +
+
+ Firefox, + Opera, + Chrome, + Safari... +
+
+
+
+
+ +
+ + + + + + + + + + +
+ +
+
+ + + + + + + + +
+
+
+ +
+ + + diff --git a/tst/RainTPL.php b/tst/view.php similarity index 83% rename from tst/RainTPL.php rename to tst/view.php index fe8aa0d6..39c71ca7 100644 --- a/tst/RainTPL.php +++ b/tst/view.php @@ -1,10 +1,18 @@ 'Plain Text', + 'syntaxhighlighting' => 'Source Code', + 'markdown' => 'Markdown', + ); + + private static $formatter_default = 'plaintext'; + private static $expire = array( '5min' => '5 minutes', '1hour' => '1 hour', @@ -20,12 +28,8 @@ class RainTPLTest extends PHPUnit_Framework_TestCase public function setUp() { /* Setup Routine */ - $page = new RainTPL; - $page::configure(array('cache_dir' => 'tmp/')); - $page::$path_replace = false; - - // We escape it here because ENT_NOQUOTES can't be used in RainTPL templates. - $page->assign('CIPHERDATA', htmlspecialchars(helper::getPaste()['data'], ENT_NOQUOTES)); + $page = new view; + $page->assign('CIPHERDATA', helper::getPaste()['data']); $page->assign('ERROR', self::$error); $page->assign('STATUS', self::$status); $page->assign('VERSION', self::$version); @@ -34,6 +38,8 @@ class RainTPLTest extends PHPUnit_Framework_TestCase $page->assign('MARKDOWN', true); $page->assign('SYNTAXHIGHLIGHTING', true); $page->assign('SYNTAXHIGHLIGHTINGTHEME', 'sons-of-obsidian'); + $page->assign('FORMATTER', self::$formatters); + $page->assign('FORMATTERDEFAULT', self::$formatter_default); $page->assign('BURNAFTERREADINGSELECTED', false); $page->assign('PASSWORD', true); $page->assign('FILEUPLOAD', false); @@ -48,16 +54,12 @@ class RainTPLTest extends PHPUnit_Framework_TestCase ob_start(); $page->draw('page'); $this->_content = ob_get_contents(); - // run a second time from cache - $page->cache('page'); - $page->draw('page'); ob_end_clean(); } public function tearDown() { /* Tear Down Routine */ - helper::rmdir(PATH . 'tmp'); } public function testTemplateRendersCorrectly() @@ -98,11 +100,12 @@ class RainTPLTest extends PHPUnit_Framework_TestCase } /** - * @expectedException RainTpl_Exception + * @expectedException Exception + * @expectedExceptionCode 80 */ public function testMissingTemplate() { - $test = new RainTPL; + $test = new view; $test->draw('123456789 does not exist!'); } }