public function parse() { while ($this->has_more() && $this->state != self::$STATE_FINISHED) { switch ($this->state) { case self::$STATE_START: $this->state = $this->parse_start(); break; case self::$STATE_TAG: $this->state = $this->parse_tag(); break; case self::$STATE_ELEMENT_OPEN: $this->state = $this->parse_element_open(); break; case self::$STATE_ELEMENT_CLOSE: $this->state = $this->parse_element_close(); break; case self::$STATE_STATEMENT: $this->state = $this->parse_statement(); break; case self::$STATE_PI: $this->state = $this->parse_pi(); break; default: Error::raise(sprintf(_t('Invalid state %d in %s->parse()'), $this->state, __CLASS__)); $this->state = self::$STATE_FINISHED; break; } } return $this->nodes; }
/** * Converts a HTML style hex string ('#7f6699') to an RGB array. */ public static function hex_rgb($hex_string) { $hex_string = ltrim($hex_string, '#'); if (!preg_match('/^[0-9a-f]+$/i', $hex_string)) { return Error::raise(_t('Not a valid hex color.')); } $normalized = ''; switch (strlen($hex_string)) { case 3: // 'fed' = 'ffeedd' for ($i = 0; $i < 3; $i++) { $normalized .= $hex_string[$i] . $hex_string[$i]; } break; case 6: // already normal $normalized = $hex_string; break; case 2: case 4: // who uses this anyway! $normalized = $hex_string . str_repeat('0', 6 - strlen($hex_string)); break; default: return Error::raise(_t('Not a valid color format.')); } return self::rgb_rgbarr(hexdec(substr($normalized, 0, 2)), hexdec(substr($normalized, 2, 2)), hexdec(substr($normalized, 4, 2))); }
/** * @param string URL * @param string method to call * @param string method's arguments */ function __construct($url, $method, $params) { if (!function_exists('xmlrpc_encode_request')) { return Error::raise(_t('xmlrpc extension not found')); } $this->url = $url; $this->method = $method; $this->params = $params; $this->request_body = xmlrpc_encode_request($method, $params); }
private static function get_external_content($url) { // Get PHP serialized object from Flickr $call = new RemoteRequest($url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Flickr.', 'flickrfeed')); } return $call->get_response_body(); }
/** * Return a normalized and absolute path if path exist * or the normalized provided path if `$strict = false` * otherwise an error is raised. * * @static * @method absolute_path * @param {String} $path * @param {Boolean} [$strict=true] Throw an exception if does not exist. * @throws {Error} If `$path` does not exist and `$strict = true`. * @return {String} */ public static function absolute_path($path, $strict = true) { // If the path exist if (file_exists($path)) { // Get the absolute path $path = realpath($path); } else { if ($strict) { Error::raise('Path "%s" does not exist.', [$path]); } } // Return a normalized path return self::normalize_path($path); }
/** * script_name is a helper function to determine the name of the script * not all PHP installations return the same values for $_SERVER['SCRIPT_URL'] * and $_SERVER['SCRIPT_NAME'] */ public static function script_name() { switch ( true ) { case isset( self::$scriptname ): break; case isset( $_SERVER['SCRIPT_NAME'] ): self::$scriptname = $_SERVER['SCRIPT_NAME']; break; case isset( $_SERVER['PHP_SELF'] ): self::$scriptname = $_SERVER['PHP_SELF']; break; default: Error::raise( _t( 'Could not determine script name.' ) ); die(); } return self::$scriptname; }
/** * Execute a call to the Picasa Service * * @param $url string The destination url * @param $args array Optional Extra arguments * @param $post_data Optional Post data * @return mixed false on error or xml string */ public function call($url, $args = array(), $post_data = '') { $token = Options::get('picasa_token_' . User::identify()->id); $default_args = array('method' => 'GET'); $args = array_merge($default_args, $args); $request = new RemoteRequest($url, $args['method']); // set authorisation header $request->add_header(array("Authorization" => "AuthSub token=" . $token)); // add extra headers if (isset($args['http_headers'])) { foreach ($args['http_headers'] as $key => $value) { $request->add_header(array($key => $value)); } } if ($post_data != '') { $request->set_body($post_data); } $request->set_timeout(30); // execute request $result = $request->execute(); if (Error::is_error($result)) { return $result; } // get the response if executed if ($request->executed()) { $response = $request->get_response_body(); } if (!$response) { return Error::raise('API call failure', E_USER_WARNING); } // parse the result try { $xml = new SimpleXMLElement($response); return $xml; } catch (Exception $e) { Session::error('Currently unable to connect to the Picasa API.', 'Picasa API'); return false; } }
private static function parse_json($block, $json) { // Decode JSON $obj = json_decode($json); if (isset($obj->query)) { $obj = $obj->results; // Strip user designate tags foreach ($obj as &$o) { $o->text = str_replace($block->search, '', $o->text); } } if (!is_array($obj)) { // Response is not JSON throw Error::raise(_t('Response is not correct, Twitter server may be down or API is changed.', 'twitterlitte')); } $serial = serialize($obj); // Convert stdClass to TwitterLitteTweet and TwitterLitteUser $serial = str_replace('s:4:"user";O:8:"stdClass":', 's:4:"user";O:16:"TwitterLitteUser":'******'O:8:"stdClass":', 'O:17:"TwitterLitteTweet":', $serial); $tweets = unserialize($serial); return $tweets; }
private function update_tweetbacks(Post $post) { // Get the lastest tweetback in database $tweetbacks = $post->comments->tweetbacks; if ($tweetbacks->count > 0) { $tweet_url = explode('/', $tweetbacks[0]->url); $since_id = end($tweet_url); } else { $since_id = 0; } // Get short urls $aliases = array_filter((array) ShortURL::get($post)); //$aliases[] = $post->permalink; // Do not include original permalink, because Twitter Search has character limit, too. // Construct request URL $url = 'http://search.twitter.com/search.json?'; $url .= http_build_query(array('ors' => implode(' ', $aliases), 'rpp' => 50, 'since_id' => $since_id), '', '&'); // Get JSON content $call = new RemoteRequest($url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Twitter.', $this->class_name)); } $response = $call->get_response_body(); // Decode JSON $obj = json_decode($response); if (isset($obj->results) && is_array($obj->results)) { $obj = $obj->results; } else { throw Error::raise(_t('Response is not correct, Twitter server may be down or API is changed.', $this->class_name)); } // Store new tweetbacks into database foreach ($obj as $tweet) { Comment::create(array('post_id' => $post->id, 'name' => $tweet->from_user, 'url' => sprintf('http://twitter.com/%1$s/status/%2$d', $tweet->from_user, $tweet->id), 'content' => $tweet->text, 'status' => Comment::STATUS_APPROVED, 'date' => HabariDateTime::date_create($tweet->created_at), 'type' => Comment::TWEETBACK)); } }
/** * Connect to the SMTP server by instantiating a SMTP object. * * @return mixed Returns a reference to the SMTP object on success, or * a Error containing a descriptive error message on * failure. * * @since 1.2.0 * @access public */ public function &getSMTPObject() { if (is_object($this->_smtp) !== false) { return $this->_smtp; } $this->_smtp = new SMTP($this->host, $this->port, $this->localhost); /* If we still don't have an SMTP object at this point, fail. */ if (is_object($this->_smtp) === false) { throw Error::raise('Failed to create a SMTP object', self::ERROR_CREATE); } /* Configure the SMTP connection. */ if ($this->debug) { $this->_smtp->setDebug(true); } /* Attempt to connect to the configured SMTP server. */ if (Error::is_error($res = $this->_smtp->connect($this->timeout))) { $error = $this->_error('Failed to connect to ' . $this->host . ':' . $this->port, $res); throw Error::raise($error, self::ERROR_CONNECT); } /* Attempt to authenticate if authentication has been enabled. */ if ($this->auth) { $method = is_string($this->auth) ? $this->auth : ''; if (Error::is_error($res = $this->_smtp->auth($this->username, $this->password, $method))) { $error = $this->_error("{$method} authentication failure", $res); $this->_smtp->rset(); throw Error::raise($error, self::ERROR_AUTH); } } return $this->_smtp; }
public function get_response_headers() { if (!$this->executed) { return Error::raise(_t('Request did not yet execute.')); } return $this->response_headers; }
/** * Set new path. * * @method setPath * @param string $key * @param string $path * @param boolean [$strict=true] * @return string */ public function setPath($key, $path, $strict = true) { // If strict mode and path not found. if ($strict and !file_exists($path)) { // Throw an error. Error::raise('Path not found: [%s: "%s"].', [$key, $path]); } // Else set and return normalized absolute path. return $this->config[$key] = self::normalizePath(realpath($path)); }
/** * Add last Audioscrobbler status, time, and image to the available template vars * @param Theme $theme The theme that will display the template **/ public function theme_audioscrobbler($theme, $params = array()) { $params = array_merge($this->config, $params); $cache_name = $this->class_name . '__' . md5(serialize($params)); if ($params['username'] != '') { $track_url = 'http://ws.audioscrobbler.com/1.0/user/' . urlencode($params['username']) . '/recenttracks.xml'; if (Cache::has($cache_name)) { $xml = new SimpleXMLElement(Cache::get($cache_name)); $theme->track = $xml->track; } else { try { // Get XML content via Audioscrobbler API $call = new RemoteRequest($track_url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Last.fm.', $this->class_name)); } $response = $call->get_response_body(); // Parse XML content $xml = new SimpleXMLElement($response); $theme->track = $xml->track; Cache::set($cache_name, $response, $params['cache']); } catch (Exception $e) { $theme->track = $e->getMessage(); } } } else { $theme->track = _t('Please set your username in the Audioscrobbler plugin config.', $this->class_name); } return $theme->fetch('audioscrobbler'); }
public function action_hconsole_debug() { if (isset($this->code['debug'])) { ob_start(); $res = eval($this->code['debug']); $dat = ob_get_contents(); ob_end_clean(); if ($res === false) { throw Error::raise($dat, E_COMPILE_ERROR); } else { echo $this->htmlspecial ? htmlspecialchars($dat) : $dat; } } if ($this->sql) { $itemlist = array(); if (preg_match('#^\\s*(select|show).*#i', $this->sql)) { $data = DB::get_results($this->sql); if (DB::has_errors()) { throw Error::raise(DB::get_last_error()); } if (is_array($data) && count($data)) { self::sql_dump($data); } else { echo 'empty set, nothing returned.'; } } else { $data = DB::query($this->sql); if (DB::has_errors()) { throw Error::raise(DB::get_last_error()); } echo 'Result: ' . (string) $data; } } }
/** * Get the brightkite feed for our user_id **/ private function load_bk_info($params = array()) { $cache_name = $this->class_name . '__' . md5(serialize($params)); if (Cache::has($cache_name)) { // Read from the cache return Cache::get($cache_name); } else { // Time to fetch it. $url = 'http://brightkite.com/people/' . $params['user_id'] . '.json'; try { $call = new RemoteRequest($url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Brightkite.', $this->class_name)); } $response = $call->get_response_body(); // Decode the JSON $bkdata = json_decode($response, true); if (!is_array($bkdata)) { // Response is not JSON throw Error::raise(_t('Response is not correct, maybe Brightkite server is down or API changed.', $this->class_name)); } // Do cache Cache::set($cache_name, $bkdata, $params['cache_expiry']); return $bkdata; } catch (Exception $e) { return $e->getMessage(); } } }
/** * Crypt or verify a given password using SSHA512. * Implements a modified version of the {Seeded,Salted}-SHA algorithm * from RfC 2307, using SHA-512 instead of SHA-1. * * Requires the new hash*() functions. * * @param string $password the password to crypt or verify * @param string $hash (optional) if given, verify $password against $hash * @return string encrypted password, or boolean for verification */ public static function ssha512($password, $hash = null) { $marker = '{SSHA512}'; if ($hash == null) { // encrypt $salt = ''; for ($i = 0; $i < 4; $i++) { $salt .= chr(mt_rand(0, 255)); } $digest = hash('sha512', $password . $salt, true); return $marker . base64_encode($digest . $salt); } else { // verify if (!substr($hash, 0, strlen($marker)) == $marker) { Error::raise(_t('Invalid hash')); return false; } $hash = substr($hash, strlen($marker)); $hash = base64_decode($hash); $digest = substr($hash, 0, 64); $salt = substr($hash, 64); return hash('sha512', $password . $salt, true) == $digest; } }
/** * Return the response body. Raises a warning and returns '' if the request wasn't executed yet. */ public function get_response_body() { if (!$this->executed) { return Error::raise(_t('Trying to fetch response body for a pending request.'), E_USER_WARNING); } return $this->response_body; }
/** * Add last Jaiku status, time, and image to the available template vars * @param Theme $theme The theme that will display the template **/ public function theme_jaiku($theme, $params = array()) { $params = array_merge($this->config, $params); $cache_name = $this->class_name . '__' . md5(serialize($params)); if ($params['username'] != '') { if (Cache::has($cache_name)) { $theme->presences = Cache::get($cache_name); } else { if ($params['limit'] == 1) { $url = 'http://' . $params['username'] . '.jaiku.com/presence/last/json'; } else { $url = 'http://' . $params['username'] . '.jaiku.com/feed/json'; } try { // Get JSON content via Jaiku API $call = new RemoteRequest($url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Jaiku.', $this->class_name)); } $response = $call->get_response_body(); // Decode JSON $obj = json_decode($response); if (!$obj instanceof stdClass) { // Response is not JSON throw Error::raise(_t('Response is not correct, maybe Jaiku server is down or API is changed.', $this->class_name)); } $serial = property_exists($obj, 'stream') ? serialize($obj->stream) : serialize($obj); // Convert stdClass to JaikuPresence and JaikuUser $serial = str_replace('s:4:"user";O:8:"stdClass":', 's:4:"user";O:9:"JaikuUser":'******'O:8:"stdClass":', 'O:13:"JaikuPresence":', $serial); $presences = unserialize($serial); // Pass $presences to $theme if (is_array($presences)) { $theme->presences = array_slice($presences, 0, $params['limit']); } else { $theme->presences = array($presences); } // Do cache Cache::set($cache_name, $theme->presences, $params['cache']); } catch (Exception $e) { $theme->presences = $e->getMessage(); } } } else { $theme->presences = _t('Please set your username in the Jaiku plugin config.', $this->class_name); } return $theme->fetch('jaiku'); }
private function load_feeds($params = array()) { $cache_name = $this->class_name . '__' . md5(serialize($params)); if (Cache::has($cache_name)) { // Read from cache return Cache::get($cache_name); } else { $url = 'http://feeds.delicious.com/v2/json/' . $params['user_id']; if ($params['tags']) { $url .= '/' . urlencode($params['tags']); } $url .= '?count=' . $params['num_item']; try { // Get JSON content via Delicious API $call = new RemoteRequest($url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Delicious.', $this->class_name)); } $response = $call->get_response_body(); // Decode JSON $deliciousfeed = json_decode($response); if (!is_array($deliciousfeed)) { // Response is not JSON throw Error::raise(_t('Response is not correct, maybe Delicious server is down or API is changed.', $this->class_name)); } else { // Transform to DeliciousPost objects $serial = serialize($deliciousfeed); $serial = str_replace('O:8:"stdClass":', 'O:13:"DeliciousPost":', $serial); $deliciousfeed = unserialize($serial); } // Do cache Cache::set($cache_name, $deliciousfeed, $params['cache_expiry']); return $deliciousfeed; } catch (Exception $e) { return $e->getMessage(); } } }
/** * Convert an RGB array to a HSV array. */ public static function rgb_hsv($rgb_arr) { $min = min($rgb_arr); $max = max($rgb_arr); $d = $max - $min; if ($max == 0) { // black // we use 0/0/0, even though at black, H and V are undefined $h = 0; $s = 0; $v = 0; } else { if ($max == $rgb_arr['r']) { // reddish (YM) $h = ($rgb_arr['g'] - $rgb_arr['b']) / $d; } elseif ($max == $rgb_arr['g']) { // greenish (CY) $h = 2 + ($rgb_arr['b'] - $rgb_arr['r']) / $d; } elseif ($max == $rgb_arr['b']) { // bluish (MC) $h = 4 + ($rgb_arr['r'] - $rgb_arr['g']) / $d; } else { Error::raise(_t('Something went terribly wrong here.')); } $h *= 60; // convert to deg $h = ($h + 360) % 360; // map to 0..359 $s = 100 * $d / $max; $v = $max; } return self::hsv_hsvarr($h, $s, $v); }
/** * Get the export path for a specific post * * Rasises an error if the export path isn't writable * * @param Post $post the post for which we want the export path * @return string path */ protected static function get_post_export_path(Post $post) { $exportPath = Options::get(self::OPTIONS_LOCALPATH); if (!$exportPath || !is_readable($exportPath) || !is_writable($exportPath)) { Error::raise(_t('Export path is not readable/writable. Be sure to configure this plugin.')); } return $exportPath . DIRECTORY_SEPARATOR . $post->slug . DIRECTORY_SEPARATOR; }
/** * Load the module compressor if exist. * * @protected * @method load_compressor */ protected function load_compressor() { // Possible PHP compressor file path $php_file = $this->base_path . '/' . $this->builder->config['compressor_filename']; // If compressor found if (is_file($php_file)) { // Create the compressor class instance $compressor = new Compressor($php_file); // Initialize the compressor if (isset($compressor->initialize)) { // Call the init. callback with this module at first param $result = call_user_func($compressor->initialize, $this); // Errors handler if (is_string($result)) { Error::raise($result); } else { if (is_array($result)) { Error::raise($result[0], $result[1]); } else { if ($result === false) { // Disable compression $compressor = null; } } } } // Set the module compressor $this->compressor = $compressor; } }
private function load_feeds($params = array()) { $cache_name = $this->class_name . '__' . md5(serialize($params)); if (Cache::has($cache_name)) { // Read from cache return Cache::get($cache_name); } else { switch ($params['type']) { case 'user': $url = 'http://api.flickr.com/services/feeds/photos_public.gne?id=' . $params['user_id'] . '&tags=' . $params['tags'] . '&format=php_serial'; break; case 'friends': $url = 'http://api.flickr.com/services/feeds/photos_friends.gne?user_id=' . $params['user_id'] . '&format=php_serial'; break; case 'faves': $url = 'http://api.flickr.com/services/feeds/photos_faves.gne?id=' . $params['user_id'] . '&format=php_serial'; break; case 'group': $url = 'http://api.flickr.com/services/feeds/groups_pool.gne?id=' . $params['user_id'] . '&format=php_serial'; break; default: $url = 'http://api.flickr.com/services/feeds/photos_public.gne?tags=' . $params['tags'] . '&format=php_serial'; break; } try { // Get PHP serialized object from Flickr $call = new RemoteRequest($url); $call->set_timeout(5); $result = $call->execute(); if (Error::is_error($result)) { throw Error::raise(_t('Unable to contact Flickr.', $this->class_name)); } // Unserialize and manipulate the data $flickrfeed = unserialize($call->get_response_body()); $flickrfeed = array_slice($flickrfeed['items'], 0, $params['num_item']); // Photo size foreach ($flickrfeed as &$image) { switch ($params['size']) { case 'thumbnail': $image['image_url'] = str_replace('_m.jpg', '_t.jpg', $image['m_url']); break; case 'small': $image['image_url'] = $image['m_url']; break; case 'medium': $image['image_url'] = $image['l_url']; break; case 'large': $image['image_url'] = str_replace('_m.jpg', '_b.jpg', $image['m_url']); break; case 'original': $image['image_url'] = $image['photo_url']; break; default: $image['image_url'] = $image['t_url']; break; } } // Do cache Cache::set($cache_name, $flickrfeed, $params['cache_expiry']); return $flickrfeed; } catch (Exception $e) { return $e->getMessage(); } } }
private static function check_attr_value($k, $v, $type) { if (is_array($type)) { // array of allowed values, exact matches only return in_array($v, $type, true); } else { // data type switch ($type) { case 'uri': // RfC 2396 <http://www.ietf.org/rfc/rfc2396.txt> $bits = self::parse_url($v); return $bits['is_relative'] || in_array($bits['scheme'], self::$whitelist_protocols); break; case 'language-code': // RfC 1766 <http://www.ietf.org/rfc/rfc1766.txt> // Language-Tag = Primary-tag *( "-" Subtag ) // Primary-tag = 1*8ALPHA // Subtag = 1*8ALPHA return preg_match('/^[a-zA-Z]{1,8}(?:-[a-zA-Z]{1,8})*$/i', $v); break; case 'text': // XXX is this sufficient? return is_string($v); break; case 'datetime': // <http://www.w3.org/TR/1998/NOTE-datetime-19980827> // <http://www.w3.org/TR/html4/types.html#h-6.11> // YYYY-MM-DDThh:mm:ssTZD return preg_match('/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9](?:Z|[\\+-][0-2][0-9]:[0-5][0-9])$/', $v); break; default: Error::raise(_t('Unknown attribute type "%s" in %s', array($type, __CLASS__))); return false; } } }
/** * Simple module scaffolding. * * @todo Make a dedicated class ! * @protected * @method make_module */ protected function make_module() { // No module name provided if (empty($_GET['make'])) { // Exit... return; } // Set and normalize the provided namespace to create $namespace = Helper::normalize_path(trim(strtolower($_GET['make']))); // Try to get the module try { $module = $this->get_module($namespace); } catch (\Exception $e) { } // Module alrady exist if (!empty($module)) { Error::raise('Module [%s] already exists.', [$namespace]); } // Set the main module class name $class_name = Helper::classify($namespace); // Set the base path $path = $this->get_path('sources', $namespace); //var_dump([$namespace, $class_name, $path]); // Make base directories foreach (Module::$autoload as $directory) { Helper::make_path($path . '/' . $directory); //var_dump($path . '/' . $directory); } // Make the straw.json file $data = "{\n"; foreach (Module::$defaults as $key => $value) { $value = json_encode($value, JSON_UNESCAPED_SLASHES); $pad = str_pad(' ', 9 - strlen($key)); $data .= "\t\"{$key}\"{$pad}: {$value},\n"; } $data = trim($data, "\n,") . "\n}\n"; $file = $path . '/' . $this->config['straw_filename']; file_put_contents($file, $data); //var_dump([$file, $data]); // Make the main language file $data = "{\n\t\"name\" : \"{$class_name}\"\n}\n"; $file = $path . '/lang/' . $this->config['lang'] . '.json'; file_put_contents($file, $data); //var_dump([$file, $data]); // Make the main module file $data = "var {$class_name} = StrawModule.extend(\n{\n\t\n});\n"; $file = $path . '/module.js'; file_put_contents($file, $data); //var_dump([$file, $data]); // Make a default model file $data = "var {$class_name}Model = StrawModel.extend(\n{\n\t\n});\n"; $file = $path . '/models/model.js'; file_put_contents($file, $data); //var_dump([$file, $data]); /* // Make a default helper script file $data = "var ${class_name}Helper =\n{\n\t\n};\n"; $file = $path . '/scripts/helper.js'; file_put_contents($file, $data); //var_dump([$file, $data]); */ // Make a default style file $id = strtolower($class_name); $data = "#{$id}\n{\n\t\n}\n"; $file = $path . '/styles/default.css'; file_put_contents($file, $data); //var_dump([$file, $data]); // Make a default view file $file = $path . '/views/default.tpl'; $data = "<div id=\"{$id}\">\n"; $data .= "\t<h1>{$class_name}</h1>\n"; $data .= "\t<p>Default view at {$file}.</p>\n"; $data .= "</div>\n"; file_put_contents($file, $data); //var_dump([$file, $data]); }
/** * Load translations from a given file. * * @param string $domain the domain to load the data into * @param string $file the file name * @return boolean TRUE if data was successfully loaded, FALSE otherwise */ private static function load_file($domain, $file) { if (!file_exists($file)) { Error::raise(sprintf(_t('No translations found for locale %s, domain %s!'), self::$locale, $domain)); return FALSE; } if (filesize($file) < 24) { Error::raise(sprintf(_t('Invalid .MO file for locale %s, domain %s!'), self::$locale, $domain)); return FALSE; } $fp = fopen($file, 'rb'); $data = fread($fp, filesize($file)); fclose($fp); // determine endianness $little_endian = TRUE; list(, $magic) = unpack('V1', substr($data, 0, 4)); switch ($magic & 0xffffffff) { case (int) 0x950412de: $little_endian = TRUE; break; case (int) 0xde120495: $little_endian = FALSE; break; default: Error::raise(sprintf(_t('Invalid magic number 0x%08x in %s!'), $magic, $file)); return FALSE; } $revision = substr($data, 4, 4); if ($revision != 0) { Error::raise(sprintf(_t('Unknown revision number %d in %s!'), $revision, $file)); return FALSE; } $l = $little_endian ? 'V' : 'N'; if ($data && strlen($data) >= 20) { $header = substr($data, 8, 12); $header = unpack("{$l}1msgcount/{$l}1msgblock/{$l}1transblock", $header); if ($header['msgblock'] + ($header['msgcount'] - 1) * 8 > filesize($file)) { Error::raise(sprintf(_t('Message count (%d) out of bounds in %s!'), $header['msgcount'], $file)); return FALSE; } $lo = "{$l}1length/{$l}1offset"; for ($msgindex = 0; $msgindex < $header['msgcount']; $msgindex++) { $msginfo = unpack($lo, substr($data, $header['msgblock'] + $msgindex * 8, 8)); $msgids = explode("", substr($data, $msginfo['offset'], $msginfo['length'])); $transinfo = unpack($lo, substr($data, $header['transblock'] + $msgindex * 8, 8)); $transids = explode("", substr($data, $transinfo['offset'], $transinfo['length'])); self::$messages[$domain][$msgids[0]] = array($msgids, $transids); } } // setup plural functionality self::$plural_function = self::get_plural_function(self::$messages[$domain][''][1][0]); // only use locale if we actually read something return count(self::$messages) > 0; }
/** * Write and throw error message(s). * * @method writeAndThrowError * @param string|array $text * @param array [$data=null] * @throw Error */ public function writeAndThrowError($text, $data = null) { $this->writeError($text, $data); Error::raise($text, $data); }