/** * Get block of attachments/files linked to the current Item * * @param array Array of params * @param string Output format, see {@link format_to_output()} * @return string HTML */ function get_files($params = array(), $format = 'htmlbody') { global $Plugins; $params = array_merge(array('before' => '<div class="item_attachments"><h3>' . T_('Attachments') . ':</h3><ul class="bFiles">', 'before_attach' => '<li>', 'before_attach_size' => '<span class="file_size">(', 'after_attach_size' => ')</span>', 'after_attach' => '</li>', 'after' => '</ul></div>', 'limit_attach' => 1000, 'limit' => 1000, 'restrict_to_image_position' => 'cover,teaser,teaserperm,teaserlink,aftermore', 'data' => '', 'attach_format' => '$icon_link$ $file_link$ $file_size$', 'file_link_format' => '$file_name$', 'file_link_class' => '', 'download_link_icon' => 'download', 'download_link_title' => T_('Download file')), $params); // Get list of attached files $LinkOwner = new LinkItem($this); if (!($LinkList = $LinkOwner->get_attachment_LinkList($params['limit'], $params['restrict_to_image_position']))) { return ''; } load_funcs('files/model/_file.funcs.php'); $r = ''; $i = 0; $r_file = array(); /** * @var File */ $File = NULL; while (($Link =& $LinkList->get_next()) && $params['limit_attach'] > $i) { if (!($File =& $Link->get_File())) { // No File object global $Debuglog; $Debuglog->add(sprintf('Link ID#%d of item #%d does not have a file object!', $Link->ID, $this->ID), array('error', 'files')); continue; } if (!$File->exists()) { // File doesn't exist global $Debuglog; $Debuglog->add(sprintf('File linked to item #%d does not exist (%s)!', $this->ID, $File->get_full_path()), array('error', 'files')); continue; } $params['File'] = $File; $params['Item'] = $this; $temp_params = $params; foreach ($params as $param_key => $param_value) { // Pass all params by reference, in order to give possibility to modify them by plugin // So plugins can add some data before/after image tags (E.g. used by infodots plugin) $params[$param_key] =& $params[$param_key]; } if (count($Plugins->trigger_event_first_true('RenderItemAttachment', $params)) != 0) { continue; } if ($File->is_image()) { // Skip images because these are displayed inline already // fp> TODO: have a setting for each linked file to decide whether it should be displayed inline or as an attachment continue; } elseif ($File->is_dir()) { // Skip directories/galleries continue; } if ($File->is_audio()) { // Player for audio file: $r_file[$i] = '<div class="podplayer">'; $r_file[$i] .= $this->get_player($File->get_url()); $r_file[$i] .= '</div>'; $i++; $params = $temp_params; continue; } // A link to download a file: // Just icon with download icon $icon = $File->exists() && strpos($params['attach_format'] . $params['file_link_format'], '$icon$') !== false ? get_icon($params['download_link_icon'], 'imgtag', array('title' => $params['download_link_title'])) : ''; // A link with icon to download $icon_link = $File->exists() && strpos($params['attach_format'], '$icon_link$') !== false ? action_icon($params['download_link_title'], $params['download_link_icon'], $File->get_url(), '', 5) : ''; // File size info $file_size = $File->exists() && strpos($params['attach_format'] . $params['file_link_format'], '$file_size$') !== false ? $params['before_attach_size'] . bytesreadable($File->get_size(), false, false) . $params['after_attach_size'] : ''; // A link with file name to download $file_link_format = str_replace(array('$icon$', '$file_name$', '$file_size$'), array($icon, '$text$', $file_size), $params['file_link_format']); if ($File->exists()) { // Get file link to download if file exists $file_link = strpos($params['attach_format'], '$file_link$') !== false ? $File->get_view_link($File->get_name(), NULL, NULL, $file_link_format, $params['file_link_class'], $Link->get_download_url()) : ''; } else { // File doesn't exist, We cannot display a link, Display only file name and warning $file_link = strpos($params['attach_format'], '$file_link$') !== false ? $File->get_name() . ' - <span class="red nowrap">' . get_icon('warning_yellow') . ' ' . T_('Missing attachment!') . '</span>' : ''; } $r_file[$i] = $params['before_attach']; $r_file[$i] .= str_replace(array('$icon$', '$icon_link$', '$file_link$', '$file_size$'), array($icon, $icon_link, $file_link, $file_size), $params['attach_format']); $r_file[$i] .= $params['after_attach']; $i++; $params = $temp_params; } if (!empty($r_file)) { $r = $params['before'] . implode("\n", $r_file) . $params['after']; // Character conversions $r = format_to_output($r, $format); } return $r; }
/** * Template function: display content of comment * * @param string Output format, see {@link format_to_output()} * @param boolean Add ban url action icon after each url or not * @param boolean show comment attachments * @param array attachment display params */ function content($format = 'htmlbody', $ban_urls = false, $show_attachments = true, $params = array()) { global $current_User; global $Plugins; // Make sure we are not missing any param: $params = array_merge(array('before_image' => '<figure class="evo_image_block">', 'before_image_legend' => '<figcaption class="evo_image_legend">', 'after_image_legend' => '</figcaption>', 'after_image' => '</figure>', 'image_size' => 'fit-400x320', 'image_class' => '', 'image_text' => '', 'attachments_mode' => 'read', 'attachments_view_text' => ''), $params); $attachments = array(); if ($show_attachments) { if (empty($this->ID) && isset($this->checked_attachments)) { // PREVIEW $attachment_ids = explode(',', $this->checked_attachments); $FileCache =& get_FileCache(); foreach ($attachment_ids as $ID) { $File = $FileCache->get_by_ID($ID, false, false); if ($File != NULL) { $attachments[] = $File; } } } else { // Get all Links $LinkOwner = new LinkComment($this); $attachments =& $LinkOwner->get_Links(); } } $images_above_content = ''; $images_below_content = ''; foreach ($attachments as $index => $attachment) { if (!empty($this->ID)) { // Normal mode when comment exists in DB (NOT PREVIEW mode) $Link = $attachment; $link_position = $Link->get('position'); $params['Link'] = $Link; $attachment = $attachment->get_File(); } else { // Set default position for preview files $link_position = 'aftermore'; } $File = $attachment; if (empty($File)) { // File object doesn't exist in DB global $Debuglog; $Debuglog->add(sprintf('File object linked to comment #%d does not exist in DB!', $this->ID), array('error', 'files')); continue; } if (!$File->exists()) { // File doesn't exist on the disk global $Debuglog; $Debuglog->add(sprintf('File linked to comment #%d does not exist (%s)!', $this->ID, $File->get_full_path()), array('error', 'files')); continue; } $r = ''; $params['File'] = $File; $params['Comment'] = $this; $params['data'] =& $r; $temp_params = $params; foreach ($params as $param_key => $param_value) { // Pass all params by reference, in order to give possibility to modify them by plugin // So plugins can add some data before/after image tag (E.g. used by infodots plugin) $params[$param_key] =& $params[$param_key]; } if (count($Plugins->trigger_event_first_true('RenderCommentAttachment', $params)) != 0) { // File was processed by plugin if ($link_position == 'teaser') { // Image should be displayed above content $images_above_content .= $r; } else { // Image should be displayed below content $images_below_content .= $r; } unset($attachments[$index]); continue; } if ($File->is_image()) { // File is image if ($params['attachments_mode'] == 'view') { // Only preview attachments $image_link_rel = ''; $image_link_to = ''; } else { // Read attachments $image_link_rel = 'lightbox[c' . $this->ID . ']'; $image_link_to = 'original'; } if (empty($this->ID)) { // PREVIEW mode $r = $File->get_tag($params['before_image'], $params['before_image_legend'], $params['after_image_legend'], $params['after_image'], $params['image_size'], $image_link_to, T_('Posted by ') . $this->get_author_name(), $image_link_rel, $params['image_class'], '', '', '#'); } else { $r = $Link->get_tag(array_merge(array('image_link_to' => $image_link_to, 'image_link_title' => T_('Posted by ') . $this->get_author_name(), 'image_link_rel' => $image_link_rel), $params)); } if ($link_position == 'teaser') { // Image should be displayed above content $images_above_content .= $r; } else { // Image should be displayed below content $images_below_content .= $r; } unset($attachments[$index]); } $params = $temp_params; } if (!empty($images_above_content)) { // Display images above content echo $images_above_content; if ($params['image_text'] != '') { // Display info text below pictures echo $params['image_text']; } } if ($ban_urls) { // add ban icons if user has edit permission for this comment $ban_urls = $current_User->check_perm('comment!CURSTATUS', 'edit', false, $this); } if ($ban_urls) { // ban urls and user has permission echo add_ban_icons($this->get_content($format)); } else { // don't ban urls echo $this->get_content($format); } if (!empty($images_below_content)) { // Display images below content echo $images_below_content; if (empty($images_above_content) && $params['image_text'] != '') { // Display info text below pictures echo $params['image_text']; } } if (isset($attachments)) { // show not image attachments $after_docs = ''; if (count($attachments) > 0) { echo '<br /><b>' . T_('Attachments:') . '</b>'; echo '<ul class="bFiles">'; $after_docs = '</ul>'; } foreach ($attachments as $attachment) { // $attachment is a File in preview mode, but it is a Link in normal mode $doc_File = empty($this->ID) ? $attachment : $attachment->get_File(); echo '<li>'; if (empty($doc_File)) { // Broken File object $attachment_download_link = ''; $attachment_name = empty($attachment) ? '' : T_('Link ID') . '#' . $attachment->ID; } elseif (!$doc_File->exists()) { $attachment_download_link = ''; $attachment_name = $doc_File->get_name(); } elseif ($params['attachments_mode'] == 'view') { // Only preview attachments $attachment_download_link = ''; $attachment_name = $doc_File->get_type(); } else { // Read attachments $attachment_download_link = action_icon(T_('Download file'), 'download', $doc_File->get_url(), '', 5) . ' '; $attachment_name = $doc_File->get_view_link($doc_File->get_name()); } echo $attachment_download_link; echo $attachment_name; if (!empty($doc_File) && $doc_File->exists()) { // Display file size if it exists echo ' (' . bytesreadable($doc_File->get_size()) . ')'; } else { // Display warning if File is broken echo ' - <span class="red nowrap">' . get_icon('warning_yellow') . ' ' . T_('Missing attachment!') . '</span>'; } if (!empty($params['attachments_view_text'])) { echo $params['attachments_view_text']; } echo '</li>'; } echo $after_docs; } }
/** * Process file uploads (this can process multiple file uploads at once) * * @param string FileRoot id string * @param string the upload dir relative path in the FileRoot * @param boolean Shall we create path dirs if they do not exist? * @param boolean Shall we check files add permission for current_User? * @param boolean upload quick mode * @param boolean show warnings if filename is not valid * @param integer minimum size for pictures in pixels (width and height) * @return mixed NULL if upload was impossible to complete for some reason (wrong fileroot ID, insufficient user permission, etc.) * array, which contains uploadedFiles, failedFiles, renamedFiles and renamedMessages */ function process_upload($root_ID, $path, $create_path_dirs = false, $check_perms = true, $upload_quickmode = true, $warn_invalid_filenames = true, $min_size = 0) { global $Settings, $Plugins, $Messages, $current_User, $force_upload_forbiddenext; if (empty($_FILES)) { // We have NO uploaded files to process... return NULL; } /** * Remember failed files (and the error messages) * @var array */ $failedFiles = array(); /** * Remember uploaded files * @var array */ $uploadedFiles = array(); /** * Remember renamed files * @var array */ $renamedFiles = array(); /** * Remember renamed Messages * @var array */ $renamedMessages = array(); $FileRootCache =& get_FileRootCache(); $fm_FileRoot =& $FileRootCache->get_by_ID($root_ID, true); if (!$fm_FileRoot) { // fileRoot not found: return NULL; } if ($check_perms && (!isset($current_User) || $current_User->check_perm('files', 'add', false, $fm_FileRoot))) { // Permission check required but current User has no permission to upload: return NULL; } // Let's get into requested list dir... $non_canonical_list_path = $fm_FileRoot->ads_path . $path; // Dereference any /../ just to make sure, and CHECK if directory exists: $ads_list_path = get_canonical_path($non_canonical_list_path); // check if the upload dir exists if (!is_dir($ads_list_path)) { if ($create_path_dirs) { // Create path mkdir_r($ads_list_path); } else { // This case should not happen! If it happens then there is a bug in the code where this function was called! return NULL; } } // Get param arrays for all uploaded files: $uploadfile_title = param('uploadfile_title', 'array/string', array()); $uploadfile_alt = param('uploadfile_alt', 'array/string', array()); $uploadfile_desc = param('uploadfile_desc', 'array/string', array()); $uploadfile_name = param('uploadfile_name', 'array/string', array()); // LOOP THROUGH ALL UPLOADED FILES AND PROCCESS EACH ONE: foreach ($_FILES['uploadfile']['name'] as $lKey => $lName) { if (empty($lName)) { // No file name: if ($upload_quickmode || !empty($uploadfile_title[$lKey]) || !empty($uploadfile_alt[$lKey]) || !empty($uploadfile_desc[$lKey]) || !empty($uploadfile_name[$lKey])) { // User specified params but NO file! Warn the user: $failedFiles[$lKey] = T_('Please select a local file to upload.'); } // Abort upload for this file: continue; } if ($Settings->get('upload_maxkb') && $_FILES['uploadfile']['size'][$lKey] > $Settings->get('upload_maxkb') * 1024) { // File is larger than allowed in settings: $failedFiles[$lKey] = sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($_FILES['uploadfile']['size'][$lKey]), bytesreadable($Settings->get('upload_maxkb') * 1024)); // Abort upload for this file: continue; } if (!empty($min_size)) { // Check pictures for small sizes $image_sizes = imgsize($_FILES['uploadfile']['tmp_name'][$lKey], 'widthheight'); if ($image_sizes[0] < $min_size || $image_sizes[1] < $min_size) { // Abort upload for this file: $failedFiles[$lKey] = sprintf(T_('Your profile picture must have a minimum size of %dx%d pixels.'), $min_size, $min_size); continue; } } if ($_FILES['uploadfile']['error'][$lKey]) { // PHP itself has detected an error!: switch ($_FILES['uploadfile']['error'][$lKey]) { case UPLOAD_ERR_FORM_SIZE: // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form. // This can easily be edited by the user/hacker, so we do not use it.. file size gets checked for real just above. break; case UPLOAD_ERR_INI_SIZE: // File is larger than allowed in php.ini: $failedFiles[$lKey] = 'The file exceeds the upload_max_filesize directive in php.ini.'; // Configuration error, no translation // Abort upload for this file: continue; case UPLOAD_ERR_PARTIAL: $failedFiles[$lKey] = T_('The file was only partially uploaded.'); // Abort upload for this file: continue; case UPLOAD_ERR_NO_FILE: // Is probably the same as empty($lName) before. $failedFiles[$lKey] = T_('No file was uploaded.'); // Abort upload for this file: continue; case 6: // numerical value of UPLOAD_ERR_NO_TMP_DIR # (min_php: 4.3.10, 5.0.3) case UPLOAD_ERR_NO_TMP_DIR: // Missing a temporary folder. $failedFiles[$lKey] = 'Temporary upload dir is missing! (upload_tmp_dir in php.ini)'; // Configuration error, no translation // Abort upload for this file: continue; default: $failedFiles[$lKey] = T_('An unknown error has occurred!') . ' Error code #' . $_FILES['uploadfile']['error'][$lKey]; // Abort upload for this file: continue; } } if (!isset($_FILES['uploadfile']['_evo_fetched_url'][$lKey]) && !is_uploaded_file($_FILES['uploadfile']['tmp_name'][$lKey])) { // Ensure that a malicious user hasn't tried to trick the script into working on files upon which it should not be working. $failedFiles[$lKey] = T_('The file does not seem to be a valid upload! It may exceed the upload_max_filesize directive in php.ini.'); // Abort upload for this file: continue; } // Use new name on server if specified: $newName = !empty($uploadfile_name[$lKey]) ? $uploadfile_name[$lKey] : $lName; // validate file name if ($error_filename = process_filename($newName, !$warn_invalid_filenames)) { // Not a valid file name or not an allowed extension: $failedFiles[$lKey] = $error_filename; // Abort upload for this file: continue; } // Check if the uploaded file type is an image, and if is an image then try to fix the file extension based on mime type // If the mime type is a known mime type and user has right to upload files with this kind of file type, // this part of code will check if the file extension is the same as admin defined for this file type, and will fix it if it isn't the same // Note: it will also change the jpeg extensions to jpg. $uploadfile_path = $_FILES['uploadfile']['tmp_name'][$lKey]; // this image_info variable will be used again to get file thumb $image_info = getimagesize($uploadfile_path); if ($image_info) { // This is an image, validate mimetype vs. extension: $image_mimetype = $image_info['mime']; $FiletypeCache =& get_FiletypeCache(); // Get correct file type based on mime type $correct_Filetype = $FiletypeCache->get_by_mimetype($image_mimetype, false, false); // Check if file type is known by us, and if it is allowed for upload. // If we don't know this file type or if it isn't allowed we don't change the extension! The current extension is allowed for sure. if ($correct_Filetype && $correct_Filetype->is_allowed()) { // A FileType with the given mime type exists in database and it is an allowed file type for current User // The "correct" extension is a plausible one, proceed... $correct_extension = array_shift($correct_Filetype->get_extensions()); $path_info = pathinfo($newName); $current_extension = $path_info['extension']; // change file extension to the correct extension, but only if the correct extension is not restricted, this is an extra security check! if (strtolower($current_extension) != strtolower($correct_extension) && !in_array($correct_extension, $force_upload_forbiddenext)) { // change the file extension to the correct extension $old_name = $newName; $newName = $path_info['filename'] . '.' . $correct_extension; $Messages->add(sprintf(T_('The extension of the file «%s» has been corrected. The new filename is «%s».'), $old_name, $newName), 'warning'); } } } // Get File object for requested target location: $oldName = strtolower($newName); list($newFile, $oldFile_thumb) = check_file_exists($fm_FileRoot, $path, $newName, $image_info); $newName = $newFile->get('name'); // Trigger plugin event if ($Plugins->trigger_event_first_false('AfterFileUpload', array('File' => &$newFile, 'name' => &$_FILES['uploadfile']['name'][$lKey], 'type' => &$_FILES['uploadfile']['type'][$lKey], 'tmp_name' => &$_FILES['uploadfile']['tmp_name'][$lKey], 'size' => &$_FILES['uploadfile']['size'][$lKey]))) { // Plugin returned 'false'. // Abort upload for this file: continue; } // Attempt to move the uploaded file to the requested target location: if (isset($_FILES['uploadfile']['_evo_fetched_url'][$lKey])) { // fetched remotely if (!rename($_FILES['uploadfile']['tmp_name'][$lKey], $newFile->get_full_path())) { $failedFiles[$lKey] = T_('An unknown error occurred when moving the uploaded file on the server.'); // Abort upload for this file: continue; } } elseif (!move_uploaded_file($_FILES['uploadfile']['tmp_name'][$lKey], $newFile->get_full_path())) { $failedFiles[$lKey] = T_('An unknown error occurred when moving the uploaded file on the server.'); // Abort upload for this file: continue; } // change to default chmod settings if ($newFile->chmod(NULL) === false) { // add a note, this is no error! $Messages->add(sprintf(T_('Could not change permissions of «%s» to default chmod setting.'), $newFile->dget('name')), 'note'); } // Refreshes file properties (type, size, perms...) $newFile->load_properties(); if (!empty($oldFile_thumb)) { // The file name was changed! if ($image_info) { $newFile_thumb = $newFile->get_preview_thumb('fulltype'); } else { $newFile_thumb = $newFile->get_size_formatted(); } //$newFile_size = bytesreadable ($_FILES['uploadfile']['size'][$lKey]); $renamedMessages[$lKey]['message'] = sprintf(T_('"%s was renamed to %s. Would you like to replace %s with the new version instead?'), '«' . $oldName . '»', '«' . $newName . '»', '«' . $oldName . '»'); $renamedMessages[$lKey]['oldThumb'] = $oldFile_thumb; $renamedMessages[$lKey]['newThumb'] = $newFile_thumb; $renamedFiles[$lKey]['oldName'] = $oldName; $renamedFiles[$lKey]['newName'] = $newName; } // Store extra info about the file into File Object: if (isset($uploadfile_title[$lKey])) { // If a title text has been passed... (does not happen in quick upload mode) $newFile->set('title', trim(strip_tags($uploadfile_title[$lKey]))); } if (isset($uploadfile_alt[$lKey])) { // If an alt text has been passed... (does not happen in quick upload mode) $newFile->set('alt', trim(strip_tags($uploadfile_alt[$lKey]))); } if (isset($uploadfile_desc[$lKey])) { // If a desc text has been passed... (does not happen in quick upload mode) $newFile->set('desc', trim(strip_tags($uploadfile_desc[$lKey]))); } // Store File object into DB: $newFile->dbsave(); $uploadedFiles[] = $newFile; } prepare_uploaded_files($uploadedFiles); return array('uploadedFiles' => $uploadedFiles, 'failedFiles' => $failedFiles, 'renamedFiles' => $renamedFiles, 'renamedMessages' => $renamedMessages); }
/** * Check the content of a given URL (referer), if the requested URI (with different hostname variations) * is present. * * @todo Use DB cache to avoid checking the same page again and again! (Plugin DB table) * * @param string * @param string URI to append to matching pattern for hostnames * @return boolean */ function is_referer_linking_us($referer, $uri) { global $misc_inc_path, $lib_subdir, $ReqHost; if (empty($referer)) { return false; } // Load page content (max. 500kb), using fsockopen: $url_parsed = @parse_url($referer); if (!$url_parsed) { return false; } if (empty($url_parsed['scheme'])) { $url_parsed = parse_url('http://' . $referer); } $host = $url_parsed['host']; $port = empty($url_parsed['port']) ? 80 : $url_parsed['port']; $path = empty($url_parsed['path']) ? '/' : $url_parsed['path']; if (!empty($url_parsed['query'])) { $path .= '?' . $url_parsed['query']; } $fp = @fsockopen($host, $port, $errno, $errstr, 30); if (!$fp) { // could not access referring page $this->debug_log('is_referer_linking_us(): could not access «' . $referer . '» (host: ' . $host . '): ' . $errstr . ' (#' . $errno . ')'); return false; } // Set timeout for data: if (function_exists('stream_set_timeout')) { stream_set_timeout($fp, 20); } else { socket_set_timeout($fp, 20); } // PHP 4 // Send request: $out = "GET {$path} HTTP/1.0\r\n"; $out .= "Host: {$host}:{$port}\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); // Skip headers: $i = 0; $source_charset = 'iso-8859-1'; // default while (($s = fgets($fp, 4096)) !== false) { $i++; if ($s == "\r\n" || $i > 100) { break; } if (preg_match('~^Content-Type:.*?charset=([\\w-]+)~i', $s, $match)) { $source_charset = $match[1]; } } // Get the refering page's content $content_ref_page = ''; $bytes_read = 0; while (($s = fgets($fp, 4096)) !== false) { $content_ref_page .= $s; $bytes_read += strlen($s); if ($bytes_read > 512000) { // do not pull more than 500kb of data! break; } } fclose($fp); if (!strlen($content_ref_page)) { $this->debug_log('is_referer_linking_us(): empty $content_ref_page (' . bytesreadable($bytes_read) . ' read)'); return false; } $have_idn_name = false; // Build the search pattern: // We match for basically for 'href="[SERVER][URI]', where [SERVER] is a list of possible hosts (especially IDNA) $search_pattern = '~\\shref=["\']?https?://('; $possible_hosts = array($_SERVER['HTTP_HOST']); if ($_SERVER['SERVER_NAME'] != $_SERVER['HTTP_HOST']) { $possible_hosts[] = $_SERVER['SERVER_NAME']; } $search_pattern_hosts = array(); foreach ($possible_hosts as $l_host) { if (preg_match('~^([^.]+\\.)(.*?)([^.]+\\.[^.]+)$~', $l_host, $match)) { // we have subdomains in this hostname if (stristr($match[1], 'www')) { // search also for hostname without 'www.' $search_pattern_hosts[] = $match[2] . $match[3]; } } $search_pattern_hosts[] = $l_host; } $search_pattern_hosts = array_unique($search_pattern_hosts); foreach ($search_pattern_hosts as $l_host) { // add IDN, because this could be linked: $l_idn_host = idna_decode($l_host); // the decoded puny-code ("xn--..") name (utf8) if ($l_idn_host != $l_host) { $have_idn_name = true; $search_pattern_hosts[] = $l_idn_host; } } // add hosts to pattern, preg_quoted for ($i = 0, $n = count($search_pattern_hosts); $i < $n; $i++) { $search_pattern_hosts[$i] = preg_quote($search_pattern_hosts[$i], '~'); } $search_pattern .= implode('|', $search_pattern_hosts) . ')'; if (empty($uri)) { // host(s) should end with "/", "'", '"', "?" or whitespace $search_pattern .= '[/"\'\\s?]'; } else { $search_pattern .= preg_quote($uri, '~'); // URI should end with "'", '"' or whitespace $search_pattern .= '["\'\\s]'; } $search_pattern .= '~i'; if ($have_idn_name) { // Convert charset to UTF-8, because the decoded domain name is UTF-8, too: if (can_convert_charsets('utf-8', $source_charset)) { $content_ref_page = convert_charset($content_ref_page, 'utf-8', $source_charset); } else { $this->debug_log('is_referer_linking_us(): warning: cannot convert charset of referring page'); } } if (preg_match($search_pattern, $content_ref_page)) { $this->debug_log('is_referer_linking_us(): found current URL in page (' . bytesreadable($bytes_read) . ' read)'); return true; } else { if (strpos($referer, $ReqHost) === 0 && !empty($uri)) { // Referer is the same host.. just search for $uri if (strpos($content_ref_page, $uri) !== false) { $this->debug_log('is_referer_linking_us(): found current URI in page (' . bytesreadable($bytes_read) . ' read)'); return true; } } $this->debug_log('is_referer_linking_us(): ' . sprintf('did not find «%s» in «%s» (%s bytes read).', $search_pattern, $referer, bytesreadable($bytes_read))); return false; } }
/** * Template function: display content of comment * * @param string Output format, see {@link format_to_output()} * @param boolean Add ban url action icon after each url or not * @param boolean show comment attachments * @param array attachment display params */ function content($format = 'htmlbody', $ban_urls = false, $show_attachments = true, $params = array()) { global $current_User; global $Plugins; // Make sure we are not missing any param: $params = array_merge(array('before_image' => '<div class="image_block">', 'before_image_legend' => '<div class="image_legend">', 'after_image_legend' => '</div>', 'after_image' => '</div>', 'image_size' => 'fit-400x320', 'image_text' => '', 'attachments_mode' => 'read', 'attachments_view_text' => ''), $params); $attachments = array(); if ($show_attachments) { if (empty($this->ID) && isset($this->checked_attachments)) { // PREVIEW $attachment_ids = explode(',', $this->checked_attachments); $FileCache =& get_FileCache(); foreach ($attachment_ids as $ID) { $File = $FileCache->get_by_ID($ID, false, false); if ($File != NULL) { $attachments[] = $File; } } } else { // Get links $LinkCache =& get_LinkCache(); $commentLinks = $LinkCache->get_by_comment_ID($this->ID); if (!empty($commentLinks)) { foreach ($commentLinks as $Link) { $File = $Link->get_File(); $attachments[] = $File; } } } } $images_is_attached = false; foreach ($attachments as $index => $attachment) { $r = ''; $params['File'] = $attachment; $params['data'] =& $r; if (count($Plugins->trigger_event_first_true('RenderCommentAttachment', $params)) != 0) { echo $r; unset($attachments[$index]); continue; } if ($attachment->is_image()) { if ($params['attachments_mode'] == 'view') { // Only preview attachments $image_link_rel = ''; $image_link_to = ''; } else { // Read attachments $image_link_rel = 'lightbox[c' . $this->ID . ']'; $image_link_to = 'original'; } echo $attachment->get_tag($params['before_image'], $params['before_image_legend'], $params['after_image_legend'], $params['after_image'], $params['image_size'], $image_link_to, T_('Posted by ') . $this->get_author_name(), $image_link_rel); unset($attachments[$index]); $images_is_attached = true; } } if ($images_is_attached && $params['image_text'] != '') { // Display info text below pictures echo $params['image_text']; } if ($ban_urls) { // add ban icons if user has edit permission for this comment $ban_urls = $current_User->check_perm('comment!CURSTATUS', 'edit', false, $this); } if ($ban_urls) { // ban urls and user has permission echo add_ban_icons($this->get_content($format)); } else { // don't ban urls echo $this->get_content($format); } if (isset($attachments)) { // show not image attachments $after_docs = ''; if (count($attachments) > 0) { echo '<br /><b>' . T_('Attachments:') . '</b>'; echo '<ul class="bFiles">'; $after_docs = '</ul>'; } foreach ($attachments as $doc_File) { if ($params['attachments_mode'] == 'view') { // Only preview attachments $attachment_download_link = ''; $attachment_name = $doc_File->get_type(); } else { // Read attachments $attachment_download_link = action_icon(T_('Download file'), 'download', $doc_File->get_url(), '', 5) . ' '; $attachment_name = $doc_File->get_view_link($doc_File->get_name()); } echo '<li>'; echo $attachment_download_link; echo $attachment_name; echo ' (' . bytesreadable($doc_File->get_size()) . ')'; if (!empty($params['attachments_view_text'])) { echo $params['attachments_view_text']; } echo '</li>'; } echo $after_docs; } }
/** * Get block of attachments/files linked to the current Item * * @param array Array of params * @param string Output format, see {@link format_to_output()} * @return string HTML */ function get_files($params = array(), $format = 'htmlbody') { global $Plugins; $params = array_merge(array('before' => '<div class="item_attachments"><h3>' . T_('Attachments') . ':</h3><ul class="bFiles">', 'before_attach' => '<li>', 'before_attach_size' => ' <span class="file_size">', 'after_attach_size' => '</span>', 'after_attach' => '</li>', 'after' => '</ul></div>', 'limit_attach' => 1000, 'limit' => 1000, 'restrict_to_image_position' => '', 'data' => ''), $params); // Get list of attached files $LinkOnwer = new LinkItem($this); if (!($FileList = $LinkOnwer->get_attachment_FileList($params['limit'], $params['restrict_to_image_position']))) { return ''; } load_funcs('files/model/_file.funcs.php'); $r = ''; $i = 0; $r_file = array(); /** * @var File */ $File = NULL; while (($File =& $FileList->get_next()) && $params['limit_attach'] > $i) { $params['File'] = $File; if (count($Plugins->trigger_event_first_true('RenderItemAttachment', $params)) != 0) { continue; } if ($File->is_image()) { // Skip images because these are displayed inline already // fp> TODO: have a setting for each linked file to decide whether it should be displayed inline or as an attachment continue; } elseif ($File->is_dir()) { // Skip directories/galleries continue; } if ($File->is_audio()) { $r_file[$i] = '<div class="podplayer">'; $r_file[$i] .= $this->get_player($File->get_url()); $r_file[$i] .= '</div>'; } else { $r_file[$i] = $params['before_attach']; $r_file[$i] .= action_icon(T_('Download file'), 'download', $File->get_url(), '', 5) . ' '; $r_file[$i] .= $File->get_view_link($File->get_name()); $r_file[$i] .= $params['before_attach_size'] . '(' . bytesreadable($File->get_size()) . ')' . $params['after_attach_size']; $r_file[$i] .= $params['after_attach']; } $i++; } if (!empty($r_file)) { $r = $params['before'] . implode("\n", $r_file) . $params['after']; // Character conversions $r = format_to_output($r, $format); } return $r; }
// Impossible to download $download_success = false; echo '</p><p style="color:red">' . sprintf(T_('Unable to download package from «%s»'), $download_url) . '</p>'; } elseif (!save_to_file($file_contents, $upgrade_file, 'w')) { // Impossible to save file... $download_success = false; echo '</p><p style="color:red">' . sprintf(T_('Unable to create file: «%s»'), $upgrade_file) . '</p>'; if (file_exists($upgrade_file)) { // Remove file from disk if (!@unlink($upgrade_file)) { echo '<p style="color:red">' . sprintf(T_('Unable to remove file: «%s»'), $upgrade_file) . '</p>'; } } } else { // The package is downloaded successfully echo ' OK ' . bytesreadable(filesize($upgrade_file), false, false) . '.</p>'; } evo_flush(); } // Pause the process before next step $AdminUI->disp_view('maintenance/views/_upgrade_downloaded.form.php'); unset($block_item_Widget); break; case 'unzip': case 'force_unzip': // STEP 3: UNZIP. // Check that this action request is not a CSRF hacked request: $Session->assert_received_crumb('upgrade_downloaded'); if ($demo_mode) { $Messages->clear(); $Messages->add(T_('This feature is disabled on the demo server.'), 'error');
/** * metaWeblog.newMediaObject image upload * wp.uploadFile * * Supplied image is encoded into the struct as bits * * @see http://www.xmlrpc.com/metaWeblogApi#metaweblognewmediaobject * @see http://codex.wordpress.org/XML-RPC_wp#wp.uploadFile * * @param xmlrpcmsg XML-RPC Message * 0 blogid (string): Unique identifier of the blog the post will be added to. * Currently ignored in b2evo, in favor of the category. * 1 username (string): Login for a Blogger user who has permission to edit the given * post (either the user who originally created it or an admin of the blog). * 2 password (string): Password for said username. * 3 struct (struct) * - name : filename * - type : mimetype * - bits : base64 encoded file * @return xmlrpcresp XML-RPC Response */ function _wp_mw_newmediaobject($m) { global $Settings, $Plugins, $force_upload_forbiddenext; // CHECK LOGIN: /** * @var User */ if (!($current_User =& xmlrpcs_login($m, 1, 2))) { // Login failed, return (last) error: return xmlrpcs_resperror(); } // GET BLOG: /** * @var Blog */ if (!($Blog =& xmlrpcs_get_Blog($m, 0))) { // Login failed, return (last) error: return xmlrpcs_resperror(); } // CHECK PERMISSION: if (!$current_User->check_perm('files', 'add', false, $Blog->ID)) { // Permission denied return xmlrpcs_resperror(3); // User error 3 } logIO('Permission granted.'); if (!$Settings->get('upload_enabled')) { return xmlrpcs_resperror(2, 'Object upload not allowed'); } $xcontent = $m->getParam(3); // Get the main data - and decode it properly for the image - sorry, binary object logIO('Decoding content...'); $contentstruct = xmlrpc_decode_recurse($xcontent); $data = $contentstruct['bits']; $file_mimetype = isset($contentstruct['type']) ? $contentstruct['type'] : '(none)'; logIO('Received MIME type: ' . $file_mimetype); $overwrite = false; if (isset($contentstruct['overwrite'])) { $overwrite = (bool) $contentstruct['overwrite']; } logIO('Overwrite if exists: ' . ($overwrite ? 'yes' : 'no')); load_funcs('files/model/_file.funcs.php'); $filesize = evo_bytes($data); if (($maxfilesize = $Settings->get('upload_maxkb') * 1024) && $filesize > $maxfilesize) { return xmlrpcs_resperror(4, sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($filesize, false), bytesreadable($maxfilesize, false))); } logIO('File size is OK: ' . bytesreadable($filesize, false)); $FileRootCache =& get_FileRootCache(); $fm_FileRoot =& $FileRootCache->get_by_type_and_ID('collection', $Blog->ID, true); if (!$fm_FileRoot) { // fileRoot not found: return xmlrpcs_resperror(14, 'File root not found'); } $rf_filepath = $contentstruct['name']; logIO('Received filepath: ' . $rf_filepath); // Split into path + name: $filepath_parts = explode('/', $rf_filepath); $filename = array_pop($filepath_parts); logIO('Original file name: ' . $filename); // Validate and sanitize filename if ($error_filename = process_filename($filename, true)) { return xmlrpcs_resperror(5, $error_filename); } logIO('Sanitized file name: ' . $filename); // Check valid path parts: $rds_subpath = ''; foreach ($filepath_parts as $filepath_part) { if (empty($filepath_part) || $filepath_part == '.') { // self ref not useful continue; } if ($error = validate_dirname($filepath_part)) { // invalid relative path: logIO($error); return xmlrpcs_resperror(6, $error); } $rds_subpath .= $filepath_part . '/'; } logIO('Subpath: ' . $rds_subpath); // Create temporary file and insert contents into it. $tmpfile_name = tempnam(sys_get_temp_dir(), 'fmupload'); if ($tmpfile_name) { if (save_to_file($data, $tmpfile_name, 'wb')) { $image_info = @getimagesize($tmpfile_name); } else { return xmlrpcs_resperror(13, 'Error while writing to temp file.'); } } if (!empty($image_info)) { // This is an image file, let's check mimetype and correct extension if ($image_info['mime'] != $file_mimetype) { // Invalid file type $FiletypeCache =& get_FiletypeCache(); // Get correct file type based on mime type $correct_Filetype = $FiletypeCache->get_by_mimetype($image_info['mime'], false, false); $file_mimetype = $image_info['mime']; // Check if file type is known by us, and if it is allowed for upload. // If we don't know this file type or if it isn't allowed we don't change the extension! The current extension is allowed for sure. if ($correct_Filetype && $correct_Filetype->is_allowed()) { // A FileType with the given mime type exists in database and it is an allowed file type for current User // The "correct" extension is a plausible one, proceed... $correct_extension = array_shift($correct_Filetype->get_extensions()); $path_info = pathinfo($filename); $current_extension = $path_info['extension']; // change file extension to the correct extension, but only if the correct extension is not restricted, this is an extra security check! if (strtolower($current_extension) != strtolower($correct_extension) && !in_array($correct_extension, $force_upload_forbiddenext)) { // change the file extension to the correct extension $old_filename = $filename; $filename = $path_info['filename'] . '.' . $correct_extension; } } } } // Get File object for requested target location: $FileCache =& get_FileCache(); $newFile =& $FileCache->get_by_root_and_path($fm_FileRoot->type, $fm_FileRoot->in_type_ID, trailing_slash($rds_subpath) . $filename, true); if ($newFile->exists()) { if ($overwrite && $newFile->unlink()) { // OK, file deleted // Delete thumb caches from old location: logIO('Old file deleted'); $newFile->rm_cache(); } else { return xmlrpcs_resperror(8, sprintf(T_('The file «%s» already exists.'), $filename)); } } // Trigger plugin event if ($Plugins->trigger_event_first_false('AfterFileUpload', array('File' => &$newFile, 'name' => &$filename, 'type' => &$file_mimetype, 'tmp_name' => &$tmpfile_name, 'size' => &$filesize))) { // Plugin returned 'false'. // Abort upload for this file: @unlink($tmpfile_name); return xmlrpcs_resperror(16, 'File upload aborted by a plugin.'); } if (!mkdir_r($newFile->get_dir())) { // Dir didn't already exist and could not be created return xmlrpcs_resperror(9, 'Error creating sub directories: ' . $newFile->get_rdfs_rel_path()); } if (!@rename($tmpfile_name, $newFile->get_full_path())) { return xmlrpcs_resperror(13, 'Error while writing to file.'); } // chmod the file $newFile->chmod(); // Initializes file properties (type, size, perms...) $newFile->load_properties(); // Load meta data AND MAKE SURE IT IS CREATED IN DB: $newFile->meta == 'unknown'; $newFile->load_meta(true); // Resize and rotate logIO('Running file post-processing (resize and rotate)...'); prepare_uploaded_files(array($newFile)); logIO('Done'); $url = $newFile->get_url(); logIO('URL of new file: ' . $url); $struct = new xmlrpcval(array('file' => new xmlrpcval($filename, 'string'), 'url' => new xmlrpcval($url, 'string'), 'type' => new xmlrpcval($file_mimetype, 'string')), 'struct'); logIO('OK.'); return new xmlrpcresp($struct); }
/** * Check if the current request exceed the post max size limit. * If too much data was sent add an error message and call header redirect. */ function check_post_max_size_exceeded() { global $Messages; if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST) && empty($_FILES) && $_SERVER['CONTENT_LENGTH'] > 0) { // Check post max size ini setting $post_max_size = ini_get('post_max_size'); // Convert post_max_size value to bytes switch (substr($post_max_size, -1)) { case 'G': $post_max_size = $post_max_size * 1024; case 'M': $post_max_size = $post_max_size * 1024; case 'K': $post_max_size = $post_max_size * 1024; } // Add error message and redirect back to the referer url $Messages->add(sprintf(T_('You have sent too much data (too many large files?) for the server to process (%s sent / %s maximum). Please try again by sending less data/files at a time.'), bytesreadable($_SERVER['CONTENT_LENGTH']), bytesreadable($post_max_size))); header_redirect($_SERVER['HTTP_REFERER']); exit(0); // Already exited here } }
$message['text'] = T_('You don\'t have permission to upload on this file root.'); $message['status'] = 'error'; out_echo($message, $specialchars); exit; } if ($upload) { // Create the object and assign property if (isset($_GET['qqfile'])) { $file = new qqUploadedFileXhr(); } elseif (isset($_FILES['qqfile'])) { $file = new qqUploadedFileForm(); } else { $file = false; } if ($Settings->get('upload_maxkb') && $file->getSize() > $Settings->get('upload_maxkb') * 1024) { $message['text'] = sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($file->getSize()), bytesreadable($Settings->get('upload_maxkb') * 1024)); $message['status'] = 'error'; out_echo($message, $specialchars); exit; } if (empty($fm_FileRoot)) { // Stop when this object is NULL, it can happens when media path has no rights to write $message['text'] = sprintf(T_('We cannot open the folder %s. PHP needs execute permissions on this folder.'), '<b>' . $media_path . '</b>'); $message['status'] = 'error'; out_echo($message, $specialchars); exit; } $newName = $file->getName(); $oldName = $newName; // validate file name if ($error_filename = process_filename($newName, true, true, $fm_FileRoot, $path)) {
/** * Get size of the file/dir, formatted to nearest unit (kb, mb, etc.) * * @uses bytesreadable() * @param File * @return string size as b/kb/mb/gd; or '<dir>' */ function get_File_size_formatted($File) { if ($this->_use_recursive_dirsize || !$File->is_dir()) { return bytesreadable($File->get_recursive_size()); } return T_('<dir>'); }
// Check that the request doesn't exceed the post max size // This is required because another way not even the $ctrl param can be initialized and the request may freeze if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST) && empty($_FILES) && $_SERVER['CONTENT_LENGTH'] > 0) { // Check post max size ini setting $post_max_size = ini_get('post_max_size'); // Convert post_max_size value to bytes switch (substr($post_max_size, -1)) { case 'G': $post_max_size = $post_max_size * 1024; case 'M': $post_max_size = $post_max_size * 1024; case 'K': $post_max_size = $post_max_size * 1024; } // Add error message and redirect back to the referer url $Messages->add(sprintf(T_('You have sent too much data (too many large files?) for the server to process (%s sent / %s maximum). Please try again by sending less data/files at a time.'), bytesreadable($_SERVER['CONTENT_LENGTH']), bytesreadable($post_max_size))); header_redirect($_SERVER['HTTP_REFERER']); exit(0); } /* * Get the blog from param, defaulting to the last selected one for this user: * we need it for quite a few of the menu urls */ if (isset($collections_Module)) { $user_selected_blog = (int) $UserSettings->get('selected_blog'); $BlogCache =& get_BlogCache(); if (param('blog', 'integer', NULL, true) === NULL || $blog > 0 && !($Blog =& $BlogCache->get_by_ID($blog, false, false))) { // Try the memorized blog from the previous action: $blog = $user_selected_blog; if (!($Blog =& $BlogCache->get_by_ID($blog, false, false))) { // That one doesn't exist either...
/** * Get size of the file, formatted to nearest unit (kb, mb, etc.) * * @uses bytesreadable() * @return string size as b/kb/mb/gd; or '<dir>' */ function get_size_formatted() { if ($this->is_dir()) { return T_('<dir>'); } else { return bytesreadable($this->get_size()); } }
<p class="note"> <?php $restrictNotes = array(); // Get list of recognized file types (others are not allowed to get uploaded) // dh> because FiletypeCache/DataObjectCache has no interface for getting a list, this dirty query seems less dirty to me. $allowed_extensions = $DB->get_col('SELECT ftyp_extensions FROM T_filetypes WHERE ftyp_allowed != 0'); $allowed_extensions = implode(' ', $allowed_extensions); // implode with space, ftyp_extensions can hold many, separated by space // into array: $allowed_extensions = preg_split('~\\s+~', $allowed_extensions, -1, PREG_SPLIT_NO_EMPTY); // readable: $allowed_extensions = implode_with_and($allowed_extensions); $restrictNotes[] = '<strong>' . T_('Allowed file extensions') . '</strong>: ' . $allowed_extensions; if ($Settings->get('upload_maxkb')) { // We want to restrict on file size: $restrictNotes[] = '<strong>' . T_('Maximum allowed file size') . '</strong>: ' . bytesreadable($Settings->get('upload_maxkb') * 1024); } echo implode('<br />', $restrictNotes) . '<br />'; ?> </p> </div> </td> </tr> </tbody> </table> <?php $Widget->disp_template_raw('block_end'); $Form->end_form(); // End payload block:
/** * Outputs debug info, according to {@link $debug} or $force param. This gets called typically at the end of the page. * * @todo dh> add get_debug_info() which returns and supports non-html format (for debug_die()) * @param boolean true to force output regardless of {@link $debug} */ function debug_info($force = false) { global $debug, $Debuglog, $DB, $obhandler_debug, $Timer, $ReqHost, $ReqPath; global $cache_imgsize, $cache_File; global $Session; global $db_config, $tableprefix; if (!$debug && !$force) { // No debug output: return; } $ReqHostPathQuery = $ReqHost . $ReqPath . (empty($_SERVER['QUERY_STRING']) ? '' : '?' . $_SERVER['QUERY_STRING']); echo '<div class="debug"><h2>Debug info</h2>'; $Debuglog->add('Len of serialized $cache_imgsize: ' . strlen(serialize($cache_imgsize)), 'memory'); $Debuglog->add('Len of serialized $cache_File: ' . strlen(serialize($cache_File)), 'memory'); if (!$obhandler_debug) { // don't display changing items when we want to test obhandler // Timer table: $time_page = $Timer->get_duration('total'); $timer_rows = array(); foreach ($Timer->get_categories() as $l_cat) { if ($l_cat == 'sql_query') { continue; } $timer_rows[$l_cat] = $Timer->get_duration($l_cat); } // arsort( $timer_rows ); ksort($timer_rows); echo '<table><thead>' . '<tr><th colspan="4" class="center">Timers</th></tr>' . '<tr><th>Category</th><th>Time</th><th>%</th><th>Count</th></tr>' . '</thead><tbody>'; $table_rows_ignore_perhaps = array(); foreach ($timer_rows as $l_cat => $l_time) { $percent_l_cat = $time_page > 0 ? number_format(100 / $time_page * $l_time, 2) : '0'; $row = "\n<tr>" . '<td>' . $l_cat . '</td>' . '<td class="right">' . $l_time . '</td>' . '<td class="right">' . $percent_l_cat . '%</td>' . '<td class="right">' . $Timer->get_count($l_cat) . '</td></tr>'; if ($l_time < 0.005) { $table_rows_ignore_perhaps[] = $row; } else { echo $row; } } $count_ignored = count($table_rows_ignore_perhaps); if ($count_ignored > 5) { echo '<tr><td colspan="4" class="center"> + ' . $count_ignored . ' < 0.005s </td></tr>'; } else { echo implode("\n", $table_rows_ignore_perhaps); } echo '</tbody>'; echo '</table>'; if (isset($DB)) { echo '<a href="' . $ReqHostPathQuery . '#evo_debug_queries">Database queries: ' . $DB->num_queries . '.</a><br />'; } foreach (array('memory_get_usage' => array('display' => 'Memory usage', 'high' => 8000000), 'memory_get_peak_usage' => array('display' => 'Memory peak usage', 'high' => 8000000)) as $l_func => $l_var) { if (function_exists($l_func)) { $_usage = $l_func(); if ($_usage > $l_var['high']) { echo '<span style="color:red; font-weight:bold">'; } echo $l_var['display'] . ': ' . bytesreadable($_usage); if ($_usage > $l_var['high']) { echo '</span>'; } echo '<br />'; } } } // DEBUGLOG(s) FROM PREVIOUS SESSIONS, after REDIRECT(s) (with list of categories at top): if (isset($Session) && ($sess_Debuglogs = $Session->get('Debuglogs')) && !empty($sess_Debuglogs)) { $count_sess_Debuglogs = count($sess_Debuglogs); if ($count_sess_Debuglogs > 1) { // Links to those Debuglogs: echo '<p>There are ' . $count_sess_Debuglogs . ' Debuglogs from redirected pages: '; for ($i = 1; $i <= $count_sess_Debuglogs; $i++) { echo '<a href="' . $ReqHostPathQuery . '#debug_sess_debuglog_' . $i . '">#' . $i . '</a> '; } echo '</p>'; } foreach ($sess_Debuglogs as $k => $sess_Debuglog) { $log_categories = array('error', 'note', 'all'); // Categories to output (in that order) $log_cats = array_keys($sess_Debuglog->get_messages($log_categories)); // the real list (with all replaced and only existing ones) $log_container_head = '<h3 id="debug_sess_debuglog_' . ($k + 1) . '" style="color:#f00;">Debug messages from redirected page (#' . ($k + 1) . ')</h3>' . '<p><a href="' . $ReqHostPathQuery . '#debug_debuglog">See below for the Debuglog from the current request.</a></p>'; $log_head_links = array(); foreach ($log_cats as $l_cat) { $log_head_links[] .= '<a href="' . $ReqHostPathQuery . '#debug_redir_' . ($k + 1) . '_info_cat_' . str_replace(' ', '_', $l_cat) . '">' . $l_cat . '</a>'; } $log_container_head .= implode(' | ', $log_head_links); echo format_to_output($sess_Debuglog->display(array('container' => array('string' => $log_container_head, 'template' => false), 'all' => array('string' => '<h4 id="debug_redir_' . ($k + 1) . '_info_cat_%s">%s:</h4>', 'template' => false)), '', false, $log_categories), 'htmlbody'); } $Session->delete('Debuglogs'); } // CURRENT DEBUGLOG (with list of categories at top): $log_categories = array('error', 'note', 'all'); // Categories to output (in that order) $log_cats = array_keys($Debuglog->get_messages($log_categories)); // the real list (with all replaced and only existing ones) $log_container_head = '<h3 id="debug_debuglog">Debug messages</h3>'; if (!empty($sess_Debuglogs)) { // link to first sess_Debuglog: $log_container_head .= '<p><a href="' . $ReqHostPathQuery . '#debug_sess_debuglog_1">See above for the Debuglog(s) from before the redirect.</a></p>'; } $log_head_links = array(); foreach ($log_cats as $l_cat) { $log_head_links[] .= '<a href="' . $ReqHostPathQuery . '#debug_info_cat_' . str_replace(' ', '_', $l_cat) . '">' . $l_cat . '</a>'; } $log_container_head .= implode(' | ', $log_head_links); echo format_to_output($Debuglog->display(array('container' => array('string' => $log_container_head, 'template' => false), 'all' => array('string' => '<h4 id="debug_info_cat_%s">%s:</h4>', 'template' => false)), '', false, $log_categories), 'htmlbody'); echo '<h3 id="evo_debug_queries">DB</h3>'; if ($db_config) { echo '<pre>', T_('DB Username') . ': ' . $db_config['user'] . "\n" . T_('DB Database') . ': ' . $db_config['name'] . "\n" . T_('DB Host') . ': ' . $db_config['host'] . "\n" . T_('DB tables prefix') . ': ' . $tableprefix . "\n" . T_('DB connection charset') . ': ' . $db_config['connection_charset'] . "\n" . '</pre>'; } if (!isset($DB)) { echo 'No DB object.'; } else { $DB->dump_queries(); } echo '</div>'; }
$block_item_Widget->disp_template_raw('block_end'); /* * Caching */ $block_item_Widget->title = T_('Caching'); $block_item_Widget->disp_template_replaced('block_start'); // Cache folder writable? list($cachedir_status, $cachedir_msg) = system_get_result($system_stats['cachedir_status']); $cachedir_long = ''; if ($cachedir_status == 'error') { $cachedir_long = '<p>' . T_('You will not be able to use page cache.') . "</p>\n" . '<p>' . T_('Your host requires that you set special file permissions on your cache directory.') . get_manual_link('cache_file_permission_errors') . "</p>\n"; } init_system_check(T_('Cache directory'), $cachedir_msg . ' - ' . $cache_path); disp_system_check($cachedir_status, $cachedir_long); // cache folder size init_system_check('Cache folder size', bytesreadable($system_stats['cachedir_size'])); disp_system_check('note'); if ($cachedir_status != 'error') { // 'cache/ directory exists and, it is writable // General cache is enabled init_system_check(T_('General caching'), $system_stats['general_pagecache_enabled'] ? 'Enabled' : 'Disabled'); disp_system_check('note'); // how many blogs have enabled caches $error_messages = system_check_caches(false); $enabled_message = $system_stats['blog_pagecaches_enabled'] . ' enabled /' . $system_stats['evo_blog_count'] . ' blogs'; init_system_check(T_('Blog\'s cache setting'), $enabled_message); disp_system_check('note'); if (count($error_messages) > 0) { // show errors init_system_check(T_('Blog\'s cache errors'), implode('<br />', $error_messages)); disp_system_check('error');
/** * Get size of the file, formatted to nearest unit (kb, mb, etc.) * * @uses bytesreadable() * @return string size as b/kb/mb/gd; or '<dir>' */ function get_size_formatted() { if ($this->_size === NULL) { return T_('<dir>'); } else { return bytesreadable($this->_size); } }
/** * Outputs debug info, according to {@link $debug} or $force param. This gets called typically at the end of the page. * * @param boolean true to force output regardless of {@link $debug} * @param boolean true to force clean output (without HTML) regardless of {@link $is_cli} */ function debug_info($force = false, $force_clean = false) { global $debug, $debug_done, $debug_jslog, $debug_jslog_done, $Debuglog, $DB, $obhandler_debug, $Timer, $ReqHost, $ReqPath, $is_cli; global $cache_imgsize, $cache_File; global $Session; global $db_config, $tableprefix, $http_response_code, $disp, $disp_detail, $robots_index, $robots_follow, $content_type_header; /** * @var Hit */ global $Hit; // Detect content-type $content_type = NULL; foreach (headers_list() as $header) { if (stripos($header, 'content-type:') !== false) { // content type sent # "Content-Type:text/html;charset=utf-8" => "text/html" $content_type = trim(array_shift(explode(';', array_pop(explode(':', $header, 2))))); break; } } // ---- Print AJAX Log if (empty($debug_jslog_done) && ($debug || $debug_jslog) && $content_type == 'text/html') { // Display debug jslog once global $rsc_url, $app_version; echo '<script type="text/javascript" src="' . $rsc_url . 'js/debug_jslog.js"></script>'; echo '<script type="text/javascript" src="' . $rsc_url . 'js/jquery/jquery.cookie.min.js"></script>'; $jquery_ui_css_url = url_add_param($rsc_url . 'css/jquery/smoothness/jquery-ui.css', 'v=' . $app_version); echo '<link href="' . $jquery_ui_css_url . '" type="text/css" rel="stylesheet" />'; $jslog_style_cookies = param_cookie('jslog_style', 'string'); $jslog_styles = array(); if (!empty($jslog_style_cookies)) { // Get styles only from cookies $jslog_style_cookies = explode(';', $jslog_style_cookies); foreach ($jslog_style_cookies as $jsc => $style) { if (strpos($style, 'height') !== false) { // Unset the height param from defined styles ( and the display param if jslog is disabled ) unset($jslog_style_cookies[$jsc]); } } $jslog_styles[] = implode(';', $jslog_style_cookies); } else { if (!is_logged_in()) { // Align top when evobar is hidden $jslog_styles[] = 'top:0'; } if ($debug_jslog) { // Display the jslog $jslog_styles[] = 'display:block'; } } $jslog_styles = count($jslog_styles) > 0 ? ' style="' . implode(';', $jslog_styles) . '"' : ''; $close_url = url_add_param($_SERVER['REQUEST_URI'], 'jslog'); echo '<div id="debug_ajax_info" class="debug"' . $jslog_styles . '>'; echo '<div class="jslog_titlebar">AJAX Debug log' . get_manual_link('ajax_debug_log') . action_icon(T_('Close'), 'close', $close_url, NULL, NULL, NULL, array('class' => 'jslog_switcher')) . '</div>'; echo '<div id="jslog_container"></div>'; echo '<div class="jslog_statusbar">' . '<a href="' . $_SERVER['REQUEST_URI'] . '#" class="jslog_clear">' . T_('Clear') . '</a>' . '</div>'; echo '</div>'; // Make sure debug jslog output only happens once: $debug_jslog_done = true; } // ---- if (!$force) { if (!empty($debug_done)) { // Already displayed! return; } if (empty($debug)) { // No debug output desired: return; } // Do not display, if no content-type header has been sent or it's != "text/html" (debug > 1 skips this) if ($debug < 2) { if ($content_type != 'text/html') { return; } } } //Make sure debug output only happens once: $debug_done = true; // clean output: $clean = $is_cli || $force_clean; $printf_format = '| %-45s | %-5s | %-7s | %-5s |'; $table_headerlen = 73; /* This calculates the number of dashes to print e. g. on the top and * bottom of the table and after the header, making the table look * better (looks like the tables of the mysql command line client). * Normally, the value won't change, so it's hardcoded above. If you * change the printf() format above, this might be useful. preg_match_all( '#\d+#', $printf_format, $table_headerlen ); $table_headerlen = array_sum( $table_headerlen[0] ) + strlen( preg_replace( '#[^ \|]+#', '', $printf_format ) ) - 2; */ $ReqHostPathQuery = $ReqHost . $ReqPath . (empty($_SERVER['QUERY_STRING']) ? '' : '?' . $_SERVER['QUERY_STRING']); echo "\n\n\n"; echo $clean ? '*** Debug info ***' . "\n\n" : '<div class="debug" id="debug_info"><h2>Debug info</h2>'; if (!$obhandler_debug) { // don't display changing items when we want to test obhandler // --------------------------- echo '<div class="log_container"><div>'; echo 'HTTP Response code: ' . $http_response_code; echo $clean ? "\n" : '<br />'; echo '$content_type_header: ' . $content_type_header; echo $clean ? "\n" : '<br />'; echo '$disp: ' . $disp . ' -- detail: ' . $disp_detail; echo $clean ? "\n" : '<br />'; echo '$robots_index: ' . $robots_index; echo $clean ? "\n" : '<br />'; echo '$robots_follow: ' . $robots_follow; echo $clean ? "\n" : '<br />'; echo '</div></div>'; // ================================== DB Summary ================================ if (isset($DB)) { echo '<div class="log_container"><div>'; echo $DB->num_queries . ' SQL queries executed in ' . $Timer->get_duration('SQL QUERIES') . " seconds\n"; if (!$clean) { echo ' <a href="' . $ReqHostPathQuery . '#evo_debug_queries">scroll down to details</a><p>'; } echo '</div></div>'; } // ========================== Timer table ================================ $time_page = $Timer->get_duration('total'); $timer_rows = array(); foreach ($Timer->get_categories() as $l_cat) { if ($l_cat == 'sql_query') { continue; } $timer_rows[$l_cat] = $Timer->get_duration($l_cat); } // Don't sort to see orginal order of creation // arsort( $timer_rows ); // ksort( $timer_rows ); // Remove "total", it will get output as the last one: $total_time = $timer_rows['total']; unset($timer_rows['total']); $percent_total = $time_page > 0 ? number_format(100 / $time_page * $total_time, 2) : '0'; if ($clean) { echo '== Timers ==' . "\n\n"; echo '+' . str_repeat('-', $table_headerlen) . '+' . "\n"; printf($printf_format . "\n", 'Category', 'Time', '%', 'Count'); echo '+' . str_repeat('-', $table_headerlen) . '+' . "\n"; } else { echo '<table class="debug_timer"><thead>' . '<tr><td colspan="4" class="center">Timers</td></tr>' . '<tr><th>Category</th><th>Time</th><th>%</th><th>Count</th></tr>' . '</thead>'; // Output "total": echo "\n<tfoot><tr>" . '<td>total</td>' . '<td class="right red">' . $total_time . '</td>' . '<td class="right">' . $percent_total . '%</td>' . '<td class="right">' . $Timer->get_count('total') . '</td></tr></tfoot>'; echo '<tbody>'; } $table_rows_collapse = array(); foreach ($timer_rows as $l_cat => $l_time) { $percent_l_cat = $time_page > 0 ? number_format(100 / $time_page * $l_time, 2) : '0'; if ($clean) { $row = sprintf($printf_format, $l_cat, $l_time, $percent_l_cat . '%', $Timer->get_count($l_cat)); } else { $row = "\n<tr>" . '<td>' . $l_cat . '</td>' . '<td class="right">' . $l_time . '</td>' . '<td class="right">' . $percent_l_cat . '%</td>' . '<td class="right">' . $Timer->get_count($l_cat) . '</td></tr>'; } // Maybe ignore this row later, but not for clean display. if (!$clean && $percent_l_cat < 1) { // Hide everything that tool less tahn 5% of the time $table_rows_collapse[] = $row; } else { echo $row . "\n"; } } $count_collapse = count($table_rows_collapse); // Collapse ignored rows, allowing to expand them with Javascript: if ($count_collapse > 5) { echo '<tr><td colspan="4" class="center" id="evo-debuglog-timer-long-header">'; echo '<a href="" onclick="var e = document.getElementById(\'evo-debuglog-timer-long\'); e.style.display = (e.style.display == \'none\' ? \'\' : \'none\'); return false;">+ ' . $count_collapse . ' queries < 1%</a> </td></tr>'; echo '</tbody>'; echo '<tbody id="evo-debuglog-timer-long" style="display:none;">'; } echo implode("\n", $table_rows_collapse) . "\n"; if ($clean) { // "total" (done in tfoot for html above) echo sprintf($printf_format, 'total', $total_time, $percent_total . '%', $Timer->get_count('total')); echo '+' . str_repeat('-', $table_headerlen) . '+' . "\n\n"; } else { echo "\n</tbody></table>"; // add jquery.tablesorter to the "Debug info" table. global $rsc_uri; echo ' <script type="text/javascript" src="' . $rsc_uri . 'js/jquery/jquery.tablesorter.min.js"></script> <script type="text/javascript"> (function($){ var clicked_once; jQuery("table.debug_timer th").click( function(event) { if( clicked_once ) return; else clicked_once = true; jQuery("#evo-debuglog-timer-long tr").appendTo(jQuery("table.debug_timer tbody")[0]); jQuery("#evo-debuglog-timer-long-header").remove(); // click for tablesorter: jQuery("table.debug_timer").tablesorter(); jQuery(event.currentTarget).click(); }); })(jQuery); </script>'; } // ================================ Opcode caching ================================ echo '<div class="log_container"><div>'; echo 'Opcode cache: ' . get_active_opcode_cache(); echo $clean ? "\n" : '<p>'; echo '</div></div>'; // ================================ Memory Usage ================================ echo '<div class="log_container"><div>'; foreach (array('memory_get_usage' => array('display' => 'Memory usage', 'high' => 8000000), 'memory_get_peak_usage' => array('display' => 'Memory peak usage', 'high' => 8000000)) as $l_func => $l_var) { if (function_exists($l_func)) { $_usage = $l_func(); if ($_usage > $l_var['high']) { echo $clean ? '[!!] ' : '<span style="color:red; font-weight:bold">'; } echo $l_var['display'] . ': ' . bytesreadable($_usage, !$clean); if (!$clean && $_usage > $l_var['high']) { echo '</span>'; } echo $clean ? "\n" : '<br />'; } } echo 'Len of serialized $cache_imgsize: ' . strlen(serialize($cache_imgsize)); echo $clean ? "\n" : '<br />'; echo 'Len of serialized $cache_File: ' . strlen(serialize($cache_File)); echo $clean ? "\n" : '<br />'; echo '</div></div>'; } // DEBUGLOG(s) FROM PREVIOUS SESSIONS, after REDIRECT(s) (with list of categories at top): if (isset($Session) && ($sess_Debuglogs = $Session->get('Debuglogs')) && !empty($sess_Debuglogs)) { $count_sess_Debuglogs = count($sess_Debuglogs); if ($count_sess_Debuglogs > 1) { // Links to those Debuglogs: if ($clean) { // kind of useless, but anyway... echo "\n" . 'There are ' . $count_sess_Debuglogs . ' Debuglogs from redirected pages.' . "\n"; } else { echo '<p>There are ' . $count_sess_Debuglogs . ' Debuglogs from redirected pages: '; for ($i = 1; $i <= $count_sess_Debuglogs; $i++) { echo '<a href="' . $ReqHostPathQuery . '#debug_sess_debuglog_' . $i . '">#' . $i . '</a> '; } echo '</p>'; } } foreach ($sess_Debuglogs as $k => $sess_Debuglog) { $log_categories = array('error', 'note', 'all'); // Categories to output (in that order) if ($clean) { $log_container_head = "\n" . '== Debug messages from redirected page (#' . ($k + 1) . ') ==' . "\n" . 'See below for the Debuglog from the current request.' . "\n"; echo format_to_output($sess_Debuglog->display(array('container' => array('string' => $log_container_head, 'template' => false), 'all' => array('string' => '= %s =' . "\n\n", 'template' => false)), '', false, $log_categories, '', 'raw', false), 'raw'); } else { $log_container_head = '<h3 id="debug_sess_debuglog_' . ($k + 1) . '" style="color:#f00;">Debug messages from redirected page (#' . ($k + 1) . ')</h3>' . '<p><a href="' . $ReqHostPathQuery . '#debug_debuglog">See below for the Debuglog from the current request.</a></p>'; $log_cats = array_keys($sess_Debuglog->get_messages($log_categories)); // the real list (with all replaced and only existing ones) $log_head_links = array(); foreach ($log_cats as $l_cat) { $log_head_links[] .= '<a href="' . $ReqHostPathQuery . '#debug_redir_' . ($k + 1) . '_info_cat_' . str_replace(' ', '_', $l_cat) . '">' . $l_cat . '</a>'; } $log_container_head .= implode(' | ', $log_head_links); echo format_to_output($sess_Debuglog->display(array('container' => array('string' => $log_container_head, 'template' => false), 'all' => array('string' => '<h4 id="debug_redir_' . ($k + 1) . '_info_cat_%s">%s:</h4>', 'template' => false)), '', false, $log_categories), 'htmlbody'); } } // Delete logs since they have been displayed... // EXCEPT if we are redirecting, because in this case we won't see these logs in a browser (only in request debug tools) // So in that case we want them to move over to the next page... if ($http_response_code < 300 || $http_response_code >= 400) { // This is NOT a 3xx redirect, assume debuglogs have been seen & delete them: $Session->delete('Debuglogs'); } } // CURRENT DEBUGLOG (with list of categories at top): $log_categories = array('error', 'note', 'all'); // Categories to output (in that order) $log_container_head = $clean ? "\n" . '== Debug messages ==' . "\n" : '<h3 id="debug_debuglog">Debug messages</h3>'; if (!empty($sess_Debuglogs)) { // link to first sess_Debuglog: if ($clean) { $log_container_head .= 'See above for the Debuglog(s) from before the redirect.' . "\n"; } else { $log_container_head .= '<p><a href="' . $ReqHostPathQuery . '#debug_sess_debuglog_1">See above for the Debuglog(s) from before the redirect.</a></p>'; } } if (!$clean) { $log_cats = array_keys($Debuglog->get_messages($log_categories)); // the real list (with all replaced and only existing ones) $log_head_links = array(); foreach ($log_cats as $l_cat) { $log_head_links[] .= '<a href="' . $ReqHostPathQuery . '#debug_info_cat_' . str_replace(' ', '_', $l_cat) . '">' . $l_cat . '</a>'; } $log_container_head .= implode(' | ', $log_head_links); echo format_to_output($Debuglog->display(array('container' => array('string' => $log_container_head, 'template' => false), 'all' => array('string' => '<h4 id="debug_info_cat_%s">%s:</h4>', 'template' => false)), '', false, $log_categories), 'htmlbody'); echo '<h3 id="evo_debug_queries">DB</h3>'; } else { echo format_to_output($Debuglog->display(array('container' => array('string' => $log_container_head, 'template' => false), 'all' => array('string' => '= %s =' . "\n\n", 'template' => false)), '', false, $log_categories, '', 'raw', false), 'raw'); echo "\n" . '== DB ==' . "\n\n"; } if ($db_config) { if (!$clean) { echo '<pre>'; } echo 'Config DB Username: '******'user'] . "\n" . 'Config DB Database: ' . $db_config['name'] . "\n" . 'Config DB Host: ' . (isset($db_config['host']) ? $db_config['host'] : 'unset (localhost)') . "\n" . 'Config DB tables prefix: ' . $tableprefix . "\n" . 'Config DB connection charset: ' . $db_config['connection_charset'] . "\n"; echo $clean ? "\n" : '</pre>'; } if (!isset($DB)) { echo 'No DB object.' . ($clean ? "\n" : ''); } else { echo '<pre>Current DB charset: ' . $DB->connection_charset . "</pre>\n"; $DB->dump_queries(!$clean); } if (!$clean) { echo '</div>'; } }
?> </a> </span> <?php // Display number of directories/files: ?> <div id="fmbar_filecounts" title="<?php printf(T_('%s bytes'), number_format($fm_Filelist->count_bytes())); ?> "> (<?php disp_cond($fm_Filelist->count_dirs(), T_('One directory'), T_('%d directories'), T_('No directories')); echo ', '; disp_cond($fm_Filelist->count_files(), T_('One file'), T_('%d files'), T_('No files')); echo ', ' . bytesreadable($fm_Filelist->count_bytes()); ?> ) </div> </td> </tr> </thead> <tbody> <tr> <?php // ______________________________ Directory tree ______________________________ if (!$fm_hide_dirtree) { echo '<td id="fm_dirtree">'; // Version with all roots displayed
if ($upload && !$current_User->check_perm('files', 'add', false, $fm_FileRoot)) { $message['text'] = '<span class="result_error">' . T_('You don\'t have permission to upload on this file root.') . '</span>'; out_echo($message, $specialchars); exit; } if ($upload) { // Create the object and assign property if (isset($_GET['qqfile'])) { $file = new qqUploadedFileXhr(); } elseif (isset($_FILES['qqfile'])) { $file = new qqUploadedFileForm(); } else { $file = false; } if ($Settings->get('upload_maxkb') && $file->getSize() > $Settings->get('upload_maxkb') * 1024) { $message['text'] = '<span class="result_error">' . sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($file->getSize()), bytesreadable($Settings->get('upload_maxkb') * 1024)) . '</span>'; out_echo($message, $specialchars); exit; } $newName = $file->getName(); $oldName = $newName; // validate file name if ($error_filename = process_filename($newName)) { // Not a file name or not an allowed extension $message['text'] = '<span class="result_error"> ' . $error_filename . '</span>'; out_echo($message, $specialchars); exit; } list($newFile, $oldFile_thumb) = check_file_exists($fm_FileRoot, $path, $newName); $newName = $newFile->get('name'); // If everything is ok, save the file somewhere
param('uploadfile_desc', 'array', array()); param('uploadfile_name', 'array', array()); foreach ($_FILES['uploadfile']['name'] as $lKey => $lName) { if (empty($lName)) { // No file name if ($upload_quickmode || !empty($uploadfile_title[$lKey]) || !empty($uploadfile_alt[$lKey]) || !empty($uploadfile_desc[$lKey]) || !empty($uploadfile_name[$lKey])) { // User specified params but NO file!!! // Remember the file as failed when additional info provided. $failedFiles[$lKey] = T_('Please select a local file to upload.'); } // Abort upload for this file: continue; } if ($Settings->get('upload_maxkb') && $_FILES['uploadfile']['size'][$lKey] > $Settings->get('upload_maxkb') * 1024) { // bigger than defined by blog $failedFiles[$lKey] = sprintf(T_('The file is too large: %s but the maximum allowed is %s.'), bytesreadable($_FILES['uploadfile']['size'][$lKey]), bytesreadable($Settings->get('upload_maxkb') * 1024)); // Abort upload for this file: continue; } if ($_FILES['uploadfile']['error'][$lKey]) { // PHP has detected an error!: switch ($_FILES['uploadfile']['error'][$lKey]) { case UPLOAD_ERR_FORM_SIZE: // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form. // This can easily be changed, so we do not use it.. file size gets checked for real just above. break; case UPLOAD_ERR_INI_SIZE: // bigger than allowed in php.ini $failedFiles[$lKey] = T_('The file exceeds the upload_max_filesize directive in php.ini.'); // Abort upload for this file: continue;