/** * prepare a multi-part message * * @param string message HTML tags or ASCII content * @return array containing message parts ($type => $content) */ public static function build_multipart($text) { global $context; // make a full html entity --body attributes are ignored most of the time $text = '<html><body>' . MAIL_FONT_PREFIX . $text . MAIL_FONT_SUFFIX . '</body></html>'; // change links to include host name $text = str_replace(' href="/', ' href="' . $context['url_to_home'] . '/', $text); $text = str_replace(' src="/', ' src="' . $context['url_to_home'] . '/', $text); // remove invisible tags, such as scripts, etc. $text = xml::strip_invisible_tags($text); // one element per type $message = array(); // text/plain part has no tag anymore $replacements = array('#<a [^>]*?><img [^>]*?></a>#i' => '', "#<a href=\"([^\"]+?)\"([^>]*?)>\$1</a>#i" => "\$1", '#<a href="([^"]+?)" ([^>]*?)>(.*?)</a>#i' => "\$3 \$1", '/<a href=\\"([^\\"]+?)">(.*?)<\\/a>/i' => "\$2 \$1", '/<hr[^>]*?>/i' => "-------\n", '/ /' => ' '); // text/plain part $message['text/plain; charset=utf-8'] = utf8::from_unicode(utf8::encode(trim(html_entity_decode(xml::strip_visible_tags(preg_replace(array_keys($replacements), array_values($replacements), $text), ''), ENT_QUOTES, 'UTF-8')))); // transform the text/html part $replacements = array('#<dl[^>]*?>(.*?)</dl>#siu' => '<table>$1</table>', '#<dt[^>]*?>(.*?)</dt>#siu' => '<tr><td>' . MAIL_FONT_PREFIX . '$1' . MAIL_FONT_SUFFIX . '</td>', '#<dd[^>]*?>(.*?)</dd>#siu' => '<td>' . MAIL_FONT_PREFIX . '$1' . MAIL_FONT_SUFFIX . '</td></tr>', '#class="grid"#i' => 'border="1" cellspacing="0" cellpadding="10"', '#on(click|keypress)="([^"]+?)"#i' => '', '#/>#i' => '>'); // text/html part $message['text/html; charset=utf-8'] = preg_replace(array_keys($replacements), array_values($replacements), $text); // return all parts return $message; }
/** * get one table by id * * @param int the id of the table * @return the resulting $row array, with at least keys: 'id', 'title', etc. */ public static function get($id) { global $context; // sanity check if (!$id) { $output = NULL; return $output; } // ensure proper unicode encoding $id = (string) $id; $id = utf8::encode($id); // // strip extra text from enhanced ids '3-alfred' -> '3' // if($position = strpos($id, '-')) // $id = substr($id, 0, $position); // search by id if (is_numeric($id)) { $query = "SELECT * FROM " . SQL::table_name('tables') . " AS tables" . " WHERE (tables.id = " . SQL::escape((int) $id) . ")"; } else { $query = "SELECT * FROM " . SQL::table_name('tables') . " AS tables" . " WHERE (tables.nick_name LIKE '" . SQL::escape($id) . "')" . " ORDER BY edit_date DESC LIMIT 1"; } // do the job $output = SQL::query_first($query); return $output; }
include_once '../shared/global.php'; include_once 'codec.php'; include_once 'xml_rpc_codec.php'; include_once '../links/links.php'; include_once '../servers/servers.php'; // load a skin engine load_skin('services'); // process raw content $raw_data = file_get_contents("php://input"); // save the raw request if debug mode if (isset($context['debug_ping']) && $context['debug_ping'] == 'Y') { Logger::remember('services/ping.php: ping request', $raw_data, 'debug'); } // transcode to our internal charset if ($context['charset'] == 'utf-8') { $raw_data = utf8::encode($raw_data); } // load the adequate codec $codec = new xml_rpc_Codec(); // parse xml parameters $result = $codec->import_request($raw_data); $status = @$result[0]; $parameters = @$result[1]; // nothing to parse if (!$raw_data) { $response = array('faultCode' => 5, 'faultString' => 'Empty request, please retry'); // parse has failed } elseif (!$status) { $response = array('faultCode' => 5, 'faultString' => 'Impossible to parse parameters'); // dispatch the request } else {
/** * get the unique handle associated to a section * * @param int or string the id or nick name of the section * @return the associated handle, or NULL if no record matches the input parameter */ public static function &get_handle($id) { global $context; // sanity check if (!$id) { $output = NULL; return $output; } // ensure proper unicode encoding $id = (string) $id; $id = utf8::encode($id); // cache previous answers static $cache; if (!is_array($cache)) { $cache = array(); } // cache hit if (isset($cache[$id])) { return $cache[$id]; } // search by id or nick name $query = "SELECT handle FROM " . SQL::table_name('sections') . " AS sections" . " WHERE (sections.id = " . SQL::escape((int) $id) . ") OR (sections.nick_name LIKE '" . SQL::escape($id) . "')" . " ORDER BY edit_date DESC LIMIT 1"; // do the job $output = SQL::query_scalar($query); // save in cache $cache[$id] = $output; // return by reference return $output; }
/** * process uploaded file * * This function processes files from the temporary directory, and put them at their definitive * place. * * It returns FALSE if there is a disk error, or if some virus has been detected, or if * the operation fails for some other reason (e.g., file size). * * @param array usually, $_FILES['upload'] * @param string target location for the file * @param mixed reference to the target anchor, of a function to parse every file individually * @return mixed file name or array of file names or FALSE if an error has occured */ public static function upload($input, $file_path, $target = NULL, $overlay = NULL) { global $context, $_REQUEST; // size exceeds php.ini settings -- UPLOAD_ERR_INI_SIZE if (isset($input['error']) && $input['error'] == 1) { Logger::error(i18n::s('The size of this file is over limit.')); } elseif (isset($input['error']) && $input['error'] == 2) { Logger::error(i18n::s('The size of this file is over limit.')); } elseif (isset($input['error']) && $input['error'] == 3) { Logger::error(i18n::s('No file has been transmitted.')); } elseif (isset($input['error']) && $input['error'] == 4) { Logger::error(i18n::s('No file has been transmitted.')); } elseif (!$input['size']) { Logger::error(i18n::s('No file has been transmitted.')); } // do we have a file? if (!isset($input['name']) || !$input['name'] || $input['name'] == 'none') { return FALSE; } // access the temporary uploaded file $file_upload = $input['tmp_name']; // $_FILES transcoding to utf8 is not automatic $input['name'] = utf8::encode($input['name']); // enhance file name $file_name = $input['name']; $file_extension = ''; $position = strrpos($input['name'], '.'); if ($position !== FALSE) { $file_name = substr($input['name'], 0, $position); $file_extension = strtolower(substr($input['name'], $position + 1)); } $input['name'] = $file_name; if ($file_extension) { $input['name'] .= '.' . $file_extension; } // ensure we have a file name $file_name = utf8::to_ascii($input['name']); // uploads are not allowed if (!Surfer::may_upload()) { Logger::error(i18n::s('You are not allowed to perform this operation.')); } elseif (!Files::is_authorized($input['name'])) { Logger::error(i18n::s('This type of file is not allowed.')); } elseif ($file_path && !Safe::is_uploaded_file($file_upload)) { Logger::error(i18n::s('Possible file attack.')); } else { // create folders if ($file_path) { Safe::make_path($file_path); } // sanity check if ($file_path && $file_path[strlen($file_path) - 1] != '/') { $file_path .= '/'; } // move the uploaded file if ($file_path && !Safe::move_uploaded_file($file_upload, $context['path_to_root'] . $file_path . $file_name)) { Logger::error(sprintf(i18n::s('Impossible to move the upload file to %s.'), $file_path . $file_name)); } else { // process the file where it is if (!$file_path) { $file_path = str_replace($context['path_to_root'], '', dirname($file_upload)); $file_name = basename($file_upload); } // check against viruses $result = Files::has_virus($context['path_to_root'] . $file_path . '/' . $file_name); // no virus has been found in this file if ($result == 'N') { $context['text'] .= Skin::build_block(i18n::s('No virus has been found.'), 'note'); } // this file has been infected! if ($result == 'Y') { // delete this file immediately Safe::unlink($file_path . '/' . $file_name); Logger::error(i18n::s('This file has been infected by a virus and has been rejected!')); return FALSE; } // explode a .zip file include_once $context['path_to_root'] . 'shared/zipfile.php'; if (preg_match('/\\.zip$/i', $file_name) && isset($_REQUEST['explode_files'])) { $zipfile = new zipfile(); // check files extracted from the archive file function explode_callback($name) { global $context; // reject all files put in sub-folders if (($path = substr($name, strlen($context['uploaded_path'] . '/'))) && strpos($path, '/') !== FALSE) { Safe::unlink($name); } elseif (!Files::is_authorized($name)) { Safe::unlink($name); } else { // make it easy to download $ascii = utf8::to_ascii(basename($name)); Safe::rename($name, $context['uploaded_path'] . '/' . $ascii); // remember this name $context['uploaded_files'][] = $ascii; } } // extract archive components and save them in mentioned directory $context['uploaded_files'] = array(); $context['uploaded_path'] = $file_path; if (!($count = $zipfile->explode($context['path_to_root'] . $file_path . '/' . $file_name, $file_path, '', 'explode_callback'))) { Logger::error(sprintf('Nothing has been extracted from %s.', $file_name)); return FALSE; } // one single file has been uploaded } else { $context['uploaded_files'] = array($file_name); } // ensure we know the surfer Surfer::check_default_editor($_REQUEST); // post-process all uploaded files foreach ($context['uploaded_files'] as $file_name) { // this will be filtered by umask anyway Safe::chmod($context['path_to_root'] . $file_path . $file_name, $context['file_mask']); // invoke post-processing function if ($target && is_callable($target)) { call_user_func($target, $file_name, $context['path_to_root'] . $file_path); // we have to update an anchor page } elseif ($target && is_string($target)) { $fields = array(); // update a file with the same name for this anchor if ($matching =& Files::get_by_anchor_and_name($target, $file_name)) { $fields['id'] = $matching['id']; } elseif (isset($input['id']) && ($matching = Files::get($input['id']))) { $fields['id'] = $matching['id']; // silently delete the previous version of the file if (isset($matching['file_name'])) { Safe::unlink($file_path . '/' . $matching['file_name']); } } // prepare file record $fields['file_name'] = $file_name; $fields['file_size'] = filesize($context['path_to_root'] . $file_path . $file_name); $fields['file_href'] = ''; $fields['anchor'] = $target; // change title if (isset($_REQUEST['title'])) { $fields['title'] = $_REQUEST['title']; } // change has been documented if (!isset($_REQUEST['version']) || !$_REQUEST['version']) { $_REQUEST['version'] = ''; } else { $_REQUEST['version'] = ' - ' . $_REQUEST['version']; } // always remember file uploads, for traceability $_REQUEST['version'] = $fields['file_name'] . ' (' . Skin::build_number($fields['file_size'], i18n::s('bytes')) . ')' . $_REQUEST['version']; // add to file history $fields['description'] = Files::add_to_history($matching, $_REQUEST['version']); // if this is an image, maybe we can derive a thumbnail for it? if (Files::is_image($file_name)) { include_once $context['path_to_root'] . 'images/image.php'; Image::shrink($context['path_to_root'] . $file_path . $file_name, $context['path_to_root'] . $file_path . 'thumbs/' . $file_name); if (file_exists($context['path_to_root'] . $file_path . 'thumbs/' . $file_name)) { $fields['thumbnail_url'] = $context['url_to_home'] . $context['url_to_root'] . $file_path . 'thumbs/' . rawurlencode($file_name); } } // change active_set if (isset($_REQUEST['active_set'])) { $fields['active_set'] = $_REQUEST['active_set']; } // change source if (isset($_REQUEST['source'])) { $fields['source'] = $_REQUEST['source']; } // change keywords if (isset($_REQUEST['keywords'])) { $fields['keywords'] = $_REQUEST['keywords']; } // change alternate_href if (isset($_REQUEST['alternate_href'])) { $fields['alternate_href'] = $_REQUEST['alternate_href']; } // overlay, if any if (is_object($overlay)) { // allow for change detection $overlay->snapshot(); // update the overlay from form content $overlay->parse_fields($_REQUEST); // save content of the overlay in this item $fields['overlay'] = $overlay->save(); $fields['overlay_id'] = $overlay->get_id(); } // create the record in the database if (!($fields['id'] = Files::post($fields))) { return FALSE; } // record surfer activity Activities::post('file:' . $fields['id'], 'upload'); } } // so far so good if (count($context['uploaded_files']) == 1) { return $context['uploaded_files'][0]; } else { return $context['uploaded_files']; } } } // some error has occured return FALSE; }
/** * get only some attributes * * @param int the id of the article * @param mixed names of the attributes to return * @param boolean TRUE to always fetch a fresh instance, FALSE to enable cache * @return the resulting $item array, with at least keys: 'id', 'title', 'description', etc. */ public static function &get_attributes($id, $attributes, $mutable = FALSE) { global $context; // sanity check if (!$id) { $output = NULL; return $output; } // ensure proper unicode encoding $id = (string) $id; $id = utf8::encode($id); // filter id from reference if parameter given that way if (substr($id, 0, 8) === 'article:') { $id = substr($id, 8); } // cache previous answers static $cache; if (!is_array($cache)) { $cache = array(); } // cache hit, but only for immutable objects if (!$mutable && isset($cache[$id])) { return $cache[$id]; } // search by id if (is_numeric($id)) { $query = "SELECT " . SQL::escape($attributes) . " FROM " . SQL::table_name('articles') . " WHERE (id = " . SQL::escape((int) $id) . ")"; // do the job $output = SQL::query_first($query); } else { $query = "SELECT " . SQL::escape($attributes) . " FROM " . SQL::table_name('articles') . " WHERE (nick_name LIKE '" . SQL::escape($id) . "') OR (handle LIKE '" . SQL::escape($id) . "')"; $count = SQL::query_count($query); if ($count == 1) { // do the job $output = SQL::query_first($query); } elseif ($count > 1) { // result depending language give by $context['page_language'] if (!isset($_SESSION['surfer_language']) || $_SESSION['surfer_language'] == 'none') { $language = $context['language']; } else { $language = $_SESSION['surfer_language']; } $result = SQL::query($query); while ($item = SQL::fetch($result)) { $output = $item; // return last by default if ($item['language'] == $language) { $output = $item; break; } } } } // save in cache, but only on generic request if (isset($output['id']) && $attributes == '*' && count($cache) < 1000) { $cache[$id] = $output; } // return by reference return $output; }
if (!Surfer::is_logged() || !is_object($anchor)) { if (isset($_REQUEST['anchor']) && $_REQUEST['anchor']) { $_SESSION['anchor_reference'] = $_REQUEST['anchor']; } elseif (isset($_REQUEST['category']) && $_REQUEST['category']) { $_SESSION['anchor_reference'] = 'category:' . $_REQUEST['category']; } elseif (isset($_REQUEST['section']) && $_REQUEST['section']) { $_SESSION['anchor_reference'] = 'section:' . $_REQUEST['section']; } if (isset($_REQUEST['link']) && $_REQUEST['link']) { $_SESSION['pasted_link'] = utf8::encode($_REQUEST['link']); } if (isset($_REQUEST['title']) && $_REQUEST['title']) { $_SESSION['pasted_title'] = utf8::encode($_REQUEST['title']); } if (isset($_REQUEST['text']) && $_REQUEST['text']) { $_SESSION['pasted_text'] = utf8::encode($_REQUEST['text']); } } // validate input syntax only if required if (isset($_REQUEST['option_validate']) && $_REQUEST['option_validate'] == 'Y') { if (isset($_REQUEST['description'])) { xml::validate($_REQUEST['description']); } } // stop crawlers if (Surfer::is_crawler()) { Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('You are not allowed to perform this operation.')); // permission denied } elseif (!$permitted) { // anonymous users are invited to log in or to register
/** * normalize an external reference * * This function strips noise attributes from search engines * * @param string the raw reference * @return an array( normalized string, search keywords ) */ public static function normalize($link) { global $context; // get the query string, if any $tokens = explode('?', $link, 2); $link = $tokens[0]; $query_string = ''; if (isset($tokens[1])) { $query_string = $tokens[1]; } // split the query string in variables, if any $attributes = array(); if ($query_string) { $tokens = explode('&', $query_string); foreach ($tokens as $token) { list($name, $value) = explode('=', $token); $name = urldecode($name); $value = urldecode($value); // strip any PHPSESSID data if (preg_match('/^PHPSESSID/i', $name)) { continue; } // strip any JSESSIONID data if (preg_match('/^jsessionid/i', $name)) { continue; } // remember this variable $attributes[$name] = $value; } } // looking for keywords $keywords = ''; // link options, if any $suffix = ''; // coming from altavista if (preg_match('/\\baltavista\\b.+/', $link) && isset($attributes['q'])) { $attributes = array('q' => $attributes['q']); $keywords = $attributes['q']; // coming from aol } elseif (preg_match('/\\baol\\b.+/', $link) && isset($attributes['q'])) { $attributes = array('q' => $attributes['q']); $keywords = $attributes['q']; // coming from ask } elseif (preg_match('/\\bask\\b.+/', $link) && isset($attributes['q'])) { $attributes = array('q' => $attributes['q']); $keywords = $attributes['q']; // coming from google } elseif (preg_match('/\\bgoogle\\b.+/', $link) && isset($attributes['q'])) { // signal to Google the charset to be used if (isset($attributes['ie'])) { $suffix = '&ie=' . urlencode($attributes['ie']); } $attributes = array('q' => $attributes['q']); $keywords = $attributes['q']; // coming from msn } elseif (preg_match('/\\bmsn\\b.+/', $link) && isset($attributes['q'])) { $attributes = array('q' => $attributes['q']); $keywords = $attributes['q']; // coming from yahoo } elseif (preg_match('/\\byahoo\\b.+/', $link) && isset($attributes['p'])) { $attributes = array('p' => $attributes['p']); $keywords = $attributes['p']; } // rebuild a full link $query_string = ''; foreach ($attributes as $name => $value) { if ($query_string) { $query_string .= '&'; } $query_string .= urlencode($name) . '=' . urlencode($value); } if ($query_string) { $link .= '?' . $query_string . $suffix; } // extract the referer domain $domain = preg_replace("/^\\w+:\\/\\//i", "", $link); $domain = preg_replace("/^www\\./i", "", $domain); $domain = preg_replace("/\\/.*/i", "", $domain); // transcode keywords, and make it a safe string to display if ($keywords) { $keywords = utf8::encode(htmlspecialchars($keywords)); } // return normalized elements return array($link, trim($domain), trim($keywords)); }
$_SESSION['pasted_introduction'] = utf8::encode($_REQUEST['introduction']); } if (isset($_REQUEST['name']) && $_REQUEST['name']) { $_SESSION['pasted_name'] = $_REQUEST['name']; } if (isset($_REQUEST['section']) && $_REQUEST['section']) { $_SESSION['pasted_section'] = $_REQUEST['section']; } if (isset($_REQUEST['source']) && $_REQUEST['source']) { $_SESSION['pasted_source'] = utf8::encode($_REQUEST['source']); } if (isset($_REQUEST['text']) && $_REQUEST['text']) { $_SESSION['pasted_text'] = utf8::encode($_REQUEST['text']); } if (isset($_REQUEST['title']) && $_REQUEST['title']) { $_SESSION['pasted_title'] = utf8::encode($_REQUEST['title']); } if (isset($_REQUEST['variant']) && $_REQUEST['variant']) { $_SESSION['pasted_variant'] = $_REQUEST['variant']; } } // validate input syntax only if required if (isset($_REQUEST['option_validate']) && $_REQUEST['option_validate'] == 'Y') { if (isset($_REQUEST['introduction'])) { xml::validate($_REQUEST['introduction']); } if (isset($_REQUEST['description'])) { xml::validate($_REQUEST['description']); } } // stop crawlers
/** * update the stack on closing tags * * The value of cdata is converted explicitly on following tags: * - </base64> * - </boolean> * - </date> * - </double> * - </integer> * - </string> * * The result is updated on following tags: * - </value> * - </methodName> * * The stack is updated on following tags: * - </methodCall>: pop 'methodCall' * - </methodResponse>: pop 'methodResponse' * - </fault>: pop 'fault' * - </params>: pop index, then pop 'params' * - </name>: push cdata (named stem) * - </member>: pop cdata * - </array>: pop index * */ function parse_tag_close($parser, $tag) { global $context; if (isset($this->cdata) && is_string($this->cdata)) { $this->cdata = trim($this->cdata); } // expand the stack if ($tag == 'name') { array_push($this->stack, $this->cdata); unset($this->cdata); return; } // convert cdata switch ($tag) { case 'base64': $this->cdata = base64_decode($this->cdata); return; case 'boolean': if (preg_match('/^(1|true)$/i', $this->cdata)) { $this->cdata = TRUE; } else { $this->cdata = FALSE; } return; case 'dateTime.iso8601': $value = (string) $this->cdata; $year = (int) substr($value, 0, 4); $month = (int) substr($value, 4, 2); $day = (int) substr($value, 6, 2); $hour = (int) substr($value, 9, 2); $minute = (int) substr($value, 12, 2); $second = (int) substr($value, 15, 2); $this->cdata = mktime($hour, $minute, $second, $month, $day, $year); return; case 'double': $this->cdata = (double) $this->cdata; return; case 'i4': case 'int': $this->cdata = (int) $this->cdata; return; case 'string': // transcode to our internal charset, if unicode if ($context['charset'] == 'utf-8' && isset($this->cdata)) { $this->cdata = utf8::encode($this->cdata); } return; } // sanity check if (!isset($this->cdata)) { $this->cdata = ''; } // update the result tree if ($tag == 'value' || $tag == 'methodName') { // browse containers $here =& $this->result; $container_id = NULL; foreach ($this->stack as $container_id) { if (!isset($here[$container_id])) { $here[$container_id] = array(); } $here =& $here[$container_id]; } // update a leaf if ($tag == 'value' && !@count($here)) { $here = $this->cdata; unset($this->cdata); } elseif ($tag == 'methodName') { $here[$tag] = $this->cdata; unset($this->cdata); } } // update the stack if (preg_match('/^(array|fault|member|methodCall|methodResponse)$/', $tag)) { array_pop($this->stack); } elseif ($tag == 'params') { array_pop($this->stack); array_pop($this->stack); } }
/** * list keywords * * This function is used to list all keywords starting with provided letters. * * @param string prefix to consider * @paral string or int nickname or ID of category keywords have to be child to * @return an array of matching $keyword => $introduction * * @see categories/complete.php */ public static function &list_keywords($prefix, $mothercat = NULL) { global $context; // we return an array $output = array(); // ensure proper unicode encoding $prefix = utf8::encode($prefix); // look for mothercat if ($mothercat = categories::get($mothercat)) { $more = ' AND categories.anchor = "category:' . $mothercat['id'] . '"'; } else { $more = ''; } // select among available items $query = "SELECT keywords, introduction FROM " . SQL::table_name('categories') . " AS categories" . " WHERE categories.keywords LIKE '" . SQL::escape($prefix) . "%'" . $more . " ORDER BY keywords LIMIT 100"; $result = SQL::query($query); // populate the returned array while ($row = SQL::fetch($result)) { $output[$row['keywords']] = $row['introduction']; } // return by reference return $output; }