| Line 1... | Line 1... | 
      
        | 1 | <?php | 1 | <?php | 
      
        | 2 | # vim:et:ts=3:sts=3:sw=3:fdm=marker: | - |  | 
      
        | 3 |   | - |  | 
      
        | 4 | // WebSVN - Subversion repository viewing via the web using PHP | 2 | // WebSVN - Subversion repository viewing via the web using PHP | 
      
        | 5 | // Copyright © 2004-2006 Tim Armes, Matt Sicker | 3 | // Copyright (C) 2004-2006 Tim Armes | 
      
        | 6 | // | 4 | // | 
      
        | 7 | // This program is free software; you can redistribute it and/or modify | 5 | // This program is free software; you can redistribute it and/or modify | 
      
        | 8 | // it under the terms of the GNU General Public License as published by | 6 | // it under the terms of the GNU General Public License as published by | 
      
        | 9 | // the Free Software Foundation; either version 2 of the License, or | 7 | // the Free Software Foundation; either version 2 of the License, or | 
      
        | 10 | // (at your option) any later version. | 8 | // (at your option) any later version. | 
      
        | 11 | // | 9 | // | 
      
        | 12 | // This program is distributed in the hope that it will be useful, | 10 | // This program is distributed in the hope that it will be useful, | 
      
        | 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
      
        | 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
      
        | 15 | // GNU General Public License for more details. | 13 | // GNU General Public License for more details. | 
      
        | 16 | // | 14 | // | 
      
        | 17 | // You should have received a copy of the GNU General Public License | 15 | // You should have received a copy of the GNU General Public License | 
      
        | 18 | // along with this program; if not, write to the Free Software | 16 | // along with this program; if not, write to the Free Software | 
      
        | 19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
      
        | 20 | // | 18 | // | 
      
        | 21 | // -- | 19 | // -- | 
      
        | 22 | // | 20 | // | 
      
        | 23 | // filedetails.php | 21 | // filedetails.php | 
      
        | 24 | // | 22 | // | 
      
        | 25 | // Simply lists the contents of a file | 23 | // Simply lists the contents of a file | 
      
        | 26 |   | 24 |   | 
      
        | 27 | require_once("include/setup.inc"); | 25 | require_once 'include/setup.php'; | 
      
        | 28 | require_once("include/svnlook.inc"); | 26 | require_once 'include/svnlook.php'; | 
      
        | 29 | require_once("include/utils.inc"); | 27 | require_once 'include/utils.php'; | 
      
        | 30 | require_once("include/template.inc"); | 28 | require_once 'include/template.php'; | 
      
        | 31 |   | 29 |   | 
      
        | 32 | // Make sure that we have a repository | 30 | // Make sure that we have a repository | 
      
        | 33 | if (!isset($rep)) | 31 | if (!$rep) | 
      
        | 34 | { | 32 | { | 
      
        | 35 |    echo $lang["NOREP"]; | 33 | 	renderTemplate404('file','NOREP'); | 
      
        | 36 |    exit; | - |  | 
      
        | 37 | } | 34 | } | 
      
        | 38 |   | 35 |   | 
      
        | 39 | $svnrep = new SVNRepository($rep); | 36 | $svnrep = new SVNRepository($rep); | 
      
        | 40 |   | 37 |   | 
      
        | 41 | if ($path{0} != "/") | 38 | if ($path[0] != '/')  | 
      
        | - |  | 39 | { | 
      
        | 42 |    $ppath = "/".$path; | 40 | 	$ppath = '/'.$path; | 
      
        | - |  | 41 | }  | 
      
        | 43 | else | 42 | else  | 
      
        | - |  | 43 | { | 
      
        | 44 |    $ppath = $path; | 44 | 	$ppath = $path; | 
      
        | - |  | 45 | } | 
      
        | 45 |   | 46 |   | 
      
        | 46 | $passrev = $rev; | 47 | $useMime = false; | 
      
        | 47 |   | 48 |   | 
      
        | 48 | // If there's no revision info, go to the lastest revision for this path | 49 | // If there's no revision info, go to the lastest revision for this path | 
      
        | 49 | $history = $svnrep->getLog($path, "", "", true); | 50 | $history = $svnrep->getLog($path, 'HEAD', 1, false, 2, ($path == '/') ? '' : $peg); | 
      
        | 50 | $youngest = $history->entries[0]->rev; | - |  | 
      
        | 51 |   | 51 |   | 
      
        | - |  | 52 | if (!$history)  | 
      
        | - |  | 53 | { | 
      
        | - |  | 54 | 	unset($vars['error']); | 
      
        | - |  | 55 | 	$history = $svnrep->getLog($path, '', '', false, 2, ($path == '/') ? '' : $peg); | 
      
        | - |  | 56 | 	if (!$history)  | 
      
        | - |  | 57 | 	{ | 
      
        | - |  | 58 | 		renderTemplate404('file','NOPATH'); | 
      
        | - |  | 59 | 	} | 
      
        | - |  | 60 | } | 
      
        | - |  | 61 |   | 
      
        | - |  | 62 | $youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false; | 
      
        | - |  | 63 |   | 
      
        | 52 | if (empty($rev)) | 64 | if (empty($rev))  | 
      
        | - |  | 65 | { | 
      
        | 53 |    $rev = $youngest; | 66 | 	$rev = !$peg ? $youngest : min($peg, $youngest); | 
      
        | - |  | 67 | } | 
      
        | 54 |   | 68 |   | 
      
        | 55 | $extn = strrchr($path, "."); | 69 | $extn = strtolower(strrchr($path, '.')); | 
      
        | 56 |   | 70 |   | 
      
        | 57 | // Check to see if the user has requested that this type be zipped and sent | 71 | // Check to see if the user has requested that this type be zipped and sent | 
      
        | 58 | // to the browser as an attachment | 72 | // to the browser as an attachment | 
      
        | 59 |   | 73 |   | 
      
        | 60 | if (in_array($extn, $zipped)) | 74 | if ($history && isset($zipped) && in_array($extn, $zipped) && $rep->hasReadAccess($path, false))  | 
      
        | 61 | { | 75 | { | 
      
        | 62 |    $base = basename($path); | 76 | 	$base = basename($path); | 
      
        | 63 |    header("Content-Type: application/x-gzip"); | 77 | 	header('Content-Type: application/gzip'); | 
      
        | 64 |    header("Content-Disposition: attachment; filename=".urlencode($base).".gz"); | 78 | 	header("Content-Disposition: attachment; filename*=UTF-8''".rawurlencode($base).'.gz'); | 
      
        | 65 |   | 79 |   | 
      
        | 66 |    // Get the file contents and pipe into gzip.  All this without creating | 80 | 	// Get the file contents and pipe into gzip. All this without creating | 
      
        | 67 |    // a temporary file.  Damn clever. | 81 | 	// a temporary file. Damn clever. | 
      
        | 68 |    $svnrep->getFileContents($path, "", $rev, "| ".$config->gzip." -n -f"); | 82 | 	$svnrep->getFileContents($path, '', $rev, $peg, '| '.$config->gzip.' -n -f'); | 
      
        | 69 |     | - |  | 
      
        | 70 |    exit; | 83 | 	exit; | 
      
        | 71 | } | 84 | } | 
      
        | 72 |   | 85 |   | 
      
        | 73 | // Check to see if we should serve it with a particular content-type. | 86 | // Check to see if we should serve it with a particular content-type. | 
      
        | 74 | // The content-type could come from an svn:mime-type property on the | 87 | // The content-type could come from an svn:mime-type property on the | 
      
        | 75 | // file, or from the $contentType array in setup.inc. | 88 | // file, or from the $contentType array in setup.php. | 
      
        | 76 |   | 89 |   | 
      
        | 77 | if (!$rep->getIgnoreSvnMimeTypes())  | 90 | if (!$rep->getIgnoreSvnMimeTypes())  | 
      
        | 78 | { | 91 | { | 
      
        | 79 |   $svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev); | 92 | 	$svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev); | 
      
        | 80 | } | 93 | } | 
      
        | 81 |   | 94 |   | 
      
        | 82 | if (!$rep->getIgnoreWebSVNContentTypes())  | 95 | if (!$rep->getIgnoreWebSVNContentTypes())  | 
      
        | 83 | { | 96 | { | 
      
        | 84 |   $setupContentType = @$contentType[$extn]; | 97 | 	$setupContentType = @$contentType[$extn]; | 
      
        | 85 | } | 98 | } | 
      
        | 86 |   | 99 |   | 
      
        | 87 | // Use this set of priorities when establishing what content-type to | 100 | // Use the documented priorities when establishing what content-type to use. | 
      
        | 88 | // actually use. | - |  | 
      
        | 89 |   | - |  | 
      
        | 90 | if (!empty($svnMimeType) && $svnMimeType != 'application/octet-stream')  | 101 | if (!empty($svnMimeType) && $svnMimeType != 'application/octet-stream')  | 
      
        | 91 | { | 102 | { | 
      
        | 92 |   $cont = $svnMimeType; | 103 | 	$mimeType = $svnMimeType; | 
      
        | 93 | } | 104 | } | 
      
        | 94 | else if (!empty($setupContentType)) | 105 | else if (!empty($setupContentType))  | 
      
        | 95 | { | 106 | { | 
      
        | 96 |   $cont = $setupContentType; | 107 | 	$mimeType = $setupContentType; | 
      
        | 97 | }  | 108 | } | 
      
        | 98 | else if (!empty($svnMimeType)) | 109 | else if (!empty($svnMimeType))  | 
      
        | - |  | 110 | { | 
      
        | - |  | 111 | 	$mimeType = $svnMimeType; // Use SVN's default of 'application/octet-stream' | 
      
        | - |  | 112 | } | 
      
        | - |  | 113 | else  | 
      
        | - |  | 114 | { | 
      
        | - |  | 115 | 	$mimeType = ''; | 
      
        | - |  | 116 | } | 
      
        | - |  | 117 |   | 
      
        | - |  | 118 | $useMime = ($mimeType) ? @$_REQUEST['usemime'] : false; | 
      
        | - |  | 119 |   | 
      
        | - |  | 120 | if ($history && !empty($mimeType) && !$useMime)  | 
      
        | - |  | 121 | { | 
      
        | - |  | 122 | 	$useMime = $mimeType; // Save MIME type for later before possibly clobbering | 
      
        | - |  | 123 | 	// If a MIME type exists but is set to be ignored, set it to an empty string. | 
      
        | - |  | 124 | 	foreach ($config->inlineMimeTypes as $inlineType)  | 
      
        | - |  | 125 | 	{ | 
      
        | - |  | 126 | 		if (preg_match('|'.$inlineType.'|', $mimeType))  | 
      
        | - |  | 127 | 		{ | 
      
        | - |  | 128 | 			$mimeType = ''; | 
      
        | - |  | 129 | 			break; | 
      
        | - |  | 130 | 		} | 
      
        | - |  | 131 | 	} | 
      
        | - |  | 132 | } | 
      
        | - |  | 133 |   | 
      
        | - |  | 134 | // If a MIME type is associated with the file, deliver with Content-Type header. | 
      
        | - |  | 135 | if ($history && !empty($mimeType) && $rep->hasReadAccess($path, false))  | 
      
        | 99 | { | 136 | { | 
      
        | - |  | 137 | 	$base = basename($path); | 
      
        | 100 |   // It now is equal to application/octet-stream due to logic | 138 | 	header('Content-Type: '.$mimeType); | 
      
        | 101 |   // above.... | 139 | 	//header('Content-Length: '.$size); | 
      
        | - |  | 140 | 	header("Content-Disposition: inline; filename*=UTF-8''".rawurlencode($base)); | 
      
        | 102 |   $cont = $svnMimeType; | 141 | 	$svnrep->getFileContents($path, '', $rev, $peg); | 
      
        | - |  | 142 | 	exit; | 
      
        | 103 | } | 143 | } | 
      
        | 104 |   | 144 |   | 
      
        | - |  | 145 | // Display the file inline using WebSVN. | 
      
        | - |  | 146 |   | 
      
        | - |  | 147 | $vars['action'] = ''; | 
      
        | 105 | // If there's a MIME type associated with this format, then we deliver it | 148 | $vars['path'] = str_replace('%2F', '/', rawurlencode($ppath)); | 
      
        | 106 | // with this information  | 149 | $vars['safepath'] = escape($ppath); | 
      
        | 107 |   | 150 |   | 
      
        | 108 | if (!empty($cont)) | 151 | if (isset($history->entries[0]))  | 
      
        | 109 | { | 152 | { | 
      
        | 110 |    $base = basename($path); | - |  | 
      
        | 111 |     | - |  | 
      
        | 112 |    header("Content-Type: $cont"); | 153 | 	$vars['log'] = xml_entities($history->entries[0]->msg); | 
      
        | 113 |    //header("Content-Length: $size"); | 154 | 	$vars['date'] = $history->entries[0]->date; | 
      
        | 114 |    header("Content-Disposition: inline; filename=".urlencode($base)); | 155 | 	$vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date)); | 
      
        | 115 |     | - |  | 
      
        | 116 |    $svnrep->getFileContents($path, "", $rev); | 156 | 	$vars['author'] = $history->entries[0]->author; | 
      
        | 117 |     | - |  | 
      
        | 118 |    exit; | - |  | 
      
        | 119 | } | 157 | } | 
      
        | 120 |   | 158 |   | 
      
        | - |  | 159 | createPathLinks($rep, $ppath, !$passrev && $peg ? $rev : $passrev, $peg); | 
      
        | 121 | // Explicitly requested file as attachment | 160 | $passRevString = createRevAndPegString($rev, $peg); | 
      
        | - |  | 161 |   | 
      
        | 122 | if (isset($_REQUEST['getfile'])) | 162 | if ($rev != $youngest)  | 
      
        | 123 | { | 163 | { | 
      
        | 124 |    $base = basename($path); | 164 | 	$vars['goyoungesturl'] = $config->getURL($rep, $path, 'file').createRevAndPegString($youngest, $peg); | 
      
        | - |  | 165 | 	$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>'; | 
      
        | - |  | 166 | } | 
      
        | 125 |   | 167 |   | 
      
        | 126 |    header("Content-Type: application/octet-stream"); | - |  | 
      
        | 127 |    header("Content-Length: $size"); | 168 | $revurl = $config->getURL($rep, $path, 'file'); | 
      
        | 128 |    header("Content-Disposition: inline; filename=".urlencode($base)); | - |  | 
      
        | 129 |   | 169 |   | 
      
        | - |  | 170 | if ($rev < $youngest)  | 
      
        | - |  | 171 | { | 
      
        | 130 |    $svnrep->getFileContents($path, "", $rev); | 172 | 	$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg ? $peg : 'HEAD'); | 
      
        | 131 |   | 173 |   | 
      
        | - |  | 174 | 	if (isset($history2->entries[1]))  | 
      
        | - |  | 175 | 	{ | 
      
        | - |  | 176 | 		$nextRev = $history2->entries[1]->rev; | 
      
        | - |  | 177 | 		if ($nextRev != $youngest)  | 
      
        | - |  | 178 | 		{ | 
      
        | - |  | 179 | 			$vars['nextrev'] = $nextRev; | 
      
        | - |  | 180 | 			$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg); | 
      
        | 132 |    exit; | 181 | 		} | 
      
        | - |  | 182 | 	} | 
      
        | - |  | 183 |   | 
      
        | - |  | 184 | 	unset($vars['error']); | 
      
        | 133 | } | 185 | } | 
      
        | 134 |   | 186 |   | 
      
        | 135 | // There's no associated MIME type.  Show the file using WebSVN. | 187 | $history3 = $svnrep->getLog($path, $rev, 1, true, 2, $peg ? $peg : 'HEAD'); | 
      
        | 136 |   | 188 |   | 
      
        | - |  | 189 | if (isset($history3->entries[1]))  | 
      
        | - |  | 190 | { | 
      
        | - |  | 191 | 	$prevRev = $history3->entries[1]->rev; | 
      
        | 137 | $url = $config->getURL($rep, $path, "file"); | 192 | 	$prevPath = $history3->entries[1]->path; | 
      
        | - |  | 193 | 	$vars['prevrev'] = $prevRev; | 
      
        | - |  | 194 | 	$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg); | 
      
        | - |  | 195 | } | 
      
        | 138 |   | 196 |   | 
      
        | 139 | if ($rev != $youngest) | 197 | unset($vars['error']); | 
      
        | 140 |    $vars["goyoungestlink"] = "<a href=\"${url}sc=1\">${lang["GOYOUNGEST"]}</a>"; | - |  | 
      
        | 141 | else | - |  | 
      
        | 142 |    $vars["goyoungestlink"] = ""; | - |  | 
      
        | 143 |   | 198 |   | 
      
        | 144 | $vars["action"] = ""; | - |  | 
      
        | 145 | $vars["repname"] = $rep->getDisplayName(); | 199 | $vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString; | 
      
        | 146 | $vars["rev"] = $rev; | 200 | $vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>'; | 
      
        | 147 | $vars["path"] = $ppath; | - |  | 
      
        | 148 |   | 201 |   | 
      
        | 149 | createDirLinks($rep, $ppath, $passrev, $showchanged); | 202 | $vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString; | 
      
        | - |  | 203 | $vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>'; | 
      
        | 150 |   | 204 |   | 
      
        | 151 | $url = $config->getURL($rep, $path, "log"); | 205 | $vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString; | 
      
        | 152 | $vars["fileviewloglink"] = "<a href=\"${url}rev=$passrev&sc=$showchanged&isdir=0\">${lang["VIEWLOG"]}</a>"; | 206 | $vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>'; | 
      
        | 153 |   | 207 |   | 
      
        | - |  | 208 | if ($history == null || count($history->entries) > 1)  | 
      
        | - |  | 209 | { | 
      
        | 154 | $url = $config->getURL($rep, $path, "diff"); | 210 | 	$vars['diffurl'] = $config->getURL($rep, $path, 'diff').$passRevString; | 
      
        | 155 | $vars["prevdifflink"] = "<a href=\"${url}rev=$passrev&sc=$showchanged\">${lang["DIFFPREV"]}</a>"; | 211 | 	$vars['difflink'] = '<a href="'.$vars['diffurl'].'">'.$lang['DIFFPREV'].'</a>'; | 
      
        | - |  | 212 | } | 
      
        | 156 |   | 213 |   | 
      
        | - |  | 214 | if ($rep->isDownloadAllowed($path))  | 
      
        | - |  | 215 | { | 
      
        | 157 | $url = $config->getURL($rep, $path, "blame"); | 216 | 	$vars['downloadlurl'] = $config->getURL($rep, $path, 'dl').$passRevString; | 
      
        | 158 | $vars["blamelink"] = "<a href=\"${url}rev=$passrev&sc=$showchanged\">${lang["BLAME"]}</a>"; | 217 | 	$vars['downloadlink'] = '<a href="'.$vars['downloadlurl'].'">'.$lang['DOWNLOAD'].'</a>'; | 
      
        | - |  | 218 | } | 
      
        | 159 |   | 219 |   | 
      
        | 160 | #$url = $config->getURL($rep, $path, "get"); | 220 | if ($rep->isRssEnabled())  | 
      
        | - |  | 221 | { | 
      
        | 161 | $url = $config->getURL($rep, $path, "file"); | 222 | 	$vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg); | 
      
        | 162 | $vars["getfile"] = "<a href=\"${url}getfile&rev=$passrev&sc=$showchanged\">${lang["GETFILE"]}</a>"; | 223 | 	$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>'; | 
      
        | - |  | 224 | } | 
      
        | 163 |   | 225 |   | 
      
        | - |  | 226 | $mimeType = $useMime; // Restore preserved value to use for 'mimelink' variable. | 
      
        | - |  | 227 | // If there was a MIME type, create a link to display file with that type. | 
      
        | 164 | $listing = array (); | 228 | if ($mimeType && !isset($vars['warning']))  | 
      
        | - |  | 229 | { | 
      
        | - |  | 230 | 	$vars['mimeurl'] = $config->getURL($rep, $path, 'file').'usemime=1&'.$passRevString; | 
      
        | - |  | 231 | 	$vars['mimelink'] = '<a href="'.$vars['mimeurl'].'">'.$lang['VIEWAS'].' "'.$mimeType.'"</a>'; | 
      
        | - |  | 232 | } | 
      
        | 165 |   | 233 |   | 
      
        | - |  | 234 | $vars['rev'] = $rev; | 
      
        | 166 | $vars["version"] = $version; | 235 | $vars['peg'] = $peg; | 
      
        | 167 |   | 236 |   | 
      
        | 168 | if (!$rep->hasReadAccess($path, false)) | 237 | if (!$rep->hasReadAccess($path))  | 
      
        | - |  | 238 | { | 
      
        | 169 |    $vars["noaccess"] = true; | 239 | 	$vars['error'] = $lang['NOACCESS']; | 
      
        | - |  | 240 | 	sendHeaderForbidden(); | 
      
        | - |  | 241 | } | 
      
        | - |  | 242 | else if (!$svnrep->isFile($path, $rev, $peg))  | 
      
        | - |  | 243 | { | 
      
        | - |  | 244 | 	renderTemplate404('file','NOPATH'); | 
      
        | - |  | 245 | } | 
      
        | 170 |   | 246 |   | 
      
        | 171 | parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing); | 247 | // $listing is populated with file data when file.tmpl calls [websvn-getlisting] | 
      
        | 172 | parseTemplate($rep->getTemplatePath()."file.tmpl", $vars, $listing); | 248 | renderTemplate('file'); | 
      
        | 173 | parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing); | - |  | 
      
        | 174 | ?> | - |  |