2 // +----------------------------------------------------------------------+
3 // | Anuko Time Tracker
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
6 // +----------------------------------------------------------------------+
7 // | LIBERAL FREEWARE LICENSE: This source code document may be used
8 // | by anyone for any purpose, and freely redistributed alone or in
9 // | combination with other software, provided that the license is obeyed.
11 // | There are only two ways to violate the license:
13 // | 1. To redistribute this code in source form, with the copyright
14 // | notice or license removed or altered. (Distributing in compiled
15 // | forms without embedded copyright notices is permitted).
17 // | 2. To redistribute modified versions of this code in *any* form
18 // | that bears insufficient indications that the modifications are
19 // | not the work of the original author(s).
21 // | This license applies to this document only, not any other software
22 // | that it may be combined with.
24 // +----------------------------------------------------------------------+
26 // | https://www.anuko.com/time_tracker/credits.htm
27 // +----------------------------------------------------------------------+
29 // ttFileHelper class is used for attachment handling.
31 var $errors = null; // Errors go here. Set in constructor by reference.
32 var $storage_uri = null; // Location of file storage facility.
33 var $register_uri = null; // URI to register with file storage facility.
34 var $putfile_uri = null; // URI to put file in file storage.
35 var $getfile_uri = null; // URI to get file from file storage.
36 var $site_id = null; // Site id for file storage.
37 var $site_key = null; // Site key for file storage.
38 var $file_data = null; // Downloaded file data.
41 function __construct(&$errors) {
42 $this->errors = &$errors;
44 if (defined('FILE_STORAGE_URI')) {
45 $this->storage_uri = FILE_STORAGE_URI;
46 $this->register_uri = $this->storage_uri.'register';
47 $this->putfile_uri = $this->storage_uri.'putfile';
48 $this->deletefile_uri = $this->storage_uri.'deletefile';
49 $this->getfile_uri = $this->storage_uri.'getfile';
50 $this->checkSiteRegistration();
54 // checkSiteRegistration - obtains site id and key from local database.
55 // If not found, it tries to register with file storage facility.
56 function checkSiteRegistration() {
59 $mdb2 = getConnection();
62 $sql = "select param_value as id from tt_site_config where param_name = 'locker_id'";
63 $res = $mdb2->query($sql);
64 $val = $res->fetchRow();
66 // No site id found, need to register.
67 $fields = array('name' => urlencode('time tracker'),
68 'origin' => urlencode('time tracker source'));
70 // Urlify the data for the POST.
71 foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
72 $fields_string = rtrim($fields_string, '&');
77 // Set the url, number of POST vars, POST data.
78 curl_setopt($ch, CURLOPT_URL, $this->register_uri);
79 curl_setopt($ch, CURLOPT_POST, count($fields));
80 curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
81 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
83 // Execute a post request.
84 $result = curl_exec($ch);
89 $result_array = json_decode($result, true);
91 $this->errors->add($i18n->get('error.file_storage'));
93 else if ($result_array['error']) {
94 // Add an error from file storage facility if we have it.
95 $this->errors->add($result_array['error']);
97 else if ($result_array['id'] && $result_array['key']) {
98 $this->site_id = $result_array['id'];
99 $this->site_key = $result_array['key'];
101 // Registration successful. Store id and key locally for future use.
102 $sql = "insert into tt_site_config values('locker_id', $this->site_id, now(), null)";
104 $sql = "insert into tt_site_config values('locker_key', ".$mdb2->quote($this->site_key).", now(), null)";
107 $this->errors->add($i18n->get('error.file_storage'));
111 $this->site_id = $val['id'];
114 $sql = "select param_value as site_key from tt_site_config where param_name = 'locker_key'";
115 $res = $mdb2->query($sql);
116 $val = $res->fetchRow();
117 $this->site_key = $val['site_key'];
121 // putFile - puts uploaded file in remote storage.
122 function putFile($fields) {
125 $mdb2 = getConnection();
127 $group_id = $user->getGroup();
128 $org_id = $user->org_id;
130 $curl_fields = array('site_id' => urlencode($this->site_id),
131 'site_key' => urlencode($this->site_key),
132 'org_id' => urlencode($org_id),
133 'org_key' => urlencode($this->getOrgKey()),
134 'group_id' => urlencode($group_id),
135 'group_key' => urlencode($this->getGroupKey()),
136 'user_id' => urlencode($fields['user_id']), // May be null.
137 'user_key' => urlencode($fields['user_key']), // May be null.
138 'file_name' => urlencode($fields['file_name']),
139 'description' => urlencode($fields['description']),
140 'content' => urlencode(base64_encode(file_get_contents($_FILES['newfile']['tmp_name'])))
143 // url-ify the data for the POST.
144 foreach($curl_fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
145 $fields_string = rtrim($fields_string, '&');
150 // Set the url, number of POST vars, POST data.
151 curl_setopt($ch, CURLOPT_URL, $this->putfile_uri);
152 curl_setopt($ch, CURLOPT_POST, count($fields));
153 curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
154 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
156 // Execute a post request.
157 $result = curl_exec($ch);
162 // Delete uploaded file.
163 unlink($_FILES['newfile']['tmp_name']);
166 $this->errors->add($i18n->get('error.file_storage'));
170 $result_array = json_decode($result, true);
171 $file_id = (int) $result_array['file_id'];
172 $file_key = $result_array['file_key'];
173 $error = $result_array['error'];
175 if ($error || !$file_id || !$file_key) {
177 // Add an error from file storage facility if we have it.
178 $this->errors->add($error);
183 // File put was successful. Store file attributes locally.
184 $file_key = $mdb2->quote($file_key);
185 $entity_type = $mdb2->quote($fields['entity_type']);
186 $entity_id = (int) $fields['entity_id'];
187 $file_name = $mdb2->quote($fields['file_name']);
188 $description = $mdb2->quote($fields['description']);
190 $created_ip = $mdb2->quote($_SERVER['REMOTE_ADDR']);
191 $created_by = $user->id;
193 $columns = '(group_id, org_id, remote_id, file_key, entity_type, entity_id, file_name, description, created, created_ip, created_by)';
194 $values = "values($group_id, $org_id, $file_id, $file_key, $entity_type, $entity_id, $file_name, $description, $created, $created_ip, $created_by)";
195 $sql = "insert into tt_files $columns $values";
196 $affected = $mdb2->exec($sql);
197 return (!is_a($affected, 'PEAR_Error'));
200 // deleteFile - deletes a file from remote storage and its details from local database.
201 function deleteFile($fields) {
204 $mdb2 = getConnection();
206 $group_id = $user->getGroup();
207 $org_id = $user->org_id;
209 $curl_fields = array('site_id' => urlencode($this->site_id),
210 'site_key' => urlencode($this->site_key),
211 'org_id' => urlencode($org_id),
212 'org_key' => urlencode($this->getOrgKey()),
213 'group_id' => urlencode($group_id),
214 'group_key' => urlencode($this->getGroupKey()),
215 'user_id' => urlencode($fields['user_id']), // May be null.
216 'user_key' => urlencode($fields['user_key']), // May be null.
217 'file_id' => urlencode($fields['remote_id']),
218 'file_key' => urlencode($fields['file_key']),
219 'file_name' => urlencode($fields['file_name']));
221 // url-ify the data for the POST.
222 foreach($curl_fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
223 $fields_string = rtrim($fields_string, '&');
228 // Set the url, number of POST vars, POST data.
229 curl_setopt($ch, CURLOPT_URL, $this->deletefile_uri);
230 curl_setopt($ch, CURLOPT_POST, count($fields));
231 curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
232 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
234 // Execute a post request.
235 $result = curl_exec($ch);
241 $this->errors->add($i18n->get('error.file_storage'));
245 $result_array = json_decode($result, true);
246 $status = (int) $result_array['status'];
247 $error = $result_array['error'];
250 // Add an error from file storage facility if we have it.
251 $this->errors->add($error);
255 // There is no explicit error message, but still something not right.
256 $this->errors->add($i18n->get('error.file_storage'));
260 // Delete file reference from database.
261 $file_id = $fields['id'];
262 $sql = "delete from tt_files".
263 " where id = $file_id and org_id = $org_id and group_id = $group_id";
264 $affected = $mdb2->exec($sql);
265 if (is_a($affected, 'PEAR_Error')) {
266 $this->errors->add($i18n->get('error.db'));
270 // File successfully deleted from both file storage and database.
274 // getOrgKey obtains organization key from the database.
275 private function getOrgKey() {
277 $mdb2 = getConnection();
279 $org_id = $user->org_id;
280 $sql = "select group_key from tt_groups where id = $org_id and status = 1";
281 $res = $mdb2->query($sql);
282 $val = $res->fetchRow();
283 return $val['group_key'];
286 // getGrtoupKey obtains group key from the database.
287 private function getGroupKey() {
289 $mdb2 = getConnection();
291 $group_id = $user->getGroup();
292 $org_id = $user->org_id;
294 $sql = "select group_key from tt_groups where id = $group_id and org_id = $org_id and status = 1";
295 $res = $mdb2->query($sql);
296 $val = $res->fetchRow();
297 return $val['group_key'];
300 // getProjectFiles obtains a list of files for a project.
301 static function getProjectFiles($project_id) {
303 $mdb2 = getConnection();
305 $group_id = $user->getGroup();
306 $org_id = $user->org_id;
309 $sql = "select id, remote_id, file_name as name, description from tt_files".
310 " where entity_type = 'project' and entity_id = $project_id".
311 " and group_id = $group_id and org_id = $org_id and status = 1 order by id";
312 $res = $mdb2->query($sql);
313 if (!is_a($res, 'PEAR_Error')) {
314 while ($val = $res->fetchRow()) {
321 // get - obtains file details from local database.
322 static function get($id) {
324 $mdb2 = getConnection();
326 $group_id = $user->getGroup();
327 $org_id = $user->org_id;
329 $sql = "select id, remote_id, file_key, entity_type, entity_id, file_name, description, status from tt_files".
330 " where id = $id and group_id = $group_id and org_id = $org_id and (status = 0 or status = 1)";
331 $res = $mdb2->query($sql);
332 if (!is_a($res, 'PEAR_Error')) {
333 $val = $res->fetchRow();
334 if ($val && $val['id'])
340 // update - updates file details in local database.
341 static function update($fields) {
343 $mdb2 = getConnection();
345 $group_id = $user->getGroup();
346 $org_id = $user->org_id;
348 $file_id = (int) $fields['id'];
349 $description = $mdb2->quote($fields['description']);
351 $sql = "update tt_files set description = $description where id = $file_id".
352 " and group_id = $group_id and org_id = $org_id and (status = 0 or status = 1)";
353 $affected = $mdb2->exec($sql);
354 return !is_a($affected, 'PEAR_Error');
358 // getFile - downloads file from remote storage to memory.
359 function getFile($fields) {
362 $mdb2 = getConnection();
364 $group_id = $user->getGroup();
365 $org_id = $user->org_id;
367 $curl_fields = array('site_id' => urlencode($this->site_id),
368 'site_key' => urlencode($this->site_key),
369 'org_id' => urlencode($org_id),
370 'org_key' => urlencode($this->getOrgKey()),
371 'group_id' => urlencode($group_id),
372 'group_key' => urlencode($this->getGroupKey()),
373 'user_id' => urlencode($fields['user_id']), // May be null.
374 'user_key' => urlencode($fields['user_key']), // May be null.
375 'file_id' => urlencode($fields['remote_id']),
376 'file_key' => urlencode($fields['file_key']),
377 'file_name' => urlencode($fields['file_name']));
379 // url-ify the data for the POST.
380 foreach($curl_fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
381 $fields_string = rtrim($fields_string, '&');
386 // Set the url, number of POST vars, POST data.
387 curl_setopt($ch, CURLOPT_URL, $this->getfile_uri);
388 curl_setopt($ch, CURLOPT_POST, count($fields));
389 curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
390 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
392 // Execute a post request.
393 $result = curl_exec($ch);
395 $error = curl_error();
396 $result_array2 = json_decode($result, true);
402 $this->errors->add($i18n->get('error.file_storage'));
406 $result_array = json_decode($result, true);
407 $status = (int) $result_array['status'];
408 $error = $result_array['error'];
411 // Add an error from file storage facility if we have it.
412 $this->errors->add($error);
416 // There is no explicit error message, but still something not right.
417 $this->errors->add($i18n->get('error.file_storage'));
421 $this->file_data = $result_array['content'];
426 // getFileData - returns file data from memory.
427 function getFileData() {
428 return base64_decode($this->file_data);