/** * Output the stored data * * If outputted in an aggregation we collect the images into a gallery. * * @param string|int $value the value stored in the database * @param \Doku_Renderer $R the renderer currently used to render the data * @param string $mode The mode the output is rendered in (eg. XHTML) * @return bool true if $mode could be satisfied */ public function renderValue($value, \Doku_Renderer $R, $mode) { // get width and height from config $width = null; $height = null; if ($this->config['width']) { $width = $this->config['width']; } if ($this->config['height']) { $height = $this->config['height']; } if (!empty($R->info['struct_table_hash'])) { // this is an aggregation, check for special values if ($this->config['agg_width']) { $width = $this->config['agg_width']; } if ($this->config['agg_height']) { $height = $this->config['agg_height']; } } // depending on renderer type directly output or get value from it $returnLink = null; $html = ''; if (!media_isexternal($value)) { if (is_a($R, '\\Doku_Renderer_xhtml')) { /** @var \Doku_Renderer_xhtml $R */ $html = $R->internalmedia($value, null, null, $width, $height, null, 'direct', true); } else { $R->internalmedia($value, null, null, $width, $height, null, 'direct'); } } else { if (is_a($R, '\\Doku_Renderer_xhtml')) { /** @var \Doku_Renderer_xhtml $R */ $html = $R->externalmedia($value, null, null, $width, $height, null, 'direct', true); } else { $R->externalmedia($value, null, null, $width, $height, null, 'direct'); } } // add gallery meta data in XHTML if ($mode == 'xhtml') { list(, $mime, ) = mimetype($value, false); if (substr($mime, 0, 6) == 'image/') { $hash = !empty($R->info['struct_table_hash']) ? "[gal-" . $R->info['struct_table_hash'] . "]" : ''; $html = str_replace('href', "rel=\"lightbox{$hash}\" href", $html); } $R->doc .= $html; } return true; }
/** * _getLastMediaRevisionAt is a helperfunction to internalmedia() and _media() * which returns an existing media revision less or equal to rev or date_at * * @author lisps * @param string $media_id * @access protected * @return string revision ('' for current) */ function _getLastMediaRevisionAt($media_id) { if (!$this->date_at || media_isexternal($media_id)) { return ''; } $pagelog = new MediaChangeLog($media_id); return $pagelog->getLastRevisionAt($this->date_at); }
/** * Override the mpdf _getImage function * * This function takes care of gathering the image data from HTTP or * local files before passing the data back to mpdf's original function * making sure that only cached file paths are passed to mpdf. It also * takes care of checking image ACls. */ function _getImage(&$file, $firsttime = true, $allowvector = true, $orig_srcpath = false) { global $conf; // build regex to parse URL back to media info $re = preg_quote(ml('xxx123yyy', '', true, '&', true), '/'); $re = str_replace('xxx123yyy', '([^&\\?]*)', $re); // extract the real media from a fetch.php uri and determine mime if (preg_match("/^{$re}/", $file, $m) || preg_match('/[&\\?]media=([^&\\?]*)/', $file, $m)) { $media = rawurldecode($m[1]); list($ext, $mime) = mimetype($media); } else { list($ext, $mime) = mimetype($file); } // local files $local = ''; if (substr($file, 0, 9) == 'dw2pdf://') { // support local files passed from plugins $local = substr($file, 9); } elseif (!preg_match('/(\\.php|\\?)/', $file)) { $re = preg_quote(DOKU_URL, '/'); // directly access local files instead of using HTTP, skip dynamic content $local = preg_replace("/^{$re}/i", DOKU_INC, $file); } if (substr($mime, 0, 6) == 'image/') { if (!empty($media)) { // any size restrictions? $w = $h = 0; if (preg_match('/[\\?&]w=(\\d+)/', $file, $m)) { $w = $m[1]; } if (preg_match('/[\\?&]h=(\\d+)/', $file, $m)) { $h = $m[1]; } if (media_isexternal($media)) { $local = media_get_from_URL($media, $ext, -1); if (!$local) { $local = $media; } // let mpdf try again } else { $media = cleanID($media); //check permissions (namespace only) if (auth_quickaclcheck(getNS($media) . ':X') < AUTH_READ) { $file = ''; } $local = mediaFN($media); } //handle image resizing/cropping if ($w && file_exists($local)) { if ($h) { $local = media_crop_image($local, $ext, $w, $h); } else { $local = media_resize_image($local, $ext, $w, $h); } } } elseif (media_isexternal($file)) { // fixed external URLs $local = media_get_from_URL($file, $ext, $conf['cachetime']); } if ($local) { $file = $local; $orig_srcpath = $local; } } return parent::_getImage($file, $firsttime, $allowvector, $orig_srcpath); }
public function test_internal() { $this->assertFalse(media_isexternal('wiki:logo.png')); $this->assertFalse(media_isexternal('private:logo.png')); $this->assertFalse(media_isexternal('ftp:private:logo.png')); }
/** * Build a link to a media file * * Will return a link to the detail page if $direct is false * * The $more parameter should always be given as array, the function then * will strip default parameters to produce even cleaner URLs * * @param string $id the media file id or URL * @param mixed $more string or array with additional parameters * @param bool $direct link to detail page if false * @param string $sep URL parameter separator * @param bool $abs Create an absolute URL * @return string */ function ml($id = '', $more = '', $direct = true, $sep = '&', $abs = false) { global $conf; $isexternalimage = media_isexternal($id); if (!$isexternalimage) { $id = cleanID($id); } if (is_array($more)) { // add token for resized images if (!empty($more['w']) || !empty($more['h']) || $isexternalimage) { $more['tok'] = media_get_token($id, $more['w'], $more['h']); } // strip defaults for shorter URLs if (isset($more['cache']) && $more['cache'] == 'cache') { unset($more['cache']); } if (empty($more['w'])) { unset($more['w']); } if (empty($more['h'])) { unset($more['h']); } if (isset($more['id']) && $direct) { unset($more['id']); } if (isset($more['rev']) && !$more['rev']) { unset($more['rev']); } $more = buildURLparams($more, $sep); } else { $matches = array(); if (preg_match_all('/\\b(w|h)=(\\d*)\\b/', $more, $matches, PREG_SET_ORDER) || $isexternalimage) { $resize = array('w' => 0, 'h' => 0); foreach ($matches as $match) { $resize[$match[1]] = $match[2]; } $more .= $more === '' ? '' : $sep; $more .= 'tok=' . media_get_token($id, $resize['w'], $resize['h']); } $more = str_replace('cache=cache', '', $more); //skip default $more = str_replace(',,', ',', $more); $more = str_replace(',', $sep, $more); } if ($abs) { $xlink = DOKU_URL; } else { $xlink = DOKU_BASE; } // external URLs are always direct without rewriting if ($isexternalimage) { $xlink .= 'lib/exe/fetch.php'; $xlink .= '?' . $more; $xlink .= $sep . 'media=' . rawurlencode($id); return $xlink; } $id = idfilter($id); // decide on scriptname if ($direct) { if ($conf['userewrite'] == 1) { $script = '_media'; } else { $script = 'lib/exe/fetch.php'; } } else { if ($conf['userewrite'] == 1) { $script = '_detail'; } else { $script = 'lib/exe/detail.php'; } } // build URL based on rewrite mode if ($conf['userewrite']) { $xlink .= $script . '/' . $id; if ($more) { $xlink .= '?' . $more; } } else { if ($more) { $xlink .= $script . '?' . $more; $xlink .= $sep . 'media=' . $id; } else { $xlink .= $script . '?media=' . $id; } } return $xlink; }
/** * Check for media for preconditions and return correct status code * * READ: MEDIA, MIME, EXT, CACHE * WRITE: MEDIA, FILE, array( STATUS, STATUSMESSAGE ) * * @author Gerry Weissbach <*****@*****.**> * * @param string $media reference to the media id * @param string $file reference to the file variable * @param string $rev * @param int $width * @param int $height * @return array as array(STATUS, STATUSMESSAGE) */ function checkFileStatus(&$media, &$file, $rev = '', $width = 0, $height = 0) { global $MIME, $EXT, $CACHE, $INPUT; //media to local file if (media_isexternal($media)) { //check token for external image and additional for resized and cached images if (media_get_token($media, $width, $height) !== $INPUT->str('tok')) { return array(412, 'Precondition Failed'); } //handle external images if (strncmp($MIME, 'image/', 6) == 0) { $file = media_get_from_URL($media, $EXT, $CACHE); } if (!$file) { //download failed - redirect to original URL return array(302, $media); } } else { $media = cleanID($media); if (empty($media)) { return array(400, 'Bad request'); } // check token for resized images if (($width || $height) && media_get_token($media, $width, $height) !== $INPUT->str('tok')) { return array(412, 'Precondition Failed'); } //check permissions (namespace only) if (auth_quickaclcheck(getNS($media) . ':X') < AUTH_READ) { return array(403, 'Forbidden'); } $file = mediaFN($media, $rev); } //check file existance if (!file_exists($file)) { return array(404, 'Not Found'); } return array(200, null); }
/** * Set the text and HTML body and apply replacements * * This function applies a whole bunch of default replacements in addition * to the ones specified as parameters * * If you pass the HTML part or HTML replacements yourself you have to make * sure you encode all HTML special chars correctly * * @param string $text plain text body * @param array $textrep replacements to apply on the text part * @param array $htmlrep replacements to apply on the HTML part, leave null to use $textrep * @param string $html the HTML body, leave null to create it from $text * @param bool $wrap wrap the HTML in the default header/Footer */ public function setBody($text, $textrep = null, $htmlrep = null, $html = null, $wrap = true) { $htmlrep = (array) $htmlrep; $textrep = (array) $textrep; // create HTML from text if not given if (is_null($html)) { $html = $text; $html = hsc($html); $html = preg_replace('/^----+$/m', '<hr >', $html); $html = nl2br($html); } if ($wrap) { $wrap = rawLocale('mailwrap', 'html'); $html = preg_replace('/\\n-- <br \\/>.*$/s', '', $html); //strip signature $html = str_replace('@EMAILSIGNATURE@', '', $html); //strip @EMAILSIGNATURE@ $html = str_replace('@HTMLBODY@', $html, $wrap); } if (strpos($text, '@EMAILSIGNATURE@') === false) { $text .= '@EMAILSIGNATURE@'; } // copy over all replacements missing for HTML (autolink URLs) foreach ($textrep as $key => $value) { if (isset($htmlrep[$key])) { continue; } if (media_isexternal($value)) { $htmlrep[$key] = '<a href="' . hsc($value) . '">' . hsc($value) . '</a>'; } else { $htmlrep[$key] = hsc($value); } } // embed media from templates $html = preg_replace_callback('/@MEDIA\\(([^\\)]+)\\)@/', array($this, 'autoembed_cb'), $html); // add default token replacements $trep = array_merge($this->replacements['text'], (array) $textrep); $hrep = array_merge($this->replacements['html'], (array) $htmlrep); // Apply replacements foreach ($trep as $key => $substitution) { $text = str_replace('@' . strtoupper($key) . '@', $substitution, $text); } foreach ($hrep as $key => $substitution) { $html = str_replace('@' . strtoupper($key) . '@', $substitution, $html); } $this->setHTML($html); $this->setText($text); }
/** * Set the text and HTML body and apply replacements * * This function applies a whole bunch of default replacements in addition * to the ones specidifed as parameters * * If you pass the HTML part or HTML replacements yourself you have to make * sure you encode all HTML special chars correctly * * @param string $text plain text body * @param array $textrep replacements to apply on the text part * @param array $htmlrep replacements to apply on the HTML part, leave null to use $textrep * @param string $html the HTML body, leave null to create it from $text * @param bool $wrap wrap the HTML in the default header/Footer */ public function setBody($text, $textrep = null, $htmlrep = null, $html = null, $wrap = true) { global $INFO; global $conf; /* @var Input $INPUT */ global $INPUT; $htmlrep = (array) $htmlrep; $textrep = (array) $textrep; // create HTML from text if not given if (is_null($html)) { $html = $text; $html = hsc($html); $html = preg_replace('/^-----*$/m', '<hr >', $html); $html = nl2br($html); } if ($wrap) { $wrap = rawLocale('mailwrap', 'html'); $html = preg_replace('/\\n-- <br \\/>.*$/s', '', $html); //strip signature $html = str_replace('@HTMLBODY@', $html, $wrap); } // copy over all replacements missing for HTML (autolink URLs) foreach ($textrep as $key => $value) { if (isset($htmlrep[$key])) { continue; } if (media_isexternal($value)) { $htmlrep[$key] = '<a href="' . hsc($value) . '">' . hsc($value) . '</a>'; } else { $htmlrep[$key] = hsc($value); } } // embed media from templates $html = preg_replace_callback('/@MEDIA\\(([^\\)]+)\\)@/', array($this, 'autoembed_cb'), $html); // prepare default replacements $ip = clientIP(); $cip = gethostsbyaddrs($ip); $trep = array('DATE' => dformat(), 'BROWSER' => $INPUT->server->str('HTTP_USER_AGENT'), 'IPADDRESS' => $ip, 'HOSTNAME' => $cip, 'TITLE' => $conf['title'], 'DOKUWIKIURL' => DOKU_URL, 'USER' => $INPUT->server->str('REMOTE_USER'), 'NAME' => $INFO['userinfo']['name'], 'MAIL' => $INFO['userinfo']['mail']); $trep = array_merge($trep, (array) $textrep); $hrep = array('DATE' => '<i>' . hsc(dformat()) . '</i>', 'BROWSER' => hsc($INPUT->server->str('HTTP_USER_AGENT')), 'IPADDRESS' => '<code>' . hsc($ip) . '</code>', 'HOSTNAME' => '<code>' . hsc($cip) . '</code>', 'TITLE' => hsc($conf['title']), 'DOKUWIKIURL' => '<a href="' . DOKU_URL . '">' . DOKU_URL . '</a>', 'USER' => hsc($INPUT->server->str('REMOTE_USER')), 'NAME' => hsc($INFO['userinfo']['name']), 'MAIL' => '<a href="mailto:"' . hsc($INFO['userinfo']['mail']) . '">' . hsc($INFO['userinfo']['mail']) . '</a>'); $hrep = array_merge($hrep, (array) $htmlrep); // Apply replacements foreach ($trep as $key => $substitution) { $text = str_replace('@' . strtoupper($key) . '@', $substitution, $text); } foreach ($hrep as $key => $substitution) { $html = str_replace('@' . strtoupper($key) . '@', $substitution, $html); } $this->setHTML($html); $this->setText($text); }
function _recordMediaUsage($src) { global $ID; list($src, $hash) = explode('#', $src, 2); if (media_isexternal($src)) { return; } resolve_mediaid(getNS($ID), $src, $exists); $this->meta['relation']['media'][$src] = $exists; }
/** * Calculate a token to be used to verify fetch requests for resized or * cropped images have been internally generated - and prevent external * DDOS attacks via fetch * * @author Christopher Smith <*****@*****.**> * * @param string $id id of the image * @param int $w resize/crop width * @param int $h resize/crop height * @return string */ function media_get_token($id, $w, $h) { // token is only required for modified images if ($w || $h || media_isexternal($id)) { $token = $id; if ($w) { $token .= '.' . $w; } if ($h) { $token .= '.' . $h; } return substr(PassHash::hmac('md5', $token, auth_cookiesalt()), 0, 6); } return ''; }
function Doku_Handler_Parse_Media($match) { // Strip the opening and closing markup $link = preg_replace(array('/^\\{\\{/', '/\\}\\}$/u'), '', $match); // Split title from URL $link = explode('|', $link, 2); // Check alignment $ralign = (bool) preg_match('/^ /', $link[0]); $lalign = (bool) preg_match('/ $/', $link[0]); // Logic = what's that ;)... if ($lalign & $ralign) { $align = 'center'; } else { if ($ralign) { $align = 'right'; } else { if ($lalign) { $align = 'left'; } else { $align = null; } } } // The title... if (!isset($link[1])) { $link[1] = null; } //remove aligning spaces $link[0] = trim($link[0]); //split into src and parameters (using the very last questionmark) $pos = strrpos($link[0], '?'); if ($pos !== false) { $src = substr($link[0], 0, $pos); $param = substr($link[0], $pos + 1); } else { $src = $link[0]; $param = ''; } //parse width and height if (preg_match('#(\\d+)(x(\\d+))?#i', $param, $size)) { !empty($size[1]) ? $w = $size[1] : ($w = null); !empty($size[3]) ? $h = $size[3] : ($h = null); } else { $w = null; $h = null; } //get linking command if (preg_match('/nolink/i', $param)) { $linking = 'nolink'; } else { if (preg_match('/direct/i', $param)) { $linking = 'direct'; } else { if (preg_match('/linkonly/i', $param)) { $linking = 'linkonly'; } else { $linking = 'details'; } } } //get caching command if (preg_match('/(nocache|recache)/i', $param, $cachemode)) { $cache = $cachemode[1]; } else { $cache = 'cache'; } // Check whether this is a local or remote image if (media_isexternal($src)) { $call = 'externalmedia'; } else { $call = 'internalmedia'; } $params = array('type' => $call, 'src' => $src, 'title' => $link[1], 'align' => $align, 'width' => $w, 'height' => $h, 'cache' => $cache, 'linking' => $linking); return $params; }
/** * Return formated data, depending on column type * * @param array $column * @param string $value * @param Doku_Renderer $R * @return string */ function _formatDataNew($column, $value, Doku_Renderer $R) { global $conf; $vals = explode("\n", $value); $outs = array(); //multivalued line from db result for pageid and wiki has only in first value the ID $storedID = ''; foreach ($vals as $val) { $val = trim($val); if ($val == '') { continue; } $type = $column['type']; if (is_array($type)) { $type = $type['type']; } switch ($type) { case 'page': $val = $this->_addPrePostFixes($column['type'], $val); $val = $this->ensureAbsoluteId($val); $outs[] = $R->internallink($val, null, null, true); break; case 'title': list($id, $title) = explode('|', $val, 2); $id = $this->_addPrePostFixes($column['type'], $id); $id = $this->ensureAbsoluteId($id); $outs[] = $R->internallink($id, $title, null, true); break; case 'pageid': list($id, $title) = explode('|', $val, 2); //use ID from first value of the multivalued line if ($title == null) { $title = $id; if (!empty($storedID)) { $id = $storedID; } } else { $storedID = $id; } $id = $this->_addPrePostFixes($column['type'], $id); $outs[] = $R->internallink($id, $title, null, true); break; case 'nspage': // no prefix/postfix here $val = ':' . $column['key'] . ":{$val}"; $outs[] = $R->internallink($val, null, null, true); break; case 'mail': list($id, $title) = explode(' ', $val, 2); $id = $this->_addPrePostFixes($column['type'], $id); if (!$title) { $title = $id; } else { $title = hsc($title); } $outs[] = $R->emaillink($id, $title, true); break; case 'url': $val = $this->_addPrePostFixes($column['type'], $val); $outs[] = $R->externallink($val, null, true); break; case 'tag': // per default use keyname as target page, but prefix on aliases if (!is_array($column['type'])) { $target = $column['key'] . ':'; } else { $target = $this->_addPrePostFixes($column['type'], ''); } $params = buildURLparams($this->_getTagUrlparam($column, $val)); $url = str_replace('/', ':', cleanID($target)) . '?' . $params; // FIXME: The title is lost when moving to $R->internallink, // but this syntax is required to support different renderers. // $title = sprintf($this->getLang('tagfilter'), hsc($val)); $outs[] = $R->internallink($url, hsc($val), true); break; case 'timestamp': $outs[] = dformat($val); break; case 'wiki': global $ID; $oldid = $ID; list($ID, $data) = explode('|', $val, 2); //use ID from first value of the multivalued line if ($data == null) { $data = $ID; $ID = $storedID; } else { $storedID = $ID; } $data = $this->_addPrePostFixes($column['type'], $data); // Trim document_{start,end}, p_{open,close} from instructions $allinstructions = p_get_instructions($data); $wraps = 1; if (isset($allinstructions[1]) && $allinstructions[1][0] == 'p_open') { $wraps++; } $instructions = array_slice($allinstructions, $wraps, -$wraps); $outs[] = p_render($R->getFormat(), $instructions, $byref_ignore); $ID = $oldid; break; default: $val = $this->_addPrePostFixes($column['type'], $val); //type '_img' or '_img<width>' if (substr($type, 0, 3) == 'img') { $width = (int) substr($type, 3); if (!$width) { $width = $this->getConf('image_width'); } list($mediaid, $title) = explode('|', $val, 2); if ($title === null) { $title = $column['key'] . ': ' . basename(str_replace(':', '/', $mediaid)); } else { $title = trim($title); } if (media_isexternal($val)) { $html = $R->externalmedia($mediaid, $title, $align = null, $width, $height = null, $cache = null, $linking = 'direct', true); } else { $html = $R->internalmedia($mediaid, $title, $align = null, $width, $height = null, $cache = null, $linking = 'direct', true); } if (strpos($html, 'mediafile') === false) { $html = str_replace('href', 'rel="lightbox" href', $html); } $outs[] = $html; } else { $outs[] = hsc($val); } } } return join(', ', $outs); }