import
[web.mtrack] / web / file.php
1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
3
4 include '../inc/common.php';
5 MTrackACL::requireAllRights('Browser', 'read');
6
7 $pi = mtrack_get_pathinfo(true);
8
9 $data = explode('@', $pi);
10 $pi = $data[0];
11 if (isset($data[1])) {
12   $_GET['rev'] = $data[1];
13 }
14
15 $crumbs = MTrackSCM::makeBreadcrumbs($pi);
16 if (!strlen($pi) || $pi == '/') {
17   $pi = '/';
18 } else {
19   $repo = MTrackSCM::factory($pi);
20 }
21
22 if (!$repo) {
23   throw new Exception("invalid path $pi");
24 }
25 MTrackACL::requireAllRights("repo:$repo->repoid", 'read');
26
27 if (isset($_GET['rev'])) {
28   $file = $repo->file($pi, 'rev', $_GET['rev']);
29 } else {
30   $file = $repo->file($pi);
31 }
32
33 $ent = $file->getChangeEvent();
34
35 if (isset($_GET['raw']) && $_GET['raw'] == 1) {
36   $filename = basename($pi);
37   header("Content-Type: application/octet-stream; name=\"$filename\"");
38   header("Content-Disposition: attachment; filename=\"$filename\"");
39   fpassthru($file->cat());
40   exit;
41 }
42
43 mtrack_head("File $pi @ " . $file->rev);
44
45 /* Render a bread-crumb enabled location indicator */
46 echo "<div class='browselocation'>Location: ";
47 $location = null;
48 $last = array_pop($crumbs);
49 if (isset($_GET['jump'])) {
50   $jump = '?jump=' . urlencode($_GET['jump']);
51 } else {
52   $jump = '';
53 }
54 foreach ($crumbs as $path) {
55   if (!strlen($path)) {
56     $path = '[root]';
57   } else {
58     $location .= '/' . urlencode($path);
59   }
60   $path = htmlentities($path, ENT_QUOTES, 'utf-8');
61   echo "<a href='{$ABSWEB}browse.php$location$jump'>$path</a> / ";
62 }
63
64 echo "$last @ " . mtrack_changeset($ent->rev, $repo);
65 echo "</div>";
66
67 echo "<div class='revinfo'>\n";
68 echo MTrackWiki::format_to_html($ent->changelog);
69 echo "<div class='changeinfo'>\n";
70 echo mtrack_username($ent->changeby, array('size' => 32));
71 echo "<br>\n";
72 echo mtrack_date($ent->ctime, true) . "<br>\n";
73 echo "Revision: $repo->shortname $ent->rev";
74 foreach ($ent->branches as $b) {
75   echo " " . mtrack_branch($b);
76 }
77 foreach ($ent->tags as $t) {
78   echo " " . mtrack_tag($t);
79 }
80 echo "</div></div>\n";
81
82 echo "<br><a href='{$ABSWEB}log.php/" .
83   $repo->getBrowseRootName() .
84   htmlentities("/$pi$jump", ENT_QUOTES, 'utf-8') .
85   "'>Show revision log</a>";
86
87 /* Do we want to show the file? */
88
89 $finfo = pathinfo($file->name);
90 $t = tmpfile();
91
92 $data = $file->cat();
93 stream_copy_to_stream($data, $t);
94 $data = null;
95
96 $info = fstat($t);
97
98 $location = stream_get_meta_data($t);
99 $location = $location['uri'];
100
101 $mimetype = mtrack_mime_detect($location, $file->name);
102 list($major) = explode('/', $mimetype, 2);
103
104 // Obscure-ish special cases for mime types;
105 // some .y files look like old image format data
106 if ($mimetype == 'image/x-3ds') {
107   $major = 'text';
108 } elseif ($mimetype == 'application/xml') {
109   $major = 'text';
110 }
111
112
113 $p = $_GET;
114 $p['raw'] = 1;
115 $raw_url = $ABSWEB . 'file.php' . (isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '') .
116   '?' . http_build_query($p);
117
118 if ($major == 'text') {
119   fseek($t, 0);
120   $ann = $file->annotate();
121   if ($ann === 'DELETED') {
122     echo "<div>Deleted</div>\n";
123   } else {
124     $i = 1;
125
126     $data = stream_get_contents($t);
127     $data = MTrackSyntaxHighlight::highlightSource($data, null, $file->name);
128
129     echo <<<HTML
130 <br>
131 <br>
132 <button type='button' class='toggle-ann'>Blame</button>
133 <button type='button' class='toggle-line'>Line #s</button>
134 HTML;
135     echo MTrackSyntaxHighlight::getSchemeSelect();
136     echo <<<HTML
137 <script>
138 $(document).ready(function () {
139   var ann = false;
140   var line = true;
141   $('.toggle-ann').click(function () {
142     ann = !ann;
143     if (ann) {
144       $('table.codeann .user').show();
145       $('table.codeann .changeset').show();
146     } else {
147       $('table.codeann .user').hide();
148       $('table.codeann .changeset').hide();
149     }
150   });
151   $('.toggle-line').click(function () {
152     ann = !ann;
153     if (ann) {
154       $('table.codeann .line').show();
155     } else {
156       $('table.codeann .line').hide();
157     }
158   });
159 });
160 </script>
161 HTML;
162
163     echo "<br><br><table class='codeann'><tr><th class='changeset'>rev</th><th class='user'>who</th><th class='line'>line</th><th class='code'>code</th></tr>\n";
164
165     while (isset($ann[$i])) {
166       $a = $ann[$i];
167       echo "<tr>" .
168         "<td class='changeset'>" . mtrack_changeset($a->rev, $repo) . "</td>" .
169         "<td class='user'>" . mtrack_username($a->changeby,
170             array('no_image' => true)) . "</td>" .
171         "<td class='line'><a name='l$i'></a><a href='#l$i'>$i</a></td>";
172
173       if ($i == 1) {
174         $nlines = count($ann);
175         echo "<td rowspan='$nlines' width='100%' class='source-code wezterm'>$data</td>";
176       }
177       echo "</tr>\n";
178
179       $i++;
180     }
181
182     echo "</table>\n";
183   }
184 } elseif ($major == 'image') {
185   echo "<br><br><img src='$raw_url'>\n";
186 }
187 echo "<br><br><a href='$raw_url'>Download File</a> ($mimetype)\n";
188
189 mtrack_foot();
190