diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/attach.php | 290 | ||||
-rw-r--r-- | include/connections.php | 41 | ||||
-rw-r--r-- | include/contact_widgets.php | 36 | ||||
-rw-r--r-- | include/feedutils.php | 11 | ||||
-rwxr-xr-x | include/items.php | 5 | ||||
-rw-r--r-- | include/text.php | 28 |
6 files changed, 341 insertions, 70 deletions
diff --git a/include/attach.php b/include/attach.php index c9649a4ce..69ccceaf6 100644 --- a/include/attach.php +++ b/include/attach.php @@ -647,12 +647,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $pathname = filepath_macro($newalbum); } elseif(array_key_exists('folder',$arr)) { - $x = q("select filename from attach where hash = '%s' and uid = %d limit 1", + $x = q("select display_path from attach where hash = '%s' and uid = %d limit 1", dbesc($arr['folder']), intval($channel['channel_id']) ); if($x) - $pathname = $x[0]['filename']; + $pathname = $x[0]['display_path']; } else { $pathname = filepath_macro($album); @@ -1534,7 +1534,7 @@ function attach_drop_photo($channel_id,$resource) { $interactive = (($x[0]['item_hidden']) ? false : true); drop_item($x[0]['id'], $interactive, $stage); } - + $r = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1", dbesc($resource), intval($channel_id) @@ -1544,7 +1544,7 @@ function attach_drop_photo($channel_id,$resource) { @unlink(dbunescbin($i['content'])); } } - + q("DELETE FROM photo WHERE uid = %d AND resource_id = '%s'", intval($channel_id), dbesc($resource) @@ -2495,7 +2495,7 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat return true; } /** - * This function performs an in place directory-to-directory move of a stored attachment or photo. + * This function performs an in place directory-to-directory move of a stored resource. * The data is physically moved in the store/nickname storage location and the paths adjusted * in the attach structure (and if applicable the photo table). The new 'album name' is recorded * for photos and will show up immediately there. @@ -2507,60 +2507,64 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat * @param int $channel_id * @param int $resource_id * @param string $new_folder_hash - * @return void|boolean + * @param (optional) string $newname + * @param (optional) boolean $recurse + * @return array Associative array with: + * * \e boolean \b success + * * \e string \b resource_id */ -function attach_move($channel_id, $resource_id, $new_folder_hash) { +function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '', $recurse = true) { + + $ret = [ + 'success' => false, + 'resource_id' => $resource_id + ]; $c = channelx_by_n($channel_id); if(! ($c && $resource_id)) - return false; - + return $ret; // find the resource to be moved - $r = q("select * from attach where hash = '%s' and uid = %d limit 1", dbesc($resource_id), intval($channel_id) ); if(! $r) { logger('resource_id not found'); - return false; + return $ret; } $oldstorepath = dbunescbin($r[0]['content']); - // find the resource we are moving to - if($new_folder_hash) { $n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1", dbesc($new_folder_hash), intval($channel_id) ); if(! $n) - return false; + return $ret; + $newdirname = $n[0]['filename']; $newalbumname = $n[0]['display_path']; $newstorepath = dbunescbin($n[0]['content']) . '/' . $resource_id; } else { - // root directory - + $newdirname = EMPTY_STR; $newalbumname = EMPTY_STR; $newstorepath = 'store/' . $c['channel_address'] . '/' . $resource_id; } - rename($oldstorepath,$newstorepath); - - // duplicate detection. If 'overwrite' is specified, return false because we can't yet do that. - - $filename = $r[0]['filename']; - - // don't do duplicate check unless our parent folder has changed. + if ($recurse) { + rename($oldstorepath,$newstorepath); + } - if($r[0]['folder'] !== $new_folder_hash) { + $oldfilename = $r[0]['filename']; + $filename = (($newname) ? basename($newname) : $oldfilename); + // duplicate detection. + if($recurse) { $s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", dbesc($filename), dbesc($new_folder_hash) @@ -2568,9 +2572,10 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { if($s) { $overwrite = get_pconfig($channel_id,'system','overwrite_dup_files'); + // If 'overwrite' is specified, return false because we can't yet do that. if($overwrite) { /// @fixme - return; + return $ret; } else { if(strpos($filename,'.') !== false) { @@ -2586,7 +2591,8 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { if(preg_match('/(.*?)\([0-9]{1,}\)$/',$basename,$matches)) $basename = $matches[1]; - $v = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", + $v = q("select filename from attach where uid = %d and ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", + intval($channel_id), dbesc($basename . $ext), dbesc($basename . '(%)' . $ext), dbesc($new_folder_hash) @@ -2609,12 +2615,14 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { while($found); $filename = $basename . '(' . $x . ')' . $ext; } - else + else { $filename = $basename . $ext; + } } } } + q("update attach set content = '%s', folder = '%s', filename = '%s' where id = %d", dbescbin($newstorepath), dbesc($new_folder_hash), @@ -2631,7 +2639,6 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { intval($r[0]['id']) ); - if($r[0]['is_photo']) { q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s' where resource_id = '%s' and uid = %d", @@ -2643,11 +2650,24 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { intval($channel_id) ); - q("update photo set content = '%s' where resource_id = '%s' and uid = %d and imgscale = 0", + q("update photo set content = CASE imgscale WHEN 0 THEN '%s' ELSE CONCAT('%s', '-', imgscale) END where resource_id = '%s' and uid = %d and os_storage = 1", + dbescbin($newstorepath), dbescbin($newstorepath), dbesc($resource_id), intval($channel_id) ); + + // now rename the thumbnails in os_storage - the original should have been copied before already + $ps = q("SELECT content, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and imgscale > 0 and os_storage = 1", + intval($channel_id), + dbesc($resource_id) + ); + + if ($recurse) { + foreach($ps as $p) { + rename($oldstorepath . '-' . $p['imgscale'], $p['content']); + } + } } if($r[0]['is_dir']) { @@ -2658,19 +2678,223 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { ); if($x) { foreach($x as $xv) { - $rs = attach_move($channel_id,$xv['hash'],$r[0]['hash']); - if(! $rs) { + $rs = attach_move($channel_id, $xv['hash'], $r[0]['hash'], '', false); + if(! $rs['success']) { $move_success = false; break; } } } - return $move_success; + + $ret['success'] = $move_success; + return $ret; } - return true; + $ret['success'] = true; + return $ret; } +/** + * This function performs an in place directory-to-directory copy of a stored resource. + * The data is physically copyed in the store/nickname storage location and the paths adjusted + * in the attach structure (and if applicable the photo table). The new 'album name' is recorded + * for photos and will show up immediately there. + * This takes a channel_id, attach.hash of the file to copy (this is the same as a photo resource_id), and + * the attach.hash of the new parent folder, which must already exist. If $new_folder_hash is blank or empty, + * the new file is copyed to the root of the channel's storage area. + * + * + * @param int $channel_id + * @param int $resource_id + * @param string $new_folder_hash + * @param (optional) string $newname + * @param (optional) boolean $recurse + * @return array Associative array with: + * * \e boolean \b success + * * \e string \b resource_id of the new resource + */ +function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '', $recurse = true) { + + $ret = [ + 'success' => false, + 'resource_id' => '' + ]; + + $c = channelx_by_n($channel_id); + if(! ($c && $resource_id)) + return $ret; + + // find the resource to be copied + $r = q("select * from attach where hash = '%s' and uid = %d limit 1", + dbesc($resource_id), + intval($channel_id) + ); + if(! $r) { + logger('resource_id not found'); + return $ret; + } + + $a = $r[0]; + $new_resource_id = new_uuid(); + + $ret['resource_id'] = $new_resource_id; + + $oldstorepath = dbunescbin($r[0]['content']); + + // find the resource we are copying to + if($new_folder_hash) { + $n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1", + dbesc($new_folder_hash), + intval($channel_id) + ); + if(! $n) { + logger('new_folder_hash not found'); + return $ret; + } + + $newdirname = $n[0]['filename']; + $newalbumname = $n[0]['display_path']; + $newstorepath = dbunescbin($n[0]['content']) . '/' . $new_resource_id; + } + else { + // root directory + $newdirname = EMPTY_STR; + $newalbumname = EMPTY_STR; + $newstorepath = 'store/' . $c['channel_address'] . '/' . $new_resource_id; + } + + if(is_dir($oldstorepath)) { + os_mkdir($newstorepath,STORAGE_DEFAULT_PERMISSIONS,true); + } + else { + copy($oldstorepath,$newstorepath); + } + + $oldfilename = $r[0]['filename']; + $filename = (($newname) ? basename($newname) : $oldfilename); + + // duplicate detection. If 'overwrite' is specified, return false because we can't yet do that. + if($recurse) { + $s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", + dbesc($filename), + dbesc($new_folder_hash) + ); + + if($s) { + $overwrite = get_pconfig($channel_id,'system','overwrite_dup_files'); + if($overwrite) { + /// @fixme + return $ret; + } + else { + if(strpos($filename,'.') !== false) { + $basename = substr($filename,0,strrpos($filename,'.')); + $ext = substr($filename,strrpos($filename,'.')); + } + else { + $basename = $filename; + $ext = ''; + } + + $matches = false; + if(preg_match('/(.*?)\([0-9]{1,}\)$/',$basename,$matches)) + $basename = $matches[1]; + + $v = q("select filename from attach where uid = %d and ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", + intval($channel_id), + dbesc($basename . $ext), + dbesc($basename . '(%)' . $ext), + dbesc($new_folder_hash) + ); + + if($v) { + $x = 1; + + do { + $found = false; + foreach($v as $vv) { + if($vv['filename'] === $basename . '(' . $x . ')' . $ext) { + $found = true; + break; + } + } + if($found) + $x++; + } + while($found); + $filename = $basename . '(' . $x . ')' . $ext; + } + else { + $filename = $basename . $ext; + } + } + } + } + + unset($a['id']); + $a['hash'] = $new_resource_id; + $a['content'] = $newstorepath; + $a['folder'] = $new_folder_hash; + $a['filename'] = $filename; + + create_table_from_array('attach', $a, ['content']); + + $x = attach_syspaths($channel_id, $new_resource_id); + + q("update attach set os_path = '%s', display_path = '%s' where hash = '%s'", + dbesc($x['os_path']), + dbesc($x['path']), + dbesc($new_resource_id) + ); + + if($a['is_photo']) { + + $ps = q("SELECT * FROM photo WHERE uid = %d AND resource_id = '%s'", + intval($channel_id), + dbesc($resource_id) + ); + + foreach($ps as $p) { + unset($p['id']); + $p['resource_id'] = $new_resource_id; + $p['album'] = $newalbumname; + $p['filename'] = $filename; + $p['os_path'] = $x['os_path']; + $p['display_path'] = $x['path']; + if($p['os_storage']) { + $p['content'] = (($p['imgscale'] == 0) ? $newstorepath : $newstorepath . '-' . $p['imgscale']); + + //the original should have been copied before already + if($p['imgscale'] > 0) + copy($oldstorepath, $p['content']); + } + create_table_from_array('photo', $p, ['content']); + } + } + + if($r[0]['is_dir']) { + $copy_success = true; + $x = q("select hash from attach where folder = '%s' and uid = %d", + dbesc($r[0]['hash']), + intval($channel_id) + ); + if($x) { + foreach($x as $xv) { + $rs = attach_copy($channel_id,$xv['hash'],$new_resource_id, '', false); + if(! $rs['success']) { + $copy_success = false; + break; + } + } + } + + $ret['success'] = $copy_success; + return $ret; + } + + $ret['success'] = true; + return $ret; +} /** * Used to generate a select input box of all your folders diff --git a/include/connections.php b/include/connections.php index 658fb6ee6..100e595d0 100644 --- a/include/connections.php +++ b/include/connections.php @@ -71,7 +71,7 @@ function abook_connections($channel_id, $sql_conditions = '') { intval($channel_id) ); return(($r) ? $r : array()); -} +} function abook_self($channel_id) { $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d @@ -79,7 +79,7 @@ function abook_self($channel_id) { intval($channel_id) ); return(($r) ? $r[0] : array()); -} +} function vcard_from_xchan($xchan, $observer = null, $mode = '') { @@ -119,14 +119,15 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') { if(array_key_exists('channel_id',$xchan)) App::$profile_uid = $xchan['channel_id']; - $url = (($observer) - ? z_root() . '/magic?f=&owa=1&bdest=' . bin2hex($xchan['xchan_url']) . '&addr=' . $xchan['xchan_addr'] + $url = (($observer) + ? z_root() . '/magic?f=&owa=1&bdest=' . bin2hex($xchan['xchan_url']) . '&addr=' . $xchan['xchan_addr'] : $xchan['xchan_url'] ); - + return replace_macros(get_markup_template('xchan_vcard.tpl'),array( '$name' => $xchan['xchan_name'], - '$photo' => ((is_array(App::$profile) && array_key_exists('photo',App::$profile)) ? App::$profile['photo'] : $xchan['xchan_photo_l']), + '$addr' => (($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']), + '$photo' => $xchan['xchan_photo_m'], '$follow' => (($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']), '$link' => zid($xchan['xchan_url']), '$connect' => $connect, @@ -177,10 +178,10 @@ function abook_toggle_flag($abook,$flag) { ); - // if unsetting the archive bit, update the timestamps so we'll try to connect for an additional 30 days. + // if unsetting the archive bit, update the timestamps so we'll try to connect for an additional 30 days. if(($flag === ABOOK_FLAG_ARCHIVED) && (intval($abook['abook_archived']))) { - $r = q("update abook set abook_connected = '%s', abook_updated = '%s' + $r = q("update abook set abook_connected = '%s', abook_updated = '%s' where abook_id = %d and abook_channel = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), @@ -210,7 +211,7 @@ function mark_orphan_hubsxchans() { if($dirmode == DIRECTORY_MODE_NORMAL) return; - $r = q("update hubloc set hubloc_error = 1 where hubloc_error = 0 + $r = q("update hubloc set hubloc_error = 1 where hubloc_error = 0 and hubloc_network = 'zot' and hubloc_connected < %s - interval %s", db_utcnow(), db_quoteinterval('36 day') ); @@ -301,9 +302,9 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) { ); // Cannot delete just one side of the conversation since we do not allow - // you to block private mail replies. This would leave open a gateway for abuse. + // you to block private mail replies. This would leave open a gateway for abuse. // Both participants are owners of the conversation and both can remove it. - + $r = q("delete from mail where ( from_xchan = '%s' or to_xchan = '%s' )", dbesc($xchan), dbesc($xchan) @@ -387,7 +388,7 @@ function contact_remove($channel_id, $abook_id) { $already_saved = []; foreach($r as $rr) { $w = $x = $y = null; - + // optimise so we only process newly seen parent items if (in_array($rr['parent'],$already_saved)) { continue; @@ -423,7 +424,7 @@ function contact_remove($channel_id, $abook_id) { drop_item($rr['id'],false); } } - + q("delete from abook where abook_id = %d and abook_channel = %d", intval($abook['abook_id']), intval($channel_id) @@ -501,17 +502,17 @@ function update_vcard($arr,$vcard = null) { $fn = $arr['fn']; - + // This isn't strictly correct and could be a cause for concern. // 'N' => array_reverse(explode(' ', $fn)) - // What we really want is + // What we really want is // 'N' => Adams;John;Quincy;Reverend,Dr.;III // which is a very difficult parsing problem especially if you allow // the surname to contain spaces. The only way to be sure to get it - // right is to provide a form to input all the various fields and not - // try to extract it from the FN. + // right is to provide a form to input all the various fields and not + // try to extract it from the FN. if(! $vcard) { $vcard = new \Sabre\VObject\Component\VCard([ @@ -689,12 +690,12 @@ function get_vcard_array($vc,$id) { if(is_array($entry['address'])) { array_walk($entry['address'],'array_escape_tags'); } - else { + else { $entry['address'] = (string) escape_tags($entry['address']); } $adrs[] = $entry; - + } } @@ -768,7 +769,7 @@ function vcard_query(&$r) { if($a) { foreach($a as $av) { for($x = 0; $x < count($r); $x ++) { - if($r[$x]['abook_xchan'] == $av['xchan']) { + if($r[$x]['abook_xchan'] == $av['xchan']) { $vctmp = \Sabre\VObject\Reader::read($av['v']); $r[$x]['vcard'] = (($vctmp) ? get_vcard_array($vctmp,$r[$x]['abook_id']) : [] ); } diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 626a825b2..3b22a3c6d 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -93,7 +93,7 @@ function categories_widget($baseurl,$selected = '') { dbesc(ACTIVITY_UPDATE) ); } - else + else $r = unserialize($content); $terms = array(); @@ -206,6 +206,40 @@ function articlecategories_widget($baseurl,$selected = '') { return ''; } +function filecategories_widget($baseurl,$selected = '') { + + $perms = permissions_sql(App::$profile['profile_uid']); + + $terms = array(); + $r = q("select distinct(term.term) + from term join attach on term.oid = attach.id + where attach.uid = %d + and term.uid = attach.uid + and term.ttype = %d + and term.otype = %d + $perms + order by term.term asc", + intval(App::$profile['profile_uid']), + intval(TERM_CATEGORY), + intval(TERM_OBJ_FILE) + ); + + if($r && count($r)) { + foreach($r as $rr) + $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); + + return replace_macros(get_markup_template('categories_widget.tpl'),array( + '$title' => t('Categories'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $baseurl, + )); + } + + return ''; +} function common_friends_visitor_widget($profile_uid,$cnt = 25) { diff --git a/include/feedutils.php b/include/feedutils.php index 5f5f563f8..352b8f038 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -14,9 +14,6 @@ * @return string with an atom feed */ -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\Exception\UnsatisfiedDependencyException; - function get_public_feed($channel, $params) { if(! $params) @@ -435,13 +432,7 @@ function get_atom_elements($feed, $item) { $res['plink'] = unxmlify($item->get_link(0)); $res['item_rss'] = 1; - try { - $uuid = Uuid::uuid5(Uuid::NAMESPACE_URL, $res['plink'])->toString(); - } catch (UnsatisfiedDependencyException $e) { - $uuid = md5($res['plink']); - } - - $res['uuid'] = $uuid; + $res['uuid'] = uuid_from_url($res['plink']); $summary = unxmlify($item->get_description(true)); diff --git a/include/items.php b/include/items.php index 956b259af..bcdc6c687 100755 --- a/include/items.php +++ b/include/items.php @@ -4072,6 +4072,11 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL) { if($stage == DROPITEM_PHASE1) return true; + $r = q("delete from term where otype = %d and oid = %d", + intval(TERM_OBJ_POST), + intval($item['id']) + ); + q("delete from iconfig where iid = %d", intval($item['id']) ); diff --git a/include/text.php b/include/text.php index c2a45814c..3fb17b648 100644 --- a/include/text.php +++ b/include/text.php @@ -2983,7 +2983,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true) $str_tags .= $newtag; } } - + $fn_results[] = [ 'replaced' => $replaced, @@ -3060,7 +3060,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true) ]; } } - + return $fn_results; } @@ -3098,7 +3098,7 @@ function linkify_tags(&$body, $uid, $in_network = true) { function getIconFromType($type) { $iconMap = array( //Folder - t('Collection') => 'fa-folder-o', + 'Collection' => 'fa-folder-o', 'multipart/mixed' => 'fa-folder-o', //dirs in attach use this mime type //Common file 'application/octet-stream' => 'fa-file-o', @@ -3242,7 +3242,7 @@ function item_url_replace($channel,&$item,$old,$new,$oldnick = '') { if($oldnick) json_url_replace('/' . $oldnick . '/' ,'/' . $channel['channel_address'] . '/' ,$item['target']); } - + $item['body'] = preg_replace("/(\[zrl=".preg_quote($old,'/')."\/(photo|photos|gallery)\/".$channel['channel_address'].".+\]\[zmg=\d+x\d+\])".preg_quote($old,'/')."\/(.+\[\/zmg\])/", '${1}'.$new.'/${3}', $item['body']); $item['body'] = preg_replace("/".preg_quote($old,'/')."\/(search|\w+\/".$channel['channel_address'].")/", $new.'/${1}', $item['body']); @@ -3575,7 +3575,7 @@ function cleanup_bbcode($body) { $body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body); $body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body); $body = preg_replace_callback('/\[\$b64svg(.*?)\[\/(svg)\]/ism','\red_unescape_codeblock',$body); - + // fix any img tags that should be zmg $body = preg_replace_callback('/\[img(.*?)\](.*?)\[\/img\]/ism','\red_zrlify_img_callback',$body); @@ -3791,7 +3791,7 @@ function array_path_exists($str,$arr) { /** - * @brief Generate a unique ID. + * @brief Generate a random v4 UUID. * * @return string */ @@ -3807,6 +3807,22 @@ function new_uuid() { } +/** + * @brief Generate a name-based v5 UUID in the URL namespace + * + * @param string $url + * @return string + */ +function uuid_from_url($url) { + + try { + $hash = Uuid::uuid5(Uuid::NAMESPACE_URL, $url)->toString(); + } catch (UnsatisfiedDependencyException $e) { + $hash = md5($url); + } + return $hash; +} + function svg2bb($s) { $s = preg_replace("/\<text (.*?)\>(.*?)\<(.*?)\<\/text\>/", '<text $1>$2<$3</text>', $s); |