1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
4 class MTrackAttachment {
6 static function add($object, $local_filename, $filename,
9 $size = filesize($local_filename);
13 $hash = self::import_file($local_filename);
14 $fp = fopen($local_filename, 'rb');
15 $q = MTrackDB::get()->prepare(
16 'insert into attachments (object, hash, filename, size, cid, payload)
17 values (?, ?, ?, ?, ?, ?)');
18 $q->bindValue(1, $object);
19 $q->bindValue(2, $hash);
20 $q->bindValue(3, $filename);
21 $q->bindValue(4, $size);
22 $q->bindValue(5, $CS->cid);
23 $q->bindValue(6, $fp, PDO::PARAM_LOB);
25 $CS->add("$object:@attachment:", '', $filename);
28 static function process_delete($relobj, MTrackChangeset $CS) {
29 if (!isset($_POST['delete_attachment'])) return;
30 if (!is_array($_POST['delete_attachment'])) return;
31 foreach ($_POST['delete_attachment'] as $name) {
32 $vars = explode('/', $name);
33 $filename = array_pop($vars);
34 $cid = array_pop($vars);
35 $object = join('/', $vars);
37 if ($object != $relobj) return;
38 MTrackDB::q('delete from attachments where object = ? and
39 cid = ? and filename = ?', $object, $cid, $filename);
40 $CS->add("$object:@attachment:", $filename, '');
44 /* this function is registered into sqlite and invoked from
45 * a trigger whenever an attachment row is deleted */
46 static function attachment_row_deleted($hash, $count)
49 // unlink the underlying file here
50 unlink(self::local_path($hash, false));
55 static function hash_file($filename)
57 return sha1_file($filename);
60 static function local_path($hash, $fetch = true)
62 $adir = MTrackConfig::get('core', 'vardir') . '/attach';
64 /* 40 hex digits: split into 16, 16, 4, 4 */
65 $a = substr($hash, 0, 16);
66 $b = substr($hash, 16, 16);
67 $c = substr($hash, 32, 4);
68 $d = substr($hash, 36, 4);
70 $dir = "$adir/$a/$b/$c";
73 mkdir($dir, 02777, true);
76 $filename = $dir . "/$d";
80 $fp = @fopen($filename, 'c+');
83 if ($st['size'] == 0) {
84 /* we get to fill it out */
86 $db = MTrackDB::get();
88 'select payload from attachments where hash = ?');
89 $q->execute(array($hash));
90 $q->bindColumn(1, $blob, PDO::PARAM_LOB);
92 if (is_string($blob)) {
95 stream_copy_to_stream($blob, $fp);
104 /* calculates the hash of the filename. If another file with
105 * the same hash does not already exist in the attachment area,
106 * the file is copied in.
107 * Returns the hash */
108 static function import_file($filename)
110 $h = self::hash_file($filename);
111 $dest = self::local_path($h, false);
112 if (!file_exists($dest)) {
113 if (is_uploaded_file($filename)) {
114 move_uploaded_file($filename, $dest);
115 } else if (!is_file($filename)) {
116 throw new Exception("$filename does not exist");
118 copy($filename, $dest);
124 static function renderDeleteList($object)
128 $atts = MTrackDB::q('
129 select * from attachments
130 left join changes on (attachments.cid = changes.cid)
131 where attachments.object = ? order by changedate, filename',
132 $object)->fetchAll(PDO::FETCH_ASSOC);
134 if (count($atts) == 0) return '';
139 <em>Select the checkbox to delete an attachment</em>
149 foreach ($atts as $row) {
150 $url = "{$ABSWEB}attachment.php/$object/$row[cid]/$row[filename]";
153 <td><input type='checkbox' name='delete_attachment[]'
154 value='$object/$row[cid]/$row[filename]'></td>
155 <td><a class='attachment' href='$url'>$row[filename]</a></td>
159 $html .= mtrack_username($row['who'], array(
162 " " . mtrack_date($row['changedate']) . "</td></tr>\n";
164 $html .= "</table><br>";
168 /* renders the attachment list for a given object */
169 static function renderList($object)
173 $atts = MTrackDB::q('
174 select * from attachments
175 left join changes on (attachments.cid = changes.cid)
176 where attachments.object = ? order by changedate, filename',
177 $object)->fetchAll(PDO::FETCH_ASSOC);
179 if (count($atts) == 0) return '';
183 $html = "<div class='attachment-list'><b>Attachments</b><ul>";
184 foreach ($atts as $row) {
185 $url = "{$ABSWEB}attachment.php/$object/$row[cid]/$row[filename]";
186 $html .= "<li><a class='attachment'" .
188 "$row[filename]</a> ($row[size]) added by " .
189 mtrack_username($row['who'], array(
192 " " . mtrack_date($row['changedate']);
194 list($width, $height) = getimagesize(self::local_path($row['hash']));
195 if ($width + $height) {
196 /* limit maximum size */
197 if ($width > $max_dim) {
198 $height *= $max_dim / $width;
201 if ($height > $max_dim) {
202 $width *= $max_dim / $height;
205 $html .= "<br><a href='$url'><img src='$url' width='$width' border='0' height='$height'></a>";
210 $html .= "</ul></div>";