diff options
Diffstat (limited to 'include/attach.php')
-rw-r--r-- | include/attach.php | 650 |
1 files changed, 565 insertions, 85 deletions
diff --git a/include/attach.php b/include/attach.php index c16944601..f95feed2d 100644 --- a/include/attach.php +++ b/include/attach.php @@ -150,10 +150,11 @@ function attach_count_files($channel_id, $observer, $hash = '', $filename = '', if($filetype) $sql_extra .= protect_sprintf(" and filetype like '@" . dbesc($filetype) . "@' "); - $r = q("select id from attach where uid = %d $sql_extra", + $r = q("select id, uid, folder from attach where uid = %d $sql_extra", intval($channel_id) ); + $ret['success'] = ((is_array($r)) ? true : false); $ret['results'] = ((is_array($r)) ? count($r) : false); @@ -202,7 +203,7 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $ // Retrieve all columns except 'data' - $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d $sql_extra ORDER BY $orderby $limit", + $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, os_storage, is_dir, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d $sql_extra ORDER BY $orderby $limit", intval($channel_id) ); @@ -262,12 +263,40 @@ function attach_by_hash($hash, $rev = 0) { return $ret; } + if($r[0]['folder']) { + $x = attach_can_view_folder($r[0]['uid'],get_observer_hash(),$r[0]['folder']); + if(! $x) { + $ret['message'] = t('Permission denied.'); + return $ret; + } + } + $ret['success'] = true; $ret['data'] = $r[0]; return $ret; } +function attach_can_view_folder($uid,$ob_hash,$folder_hash) { + + $sql_extra = permissions_sql($uid,$ob_hash); + $hash = $folder_hash; + $result = false; + + do { + $r = q("select folder from attach where hash = '%s' and uid = %d $sql_extra", + dbesc($hash), + intval($uid) + ); + if(! $r) + return false; + $hash = $r[0]['folder']; + } + while($hash); + return true; +} + + /** * @brief Find an attachment by hash and revision. * @@ -310,7 +339,7 @@ function attach_by_hash_nodata($hash, $rev = 0) { // Now we'll see if we can access the attachment - $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_extra limit 1", + $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, is_dir, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_extra limit 1", intval($r[0]['uid']), dbesc($hash) ); @@ -320,6 +349,15 @@ function attach_by_hash_nodata($hash, $rev = 0) { return $ret; } + if($r[0]['folder']) { + $x = attach_can_view_folder($r[0]['uid'],get_observer_hash(),$r[0]['folder']); + if(! $x) { + $ret['message'] = t('Permission denied.'); + return $ret; + } + } + + $ret['success'] = true; $ret['data'] = $r[0]; @@ -340,17 +378,68 @@ function attach_by_hash_nodata($hash, $rev = 0) { * @param string $options (optional) one of update, replace, revision * @param array $arr (optional) associative array */ + +/** + * A lot going on in this function, and some of it is old cruft and some is new cruft + * and the entire thing probably needs to be refactored. It started out just storing + * files, before we had DAV. It was made extensible to do extra stuff like edit an + * existing file or optionally store a separate revision using $options to choose between different + * storage models. Along the way we moved from + * DB data storage to file system storage. + * Then DAV came along and used different upload methods depending on whether the + * file was stored as a DAV directory object or updated as a file object. One of these + * is essentially an update and the other is basically an upload, but doesn't use the traditional PHP + * upload workflow. + * Then came hubzilla and we tried to merge photo functionality with the file storage. Most of + * that integration occurs within this function. + * This required overlap with the old photo_upload stuff and photo albums were + * completely different concepts from directories which needed to be reconciled somehow. + * The old revision stuff is kind of orphaned currently. There's new revision stuff for photos + * which attaches (2) etc. onto the name, but doesn't integrate with the attach table revisioning. + * That's where it sits currently. I repeat it needs to be refactored, and this note is here + * for future explorers and those who may be doing that work to understand where it came + * from and got to be the monstrosity of tangled unrelated code that it currently is. + */ + function attach_store($channel, $observer_hash, $options = '', $arr = null) { + require_once('include/photos.php'); + + call_hooks('photo_upload_begin',$arr); + $ret = array('success' => false); $channel_id = $channel['channel_id']; $sql_options = ''; + $source = (($arr) ? $arr['source'] : ''); + $album = (($arr) ? $arr['album'] : ''); + $newalbum = (($arr) ? $arr['newalbum'] : ''); + $hash = (($arr && $arr['hash']) ? $arr['hash'] : null); + $upload_path = (($arr && $arr['directory']) ? $arr['directory'] : ''); + $visible = (($arr && $arr['visible']) ? $arr['visible'] : ''); + + $observer = array(); + + if($observer_hash) { + $x = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($observer_hash) + ); + if($x) + $observer = $x[0]; + } + + logger('arr: ' . print_r($arr,true)); - if(! perm_is_allowed($channel_id,get_observer_hash(), 'write_storage')) { + if(! perm_is_allowed($channel_id,$observer_hash, 'write_storage')) { $ret['message'] = t('Permission denied.'); return $ret; } + $str_group_allow = perms2str($arr['group_allow']); + $str_contact_allow = perms2str($arr['contact_allow']); + $str_group_deny = perms2str($arr['group_deny']); + $str_contact_deny = perms2str($arr['contact_deny']); + + // The 'update' option sets db values without uploading a new attachment // 'replace' replaces the existing uploaded data // 'revision' creates a new revision with new upload data @@ -358,23 +447,64 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { // revise or update must provide $arr['hash'] of the thing to revise/update - if($options !== 'update') { - if(! x($_FILES,'userfile')) { - $ret['message'] = t('No source file.'); - return $ret; + // By default remove $src when finished + + $remove_when_processed = true; + + if($options === 'import') { + $src = $arr['src']; + $filename = $arr['filename']; + $filesize = @filesize($src); + + $hash = $arr['resource_id']; + + if(array_key_exists('hash',$arr)) + $hash = $arr['hash']; + if(array_key_exists('type',$arr)) + $type = $arr['type']; + + if($arr['preserve_original']) + $remove_when_processed = false; + + // if importing a directory, just do it now and go home - we're done. + + if(array_key_exists('is_dir',$arr) && intval($arr['is_dir'])) { + $x = attach_mkdir($channel,$observer_hash,$arr); + if($x['message']) + logger('import_directory: ' . $x['message']); + return; } + } + elseif($options !== 'update') { + $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); + + call_hooks('photo_upload_file',$f); + call_hooks('attach_upload_file',$f); - $src = $_FILES['userfile']['tmp_name']; - $filename = basename($_FILES['userfile']['name']); - $filesize = intval($_FILES['userfile']['size']); + if (x($f,'src') && x($f,'filesize')) { + $src = $f['src']; + $filename = $f['filename']; + $filesize = $f['filesize']; + $type = $f['type']; + + } else { + + if(! x($_FILES,'userfile')) { + $ret['message'] = t('No source file.'); + return $ret; + } + + $src = $_FILES['userfile']['tmp_name']; + $filename = basename($_FILES['userfile']['name']); + $filesize = intval($_FILES['userfile']['size']); + } } $existing_size = 0; if($options === 'replace') { - /** @BUG $replace is undefined here */ $x = q("select id, hash, filesize from attach where id = %d and uid = %d limit 1", - intval($replace), + intval($arr['id']), intval($channel_id) ); if(! $x) { @@ -391,7 +521,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { if($options === 'update' && $arr && array_key_exists('revision',$arr)) $sql_options = " and revision = " . intval($arr['revision']) . " "; - $x = q("select id, aid, uid, filename, filetype, filesize, hash, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d $sql_options limit 1", + $x = q("select id, aid, uid, filename, filetype, filesize, hash, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d $sql_options limit 1", dbesc($arr['hash']), intval($channel_id) ); @@ -402,13 +532,139 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $hash = $x[0]['hash']; } + + + $def_extension = ''; + $is_photo = 0; + $gis = @getimagesize($src); + logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA); + if(($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) { + $is_photo = 1; + if($gis[2] === IMAGETYPE_GIF) + $def_extension = '.gif'; + if($gis[2] === IMAGETYPE_JPEG) + $def_extension = '.jpg'; + if($gis[2] === IMAGETYPE_PNG) + $def_extension = '.png'; + + } + + $pathname = ''; + + if($is_photo) { + if($newalbum) { + $pathname = filepath_macro($newalbum); + } + elseif(array_key_exists('folder',$arr)) { + $x = q("select filename from attach where hash = '%s' and uid = %d limit 1", + dbesc($arr['folder']), + intval($channel['channel_id']) + ); + if($x) + $pathname = $x[0]['filename']; + } + else { + $pathname = filepath_macro($album); + } + } + else { + $pathname = filepath_macro($upload_path); + } + + $darr = array('pathname' => $pathname); + + // if we need to create a directory, use the channel default permissions. + + $darr['allow_cid'] = $channel['allow_cid']; + $darr['allow_gid'] = $channel['allow_gid']; + $darr['deny_cid'] = $channel['deny_cid']; + $darr['deny_gid'] = $channel['deny_gid']; + + + $direct = null; + + if($pathname) { + $x = attach_mkdirp($channel, $observer_hash, $darr); + $folder_hash = (($x['success']) ? $x['data']['hash'] : ''); + $direct = (($x['success']) ? $x['data'] : null); + if((! $str_contact_allow) && (! $str_group_allow) && (! $str_contact_deny) && (! $str_group_deny)) { + $str_contact_allow = $x['data']['allow_cid']; + $str_group_allow = $x['data']['allow_gid']; + $str_contact_deny = $x['data']['deny_cid']; + $str_group_deny = $x['data']['deny_gid']; + } + } + else { + $folder_hash = ((($arr) && array_key_exists('folder',$arr)) ? $arr['folder'] : ''); + } + + if((! $options) || ($options === 'import')) { + + // A freshly uploaded file. Check for duplicate and resolve with the channel's overwrite settings. + + $r = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", + dbesc($filename), + dbesc($folder_hash) + ); + if($r) { + $overwrite = get_pconfig($channel_id,'system','overwrite_dup_files'); + if($overwrite) { + $options = 'replace'; + $existing_id = $x[0]['id']; + $existing_size = intval($x[0]['filesize']); + $hash = $x[0]['hash']; + } + else { + if(strpos($filename,'.') !== false) { + $basename = substr($filename,0,strrpos($filename,'.')); + $ext = substr($filename,strrpos($filename,'.')); + } + else { + $basename = $filename; + $ext = $def_extension; + } + + $r = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", + dbesc($basename . $ext), + dbesc($basename . '(%)' . $ext), + dbesc($folder_hash) + ); + + if($r) { + $x = 1; + + do { + $found = false; + foreach($r as $rr) { + if($rr['filename'] === $basename . '(' . $x . ')' . $ext) { + $found = true; + break; + } + } + if($found) + $x++; + } + while($found); + $filename = $basename . '(' . $x . ')' . $ext; + } + else + $filename = $basename . $ext; + } + } + } + + if(! $hash) + $hash = random_string(); + // Check storage limits if($options !== 'update') { $maxfilesize = get_config('system','maxfilesize'); if(($maxfilesize) && ($filesize > $maxfilesize)) { $ret['message'] = sprintf( t('File exceeds size limit of %d'), $maxfilesize); - @unlink($src); + if($remove_when_processed) + @unlink($src); + call_hooks('photo_upload_end',$ret); return $ret; } @@ -420,41 +676,70 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { ); if(($r) && (($r[0]['total'] + $filesize) > ($limit - $existing_size))) { $ret['message'] = upgrade_message(true) . sprintf(t("You have reached your limit of %1$.0f Mbytes attachment storage."), $limit / 1024000); - @unlink($src); + if($remove_when_processed) + @unlink($src); + + call_hooks('photo_upload_end',$ret); return $ret; } } - $mimetype = z_mime_content_type($filename); + $mimetype = ((isset($type) && $type) ? $type : z_mime_content_type($filename)); } - if(! isset($hash)) - $hash = random_string(); + $os_basepath = 'store/' . $channel['channel_address'] . '/' ; + $os_relpath = ''; - $created = datetime_convert(); + if($folder_hash) { + $curr = find_folder_hash_by_attach_hash($channel_id,$folder_hash,true); + if($curr) + $os_relpath .= $curr . '/'; + $os_relpath .= $folder_hash . '/'; + } + + $os_relpath .= $hash; + + if($src) + @file_put_contents($os_basepath . $os_relpath,@file_get_contents($src)); + + if(array_key_exists('created', $arr)) + $created = $arr['created']; + else + $created = datetime_convert(); + + if(array_key_exists('edited', $arr)) + $edited = $arr['edited']; + else + $edited = $created; if($options === 'replace') { - $r = q("update attach set filename = '%s', filetype = '%s', filesize = %d, data = '%s', edited = '%s' where id = %d and uid = %d", + $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', filesize = %d, os_storage = %d, is_photo = %d, data = '%s', edited = '%s' where id = %d and uid = %d", dbesc($filename), dbesc($mimetype), + dbesc($folder_hash), intval($filesize), - dbescbin(@file_get_contents($src)), + intval(1), + intval($is_photo), + dbesc($os_relpath), dbesc($created), intval($existing_id), intval($channel_id) ); } elseif($options === 'revise') { - $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", + $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($x[0]['aid']), intval($channel_id), dbesc($x[0]['hash']), - dbesc(get_observer_hash()), + dbesc($observer_hash), dbesc($filename), dbesc($mimetype), + dbesc($folder_hash), intval($filesize), intval($x[0]['revision'] + 1), - dbescbin(@file_get_contents($src)), + intval(1), + intval($is_photo), + dbesc($os_relpath), dbesc($created), dbesc($created), dbesc($x[0]['allow_cid']), @@ -464,11 +749,14 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { ); } elseif($options === 'update') { - $r = q("update attach set filename = '%s', filetype = '%s', edited = '%s', + $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where id = %d and uid = %d", dbesc((array_key_exists('filename',$arr)) ? $arr['filename'] : $x[0]['filename']), dbesc((array_key_exists('filetype',$arr)) ? $arr['filetype'] : $x[0]['filetype']), + dbesc(($folder_hash) ? $folder_hash : $x[0]['folder']), dbesc($created), + dbesc((array_key_exists('os_storage',$arr)) ? $arr['os_storage'] : $x[0]['os_storage']), + dbesc((array_key_exists('is_photo',$arr)) ? $arr['is_photo'] : $x[0]['is_photo']), dbesc((array_key_exists('allow_cid',$arr)) ? $arr['allow_cid'] : $x[0]['allow_cid']), dbesc((array_key_exists('allow_gid',$arr)) ? $arr['allow_gid'] : $x[0]['allow_gid']), dbesc((array_key_exists('deny_cid',$arr)) ? $arr['deny_cid'] : $x[0]['deny_cid']), @@ -478,49 +766,90 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { ); } else { - $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", + + $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel_id), dbesc($hash), dbesc(get_observer_hash()), dbesc($filename), dbesc($mimetype), + dbesc($folder_hash), intval($filesize), intval(0), - dbescbin(@file_get_contents($src)), + intval(1), + intval($is_photo), + dbesc($os_relpath), dbesc($created), dbesc($created), - dbesc(($arr && array_key_exists('allow_cid',$arr)) ? $arr['allow_cid'] : '<' . $channel['channel_hash'] . '>'), - dbesc(($arr && array_key_exists('allow_gid',$arr)) ? $arr['allow_gid'] : ''), - dbesc(($arr && array_key_exists('deny_cid',$arr)) ? $arr['deny_cid'] : ''), - dbesc(($arr && array_key_exists('deny_gid',$arr)) ? $arr['deny_gid'] : '') + dbesc(($arr && array_key_exists('allow_cid',$arr)) ? $arr['allow_cid'] : $str_contact_allow), + dbesc(($arr && array_key_exists('allow_gid',$arr)) ? $arr['allow_gid'] : $str_group_allow), + dbesc(($arr && array_key_exists('deny_cid',$arr)) ? $arr['deny_cid'] : $str_contact_deny), + dbesc(($arr && array_key_exists('deny_gid',$arr)) ? $arr['deny_gid'] : $str_group_deny) ); } - if($options !== 'update') + if($is_photo) { + + $args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct); + if($arr['contact_allow']) + $args['contact_allow'] = $arr['contact_allow']; + if($arr['group_allow']) + $args['group_allow'] = $arr['group_allow']; + if($arr['contact_deny']) + $args['contact_deny'] = $arr['contact_deny']; + if($arr['group_deny']) + $args['group_deny'] = $arr['group_deny']; + if(array_key_exists('allow_cid',$arr)) + $args['allow_cid'] = $arr['allow_cid']; + if(array_key_exists('allow_gid',$arr)) + $args['allow_gid'] = $arr['allow_gid']; + if(array_key_exists('deny_cid',$arr)) + $args['deny_cid'] = $arr['deny_cid']; + if(array_key_exists('deny_gid',$arr)) + $args['deny_gid'] = $arr['deny_gid']; + + $args['created'] = $created; + $args['edited'] = $edited; + if($arr['item']) + $args['item'] = $arr['item']; + + $p = photo_upload($channel,$observer,$args); + if($p['success']) { + $ret['body'] = $p['body']; + } + } + + if(($options !== 'update') && ($remove_when_processed)) @unlink($src); if(! $r) { $ret['message'] = t('File upload failed. Possible system limit or action terminated.'); + call_hooks('photo_upload_end',$ret); return $ret; } // Caution: This re-uses $sql_options set further above - $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_options limit 1", + $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_options limit 1", intval($channel_id), dbesc($hash) ); if(! $r) { $ret['message'] = t('Stored file could not be verified. Upload failed.'); + call_hooks('photo_upload_end',$ret); return $ret; } + $ret['success'] = true; $ret['data'] = $r[0]; - + if(! $is_photo) { + // This would've been called already with a success result in photos_upload() if it was a photo. + call_hooks('photo_upload_end',$ret); + } return $ret; } @@ -552,10 +881,9 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { if(count($paths) > 1) { $curpath = array_shift($paths); - $r = q("select hash, id from attach where uid = %d and filename = '%s' and (flags & %d )>0 " . permissions_sql($channel_id) . " limit 1", + $r = q("select hash, id, is_dir from attach where uid = %d and filename = '%s' and is_dir != 0 " . permissions_sql($channel_id) . " limit 1", intval($channel_id), - dbesc($curpath), - intval(ATTACH_FLAG_DIR) + dbesc($curpath) ); if(! $r) { $ret['message'] = t('Path not available.'); @@ -568,11 +896,10 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { else $paths = array($pathname); - $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and folder = '%s' and filename = '%s' and (flags & %d )>0 " . permissions_sql($channel_id), + $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, is_photo, is_dir, os_storage, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and folder = '%s' and filename = '%s' and is_dir != 0 " . permissions_sql($channel_id), intval($channel_id), dbesc($parent_hash), - dbesc($paths[0]), - intval(ATTACH_FLAG_DIR) + dbesc($paths[0]) ); if(! $r) { $ret['message'] = t('Path not available.'); @@ -594,7 +921,7 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { * * \e string \b filename * * \e string \b folder hash of parent directory, empty string for root directory * - Optional: - * * \e string \b hash precumputed hash for this node + * * \e string \b hash precomputed hash for this node * * \e tring \b allow_cid * * \e string \b allow_gid * * \e string \b deny_cid @@ -605,6 +932,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $ret = array('success' => false); $channel_id = $channel['channel_id']; + $sql_options = ''; $basepath = 'store/' . $channel['channel_address']; @@ -629,13 +957,23 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { // Check for duplicate name. // Check both the filename and the hash as we will be making use of both. - $r = q("select hash from attach where ( filename = '%s' or hash = '%s' ) and folder = '%s' and uid = %d limit 1", + $r = q("select id, hash, is_dir, flags from attach where ( filename = '%s' or hash = '%s' ) and folder = '%s' and uid = %d limit 1", dbesc($arr['filename']), dbesc($arr['hash']), dbesc($arr['folder']), intval($channel['channel_id']) ); if($r) { + if(array_key_exists('force',$arr) && intval($arr['force']) + && (intval($r[0]['is_dir']))) { + $ret['success'] = true; + $r = q("select * from attach where id = %d limit 1", + intval($r[0]['id']) + ); + if($r) + $ret['data'] = $r[0]; + return $ret; + } $ret['message'] = t('duplicate filename or path'); return $ret; } @@ -651,13 +989,11 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $sql_options = permissions_sql($channel['channel_id']); do { - $r = q("select filename, hash, flags, folder from attach where uid = %d and hash = '%s' and ( flags & %d )>0 + $r = q("select filename, hash, flags, is_dir, folder from attach where uid = %d and hash = '%s' and is_dir != 0 $sql_options limit 1", intval($channel['channel_id']), - dbesc($lfile), - intval(ATTACH_FLAG_DIR) + dbesc($lfile) ); - if(! $r) { logger('attach_mkdir: hash ' . $lfile . ' not found in ' . $lpath); $ret['message'] = t('Path not found.'); @@ -666,7 +1002,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { if($lfile) $lpath = $r[0]['hash'] . '/' . $lpath; $lfile = $r[0]['folder']; - } while ( ($r[0]['folder']) && ($r[0]['flags'] & ATTACH_FLAG_DIR)) ; + } while ( ($r[0]['folder']) && intval($r[0]['is_dir'])) ; $path = $basepath . '/' . $lpath; } else @@ -676,8 +1012,8 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $created = datetime_convert(); - $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", + $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_dir, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel_id), dbesc($arr['hash']), @@ -687,7 +1023,8 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { intval(0), intval(0), dbesc($arr['folder']), - intval(ATTACH_FLAG_DIR|ATTACH_FLAG_OS), + intval(1), + intval(1), dbesc($path), dbesc($created), dbesc($created), @@ -700,7 +1037,6 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { if($r) { if(os_mkdir($path, STORAGE_DEFAULT_PERMISSIONS, true)) { $ret['success'] = true; - $ret['data'] = $arr; // update the parent folder's lastmodified timestamp $e = q("UPDATE attach SET edited = '%s' WHERE hash = '%s' AND uid = %d", @@ -708,6 +1044,13 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { dbesc($arr['folder']), intval($channel_id) ); + + $z = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1", + dbesc($arr['hash']), + intval($channel_id) + ); + if($z) + $ret['data'] = $z[0]; } else { logger('attach_mkdir: ' . mkdir . ' ' . $path . ' failed.'); @@ -722,6 +1065,95 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { } /** + * @brief Create directory (recursive). + * + * @param array $channel channel array of owner + * @param string $observer_hash hash of current observer + * @param array $arr parameter array to fulfil request + * - Required: + * * \e string \b pathname + * * \e string \b folder hash of parent directory, empty string for root directory + * - Optional: + * * \e string \b allow_cid + * * \e string \b allow_gid + * * \e string \b deny_cid + * * \e string \b deny_gid + * @return array + */ +function attach_mkdirp($channel, $observer_hash, $arr = null) { + + $ret = array('success' => false); + $channel_id = $channel['channel_id']; + + $sql_options = ''; + + $basepath = 'store/' . $channel['channel_address']; + + logger('attach_mkdirp: basepath: ' . $basepath); + + if(! is_dir($basepath)) + os_mkdir($basepath,STORAGE_DEFAULT_PERMISSIONS, true); + + if(! perm_is_allowed($channel_id, $observer_hash, 'write_storage')) { + $ret['message'] = t('Permission denied.'); + return $ret; + } + + if(! $arr['pathname']) { + $ret['message'] = t('Empty pathname'); + return $ret; + } + + $paths = explode('/',$arr['pathname']); + if(! $paths) { + $ret['message'] = t('Empty path'); + return $ret; + } + + $current_parent = ''; + + foreach($paths as $p) { + if(! $p) + continue; + $arx = array( + 'filename' => $p, + 'folder' => $current_parent, + 'force' => 1 + ); + if(array_key_exists('allow_cid',$arr)) + $arx['allow_cid'] = $arr['allow_cid']; + if(array_key_exists('deny_cid',$arr)) + $arx['deny_cid'] = $arr['deny_cid']; + if(array_key_exists('allow_gid',$arr)) + $arx['allow_gid'] = $arr['allow_gid']; + if(array_key_exists('deny_gid',$arr)) + $arx['deny_gid'] = $arr['deny_gid']; + + $x = attach_mkdir($channel, $observer_hash, $arx); + if($x['success']) { + $current_parent = $x['data']['hash']; + } + else { + $ret['message'] = $x['message']; + return $ret; + } + } + if(isset($x)) { + $ret['success'] = true; + $ret['data'] = $x['data']; + } + + return $ret; + +} + + + + + + + +/** * @brief Changes permissions of a file. * * @param int $channel_id @@ -734,7 +1166,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { */ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) { - $r = q("select hash, flags from attach where hash = '%s' and uid = %d limit 1", + $r = q("select hash, flags, is_dir, is_photo from attach where hash = '%s' and uid = %d limit 1", dbesc($resource), intval($channel_id) ); @@ -742,9 +1174,9 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi if(! $r) return; - if($r[0]['flags'] & ATTACH_FLAG_DIR) { + if(intval($r[0]['is_dir'])) { if($recurse) { - $r = q("select hash, flags from attach where folder = '%s' and uid = %d", + $r = q("select hash, flags, is_dir from attach where folder = '%s' and uid = %d", dbesc($resource), intval($channel_id) ); @@ -764,6 +1196,16 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi dbesc($resource), intval($channel_id) ); + if($r[0]['is_photo']) { + $x = q("update photo set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where resource_id = '%s' and uid = %d", + dbesc($allow_cid), + dbesc($allow_gid), + dbesc($deny_cid), + dbesc($deny_gid), + dbesc($resource), + intval($channel_id) + ); + } } /** @@ -778,15 +1220,16 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi * The hash to delete * @return void */ -function attach_delete($channel_id, $resource) { +function attach_delete($channel_id, $resource, $is_photo = 0) { $c = q("SELECT channel_address FROM channel WHERE channel_id = %d LIMIT 1", intval($channel_id) ); $channel_address = (($c) ? $c[0]['channel_address'] : 'notfound'); + $photo_sql = (($is_photo) ? " and is_photo = 1 " : ''); - $r = q("SELECT hash, flags, folder FROM attach WHERE hash = '%s' AND uid = %d limit 1", + $r = q("SELECT hash, flags, is_dir, is_photo, folder FROM attach WHERE hash = '%s' AND uid = %d $photo_sql limit 1", dbesc($resource), intval($channel_id) ); @@ -798,8 +1241,8 @@ function attach_delete($channel_id, $resource) { $object = get_file_activity_object($channel_id, $resource, $cloudpath); // If resource is a directory delete everything in the directory recursive - if($r[0]['flags'] & ATTACH_FLAG_DIR) { - $x = q("SELECT hash, flags FROM attach WHERE folder = '%s' AND uid = %d", + if(intval($r[0]['is_dir'])) { + $x = q("SELECT hash, os_storage, is_dir, flags FROM attach WHERE folder = '%s' AND uid = %d", dbesc($resource), intval($channel_id) ); @@ -811,7 +1254,7 @@ function attach_delete($channel_id, $resource) { } // delete a file from filesystem - if($r[0]['flags'] & ATTACH_FLAG_OS) { + if(intval($r[0]['os_storage'])) { $y = q("SELECT data FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1", dbesc($resource), intval($channel_id) @@ -832,6 +1275,21 @@ function attach_delete($channel_id, $resource) { intval($channel_id) ); + if($r[0]['is_photo']) { + $x = q("select id, item_hidden from item where resource_id = '%s' and resource_type = 'photo' and uid = %d", + dbesc($resource), + intval($channel_id) + ); + if($x) { + drop_item($x[0]['id'],false,(($x[0]['item_hidden']) ? DROPITEM_NORMAL : DROPITEM_PHASE1),true); + + q("DELETE FROM photo WHERE uid = %d AND resource_id = '%s'", + intval($channel_id), + dbesc($resource) + ); + } + } + // update the parent folder's lastmodified timestamp $e = q("UPDATE attach SET edited = '%s' WHERE hash = '%s' AND uid = %d", dbesc(datetime_convert()), @@ -873,11 +1331,10 @@ function get_cloudpath($arr) { $lfile = $arr['folder']; do { - $r = q("select filename, hash, flags, folder from attach where uid = %d and hash = '%s' and ( flags & %d )>0 + $r = q("select filename, hash, flags, is_dir, folder from attach where uid = %d and hash = '%s' and is_dir != 0 limit 1", intval($arr['uid']), - dbesc($lfile), - intval(ATTACH_FLAG_DIR) + dbesc($lfile) ); if(! $r) @@ -887,7 +1344,7 @@ function get_cloudpath($arr) { $lpath = $r[0]['filename'] . '/' . $lpath; $lfile = $r[0]['folder']; - } while ( ($r[0]['folder']) && ($r[0]['flags'] & ATTACH_FLAG_DIR)); + } while ( ($r[0]['folder']) && intval($r[0]['is_dir'])); $path .= $lpath; } @@ -932,14 +1389,19 @@ function get_parent_cloudpath($channel_id, $channel_name, $attachHash) { * The hash of the attachment * @return string */ -function find_folder_hash_by_attach_hash($channel_id, $attachHash) { +function find_folder_hash_by_attach_hash($channel_id, $attachHash, $recurse = false) { + +logger('attach_hash: ' . $attachHash); $r = q("SELECT folder FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1", intval($channel_id), dbesc($attachHash) ); $hash = ''; - if ($r) { - $hash = $r[0]['folder']; + if($r && $r[0]['folder']) { + if($recurse) + $hash = find_folder_hash_by_attach_hash($channel_id,$r[0]['folder'],true) . '/' . $r[0]['folder']; + else + $hash = $r[0]['folder']; } return $hash; } @@ -1011,7 +1473,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, //filter out receivers which do not have permission to view filestorage $arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); - $is_dir = (($object['flags'] & ATTACH_FLAG_DIR) ? true : false); + $is_dir = (intval($object['is_dir']) ? true : false); //do not send activity for folders for now if($is_dir) @@ -1036,9 +1498,13 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $mid = item_message_id(); - $objtype = ACTIVITY_OBJ_FILE; + $arr = array(); - $item_flags = ITEM_WALL|ITEM_ORIGIN; + $arr['item_wall'] = 1; + $arr['item_origin'] = 1; + $arr['item_unseen'] = 1; + + $objtype = ACTIVITY_OBJ_FILE; $private = (($arr_allow_cid[0] || $arr_allow_gid[0] || $arr_deny_cid[0] || $arr_deny_gid[0]) ? 1 : 0); @@ -1077,23 +1543,20 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $u_mid = item_message_id(); - $arr = array(); - $arr['aid'] = get_account_id(); $arr['uid'] = $channel_id; $arr['mid'] = $u_mid; $arr['parent_mid'] = $u_mid; - $arr['item_flags'] = $item_flags; - $arr['item_unseen'] = 1; $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $poster['xchan_hash']; $arr['title'] = ''; - $arr['allow_cid'] = perms2str($u_arr_allow_cid); - $arr['allow_gid'] = perms2str($u_arr_allow_gid); - $arr['deny_cid'] = perms2str($u_arr_deny_cid); - $arr['deny_gid'] = perms2str($u_arr_deny_gid); - $arr['item_restrict'] = ITEM_HIDDEN; - $arr['item_private'] = $private; + //updates should be visible to everybody -> perms may have changed + $arr['allow_cid'] = ''; + $arr['allow_gid'] = ''; + $arr['deny_cid'] = ''; + $arr['deny_gid'] = ''; + $arr['item_hidden'] = 1; + $arr['item_private'] = 0; $arr['verb'] = ACTIVITY_UPDATE; $arr['obj_type'] = $objtype; $arr['object'] = $u_jsonobject; @@ -1124,7 +1587,8 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $arr['uid'] = $channel_id; $arr['mid'] = $mid; $arr['parent_mid'] = $mid; - $arr['item_flags'] = $item_flags; + $arr['item_wall'] = 1; + $arr['item_origin'] = 1; $arr['item_unseen'] = 1; $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $poster['xchan_hash']; @@ -1133,7 +1597,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $arr['allow_gid'] = perms2str($arr_allow_gid); $arr['deny_cid'] = perms2str($arr_deny_cid); $arr['deny_gid'] = perms2str($arr_deny_gid); - $arr['item_restrict'] = ITEM_HIDDEN; + $arr['item_hidden'] = 1; $arr['item_private'] = $private; $arr['verb'] = (($update) ? ACTIVITY_UPDATE : ACTIVITY_POST); $arr['obj_type'] = $objtype; @@ -1165,7 +1629,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, */ function get_file_activity_object($channel_id, $hash, $cloudpath) { - $x = q("SELECT creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1", + $x = q("SELECT creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, is_dir, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1", intval($channel_id), dbesc($hash) ); @@ -1193,6 +1657,9 @@ function get_file_activity_object($channel_id, $hash, $cloudpath) { 'revision' => $x[0]['revision'], 'folder' => $x[0]['folder'], 'flags' => $x[0]['flags'], + 'os_storage' => $x[0]['os_storage'], + 'is_photo' => $x[0]['is_photo'], + 'is_dir' => $x[0]['is_dir'], 'created' => $x[0]['created'], 'edited' => $x[0]['edited'], 'allow_cid' => $x[0]['allow_cid'], @@ -1348,3 +1815,16 @@ function in_group($group_id) { return $group_members; } + + +function filepath_macro($s) { + + return str_replace( + array( '%Y', '%m', '%d' ), + array( datetime_convert('UTC',date_default_timezone_get(),'now', 'Y'), + datetime_convert('UTC',date_default_timezone_get(),'now', 'm'), + datetime_convert('UTC',date_default_timezone_get(),'now', 'd') + ), $s); + +} + |