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 // getEntityFiles obtains a list of files for an entity.
301 static function getEntityFiles($id, $type) {
303 $mdb2 = getConnection();
305 $group_id = $user->getGroup();
306 $org_id = $user->org_id;
309 $entity_type = $mdb2->quote($type);
310 $sql = "select id, remote_id, file_name as name, description from tt_files".
311 " where entity_type = $entity_type and entity_id = $id".
312 " and group_id = $group_id and org_id = $org_id and status = 1 order by id";
313 $res = $mdb2->query($sql);
314 if (!is_a($res, 'PEAR_Error')) {
315 while ($val = $res->fetchRow()) {
322 // get - obtains file details from local database.
323 static function get($id) {
325 $mdb2 = getConnection();
327 $group_id = $user->getGroup();
328 $org_id = $user->org_id;
330 $sql = "select id, remote_id, file_key, entity_type, entity_id, file_name, description, status from tt_files".
331 " where id = $id and group_id = $group_id and org_id = $org_id and (status = 0 or status = 1)";
332 $res = $mdb2->query($sql);
333 if (!is_a($res, 'PEAR_Error')) {
334 $val = $res->fetchRow();
335 if ($val && $val['id'])
341 // update - updates file details in local database.
342 static function update($fields) {
344 $mdb2 = getConnection();
346 $group_id = $user->getGroup();
347 $org_id = $user->org_id;
349 $file_id = (int) $fields['id'];
350 $description = $mdb2->quote($fields['description']);
352 $sql = "update tt_files set description = $description where id = $file_id".
353 " and group_id = $group_id and org_id = $org_id and (status = 0 or status = 1)";
354 $affected = $mdb2->exec($sql);
355 return !is_a($affected, 'PEAR_Error');
359 // getFile - downloads file from remote storage to memory.
360 function getFile($fields) {
363 $mdb2 = getConnection();
365 $group_id = $user->getGroup();
366 $org_id = $user->org_id;
368 $curl_fields = array('site_id' => urlencode($this->site_id),
369 'site_key' => urlencode($this->site_key),
370 'org_id' => urlencode($org_id),
371 'org_key' => urlencode($this->getOrgKey()),
372 'group_id' => urlencode($group_id),
373 'group_key' => urlencode($this->getGroupKey()),
374 'user_id' => urlencode($fields['user_id']), // May be null.
375 'user_key' => urlencode($fields['user_key']), // May be null.
376 'file_id' => urlencode($fields['remote_id']),
377 'file_key' => urlencode($fields['file_key']),
378 'file_name' => urlencode($fields['file_name']));
380 // url-ify the data for the POST.
381 foreach($curl_fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
382 $fields_string = rtrim($fields_string, '&');
387 // Set the url, number of POST vars, POST data.
388 curl_setopt($ch, CURLOPT_URL, $this->getfile_uri);
389 curl_setopt($ch, CURLOPT_POST, count($fields));
390 curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
391 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
393 // Execute a post request.
394 $result = curl_exec($ch);
396 $error = curl_error();
397 $result_array2 = json_decode($result, true);
403 $this->errors->add($i18n->get('error.file_storage'));
407 $result_array = json_decode($result, true);
408 $status = (int) $result_array['status'];
409 $error = $result_array['error'];
412 // Add an error from file storage facility if we have it.
413 $this->errors->add($error);
417 // There is no explicit error message, but still something not right.
418 $this->errors->add($i18n->get('error.file_storage'));
422 $this->file_data = $result_array['content'];
427 // getFileData - returns file data from memory.
428 function getFileData() {
429 return base64_decode($this->file_data);