diff --git a/boot.php b/boot.php index 317ebd90b..e7ed7dcee 100755 --- a/boot.php +++ b/boot.php @@ -50,7 +50,7 @@ define ( 'PLATFORM_NAME', 'hubzilla' ); define ( 'RED_VERSION', trim(file_get_contents('version.inc')) . 'H'); define ( 'ZOT_REVISION', 1 ); -define ( 'DB_UPDATE_VERSION', 1149 ); +define ( 'DB_UPDATE_VERSION', 1151 ); /** * @brief Constant with a HTML line break. diff --git a/doc/credits.bb b/doc/credits.bb index 5459c7d7a..200f1fc85 100644 --- a/doc/credits.bb +++ b/doc/credits.bb @@ -1,5 +1,9 @@ [b]Credits[/b] +Thanks to all who have helped and contributed to the project and its predecessors over the years. It is possible we missed in your name but this is unintentional. We also thank the community and its members for providing valuable input and without whom this entire effort would be meaningless. + +It is also worth acknowledging the contributions and solutions to problems which arose from discussions amongst members and developers of other somewhat related and competing projects; even if we have had our occasional disagreements. + Mike Macgirvin Fabio Comuni Simon L'nu @@ -62,6 +66,7 @@ tonnerkiller Antoine G Christian Drechsler Ludovic Grossard +RedmatrixCanada Stanislav Lechev [0xAF] aweiher bufalo1973 @@ -73,3 +78,5 @@ mycocham ndurchx pafcu Simó Albert i Beltran +Manuel Reva +Manuel Jiménez Friaza diff --git a/include/AccessList.php b/include/AccessList.php index 46e66d33d..43f1de111 100644 --- a/include/AccessList.php +++ b/include/AccessList.php @@ -34,6 +34,11 @@ class AccessList { return $this->explicit; } + /** + * Set AccessList from strings such as those in already + * existing stored data items + */ + function set($arr,$explicit = true) { $this->allow_cid = $arr['allow_cid']; $this->allow_gid = $arr['allow_gid']; @@ -43,6 +48,12 @@ class AccessList { $this->explicit = $explicit; } + /** + * return an array consisting of the current + * access list components where the elements + * are directly storable. + */ + function get() { return array( 'allow_cid' => $this->allow_cid, @@ -52,6 +63,12 @@ class AccessList { ); } + /** + * Set AccessList from arrays, such as those provided by + * acl_selector(). For convenience, a string (or non-array) input is + * assumed to be a comma-separated list and auto-converted into an array. + */ + function set_from_array($arr,$explicit = true) { $this->allow_cid = perms2str((is_array($arr['contact_allow'])) ? $arr['contact_allow'] : explode(',',$arr['contact_allow'])); diff --git a/include/apps.php b/include/apps.php index 504641102..661fc2163 100644 --- a/include/apps.php +++ b/include/apps.php @@ -264,18 +264,37 @@ function app_install($uid,$app) { else $x = app_store($app); - if($x['success']) - return $x['app_id']; + if($x['success']) { + $r = q("select * from app where app_id = '%s' and app_channel = %d limit 1", + dbesc($x['app_id']), + intval($uid) + ); + if($r) + build_sync_packet($uid,array('app' => $r[0])); + return $x['app_id']; + } return false; } function app_destroy($uid,$app) { + + if($uid && $app['guid']) { + + $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1", + dbesc($app['guid']), + intval($uid) + ); + $x[0]['app_deleted'] = 1; + + $r = q("delete from app where app_id = '%s' and app_channel = %d", dbesc($app['guid']), intval($uid) ); + + build_sync_packet($uid,array('app' => $x)); } } @@ -325,7 +344,7 @@ function app_store($arr) { return $ret; if($arr['photo'] && ! strstr($arr['photo'],z_root())) { - $x = import_profile_photo($arr['photo'],get_observer_hash(),true); + $x = import_xchan_photo($arr['photo'],get_observer_hash(),true); $arr['photo'] = $x[1]; } @@ -342,7 +361,9 @@ function app_store($arr) { $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : ''); $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : ''); - $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' )", + $created = datetime_convert(); + + $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )", dbesc($darray['app_id']), dbesc($darray['app_sig']), dbesc($darray['app_author']), @@ -355,7 +376,9 @@ function app_store($arr) { dbesc($darray['app_addr']), dbesc($darray['app_price']), dbesc($darray['app_page']), - dbesc($darray['app_requires']) + dbesc($darray['app_requires']), + dbesc($created), + dbesc($created) ); if($r) { $ret['success'] = true; @@ -378,7 +401,7 @@ function app_update($arr) { return $ret; if($arr['photo'] && ! strstr($arr['photo'],z_root())) { - $x = import_profile_photo($arr['photo'],get_observer_hash(),true); + $x = import_xchan_photo($arr['photo'],get_observer_hash(),true); $arr['photo'] = $x[1]; } @@ -393,7 +416,9 @@ function app_update($arr) { $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : ''); $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : ''); - $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s' where app_id = '%s' and app_channel = %d", + $edited = datetime_convert(); + + $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s' where app_id = '%s' and app_channel = %d", dbesc($darray['app_sig']), dbesc($darray['app_author']), dbesc($darray['app_name']), @@ -405,6 +430,7 @@ function app_update($arr) { dbesc($darray['app_price']), dbesc($darray['app_page']), dbesc($darray['app_requires']), + dbesc($edited), dbesc($darray['app_id']), intval($darray['app_channel']) ); diff --git a/include/hubloc.php b/include/hubloc.php index 515223f53..396f4ddfa 100644 --- a/include/hubloc.php +++ b/include/hubloc.php @@ -230,7 +230,7 @@ function xchan_store($arr) { if(! $r) return $r; - $photos = import_profile_photo($arr['photo'],$arr['hash']); + $photos = import_xchan_photo($arr['photo'],$arr['hash']); $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($photos[0]), diff --git a/include/identity.php b/include/identity.php index 8d6a65cad..115baddc1 100644 --- a/include/identity.php +++ b/include/identity.php @@ -555,17 +555,27 @@ function identity_basic_export($channel_id, $items = false) { if($r) $ret['term'] = $r; - $r = q("select * from obj where obj_channel = %d", + + // add psuedo-column obj_baseurl to aid in relocations + + $r = q("select obj.*, '%s' as obj_baseurl from obj where obj_channel = %d", + dbesc(z_root()), intval($channel_id) ); if($r) $ret['obj'] = $r; + + $r = q("select * from app where app_channel = %d", + intval($channel_id) + ); + if($r) + $ret['app'] = $r; + if(! $items) return $ret; - $r = q("select * from likes where channel_id = %d", intval($channel_id) ); diff --git a/include/import.php b/include/import.php new file mode 100644 index 000000000..6ce572ea2 --- /dev/null +++ b/include/import.php @@ -0,0 +1,380 @@ + $hubloc['hubloc_guid'], + 'guid_sig' => $hubloc['hubloc_guid_sig'], + 'url' => $hubloc['hubloc_url'], + 'url_sig' => $hubloc['hubloc_url_sig'] + ); + if(($hubloc['hubloc_hash'] === $channel['channel_hash']) && intval($hubloc['hubloc_primary']) && ($seize)) + $hubloc['hubloc_primary'] = 0; + + if(! zot_gethub($arr)) { + unset($hubloc['hubloc_id']); + dbesc_array($hubloc); + + $r = dbq("INSERT INTO hubloc (`" + . implode("`, `", array_keys($hubloc)) + . "`) VALUES ('" + . implode("', '", array_values($hubloc)) + . "')" + ); + } + } + } +} + + + +function import_objs($channel,$objs) { + + if($channel && $objs) { + foreach($objs as $obj) { + + // if it's the old term format - too hard to support + if(! $obj['obj_created']) + continue; + + $baseurl = $obj['obj_baseurl']; + unset($obj['obj_id']); + unset($obj['obj_baseurl']); + + $obj['obj_channel'] = $channel['channel_id']; + + if($baseurl && (strpos($obj['obj_url'],$baseurl . '/thing/') !== false)) { + $obj['obj_url'] = str_replace($baseurl,z_root(),$obj['obj_url']); + } + + if($obj['obj_imgurl']) { + $x = import_xchan_photo($obj['obj_imgurl'],$channel['channel_hash'],true); + $obj['obj_imgurl'] = $x[0]; + } + + dbesc_array($obj); + + $r = dbq("INSERT INTO obj (`" + . implode("`, `", array_keys($obj)) + . "`) VALUES ('" + . implode("', '", array_values($obj)) + . "')" + ); + } + } +} + +function sync_objs($channel,$objs) { + + if($channel && $objs) { + foreach($objs as $obj) { + + if(array_key_exists('obj_deleted',$obj) && $obj['obj_deleted'] && $obj['obj_obj']) { + q("delete from obj where obj_obj = '%s' and obj_channel = %d limit 1", + dbesc($obj['obj_obj']), + intval($channel['channel_id']) + ); + continue; + } + + // if it's the old term format - too hard to support + if(! $obj['obj_created']) + continue; + + $baseurl = $obj['obj_baseurl']; + unset($obj['obj_id']); + unset($obj['obj_baseurl']); + + $obj['obj_channel'] = $channel['channel_id']; + + if($baseurl && (strpos($obj['obj_url'],$baseurl . '/thing/') !== false)) { + $obj['obj_url'] = str_replace($baseurl,z_root(),$obj['obj_url']); + } + + $exists = false; + + $x = q("select * from obj where obj_obj = '%s' and obj_channel = %d limit 1", + dbesc($obj['obj_obj']), + intval($channel['channel_id']) + ); + if($x) { + if($x[0]['obj_edited'] >= $obj['obj_edited']) + continue; + + $exists = true; + } + + if($obj['obj_imgurl']) { + $x = import_xchan_photo($obj['obj_imgurl'],$channel['channel_hash'],true); + $obj['obj_imgurl'] = $x[0]; + } + + $hash = $obj['obj_obj']; + + if($exists) { + unset($obj['obj_obj']); + foreach($obj as $k => $v) { + $r = q("UPDATE obj SET `%s` = '%s' WHERE obj_obj = '%s' AND obj_channel = %d", + dbesc($k), + dbesc($v), + dbesc($hash), + intval($channel['channel_id']) + ); + } + } + else { + + dbesc_array($obj); + + $r = dbq("INSERT INTO obj (`" + . implode("`, `", array_keys($obj)) + . "`) VALUES ('" + . implode("', '", array_values($obj)) + . "')" + ); + } + } + } +} + + + + + +function import_apps($channel,$apps) { + + if($channel && $apps) { + foreach($apps as $app) { + + unset($app['id']); + unset($app['app_channel']); + + $app['app_channel'] = $channel['channel_id']; + + if($app['app_photo']) { + $x = import_xchan_photo($app['app_photo'],$channel['channel_hash'],true); + $app['app_photo'] = $x[0]; + } + + dbesc_array($app); + $r = dbq("INSERT INTO app (`" + . implode("`, `", array_keys($app)) + . "`) VALUES ('" + . implode("', '", array_values($app)) + . "')" + ); + } + } +} + + + +function sync_apps($channel,$apps) { + + if($channel && $apps) { + foreach($apps as $app) { + + if(array_key_exists('app_deleted',$app) && $app['app_deleted'] && $app['app_id']) { + q("delete from app where app_id = '%s' and app_channel = %d limit 1", + dbesc($app['app_id']), + intval($channel['channel_id']) + ); + continue; + } + + unset($app['id']); + unset($app['app_channel']); + + if(! $app['app_created'] || $app['app_created'] === NULL_DATE) + $app['app_created'] = datetime_convert(); + if(! $app['app_edited'] || $app['app_edited'] === NULL_DATE) + $app['app_edited'] = datetime_convert(); + + $app['app_channel'] = $channel['channel_id']; + + if($app['app_photo']) { + $x = import_xchan_photo($app['app_photo'],$channel['channel_hash'],true); + $app['app_photo'] = $x[0]; + } + + $exists = false; + + $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1", + dbesc($app['app_id']), + intval($channel['channel_id']) + ); + if($x) { + if($x[0]['app_edited'] >= $obj['app_edited']) + continue; + $exists = true; + } + $hash = $app['app_id']; + + if($exists) { + unset($app['app_id']); + foreach($app as $k => $v) { + $r = q("UPDATE app SET `%s` = '%s' WHERE app_id = '%s' AND app_channel = %d", + dbesc($k), + dbesc($v), + dbesc($hash), + intval($channel['channel_id']) + ); + } + } + else { + dbesc_array($app); + $r = dbq("INSERT INTO app (`" + . implode("`, `", array_keys($app)) + . "`) VALUES ('" + . implode("', '", array_values($app)) + . "')" + ); + } + } + } +} \ No newline at end of file diff --git a/include/importdoc.php b/include/importdoc.php index 9cce35c50..10f868697 100755 --- a/include/importdoc.php +++ b/include/importdoc.php @@ -1,17 +1,30 @@ ') ); + $r = q("UPDATE attach SET allow_cid = '%s' WHERE hash = '%s' AND is_photo = 1 and uid = %d and allow_cid = '%s'", + dbesc('<' . $recipient . '>'), + dbesc($image_uri), + intval($channel['channel_id']), + dbesc('<' . $channel['channel_hash'] . '>') + ); } } diff --git a/include/network.php b/include/network.php index ef92e0132..75729d6e4 100644 --- a/include/network.php +++ b/include/network.php @@ -1035,7 +1035,7 @@ function discover_by_url($url,$arr = null) { dbesc(datetime_convert()) ); - $photos = import_profile_photo($photo,$guid); + $photos = import_xchan_photo($photo,$guid); $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($photos[0]), @@ -1192,7 +1192,7 @@ function discover_by_webbie($webbie) { dbescdate(datetime_convert()) ); } - $photos = import_profile_photo($vcard['photo'],$addr); + $photos = import_xchan_photo($vcard['photo'],$addr); $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])), dbesc($photos[0]), diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 553e77ed1..2a7d1ae01 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -557,14 +557,14 @@ function guess_image_type($filename, $headers = '') { } -function import_profile_photo($photo,$xchan,$thing = false) { +function import_xchan_photo($photo,$xchan,$thing = false) { $a = get_app(); $flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN); $album = (($thing) ? 'Things' : 'Contact Photos'); - logger('import_profile_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG); + logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG); if($thing) $hash = photo_new_resource(); @@ -650,7 +650,7 @@ function import_profile_photo($photo,$xchan,$thing = false) { $micro = $a->get_baseurl() . '/photo/' . $hash . '-6'; } else { - logger('import_profile_photo: invalid image from ' . $photo); + logger('import_xchan_photo: invalid image from ' . $photo); $photo_failure = true; } if($photo_failure) { diff --git a/include/poller.php b/include/poller.php index 030394486..a1b25bf41 100644 --- a/include/poller.php +++ b/include/poller.php @@ -235,7 +235,7 @@ function poller_run($argv, $argc){ if($r) { require_once('include/photo/photo_driver.php'); foreach($r as $rr) { - $photos = import_profile_photo($rr['xchan_photo_l'],$rr['xchan_hash']); + $photos = import_xchan_photo($rr['xchan_photo_l'],$rr['xchan_hash']); $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc($photos[0]), diff --git a/include/taxonomy.php b/include/taxonomy.php index b57cfc5c4..a82cf94f7 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -341,7 +341,7 @@ function get_things($profile_hash,$uid) { $sql_extra = (($profile_hash) ? " and obj_page = '" . $profile_hash . "' " : ''); - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and uid = %d and obj_type = %d $sql_extra order by obj_verb, term", + $r = q("select * from obj where obj_channel = %d and obj_type = %d $sql_extra order by obj_verb, obj_term", intval($uid), intval(TERM_OBJ_THING) ); @@ -357,8 +357,8 @@ function get_things($profile_hash,$uid) { foreach($r as $rr) { $rr['profile_name'] = ''; - if(! in_array($rr['term_hash'],$profile_hashes)) - $profile_hashes[] = $rr['term_hash']; + if(! in_array($rr['obj_obj'],$profile_hashes)) + $profile_hashes[] = $rr['obj_obj']; } stringify_array_elms($profile_hashes); if(! $profile_hash) { @@ -390,7 +390,7 @@ function get_things($profile_hash,$uid) { $l = q("select xchan_name, xchan_url from likes left join xchan on likee = xchan_hash where target_type = '%s' and target_id = '%s' and channel_id = %d", dbesc(ACTIVITY_OBJ_THING), - dbesc($rr['term_hash']), + dbesc($rr['obj_obj']), intval($uid) ); @@ -400,7 +400,7 @@ function get_things($profile_hash,$uid) { if(! $things[$rr['obj_verb']]) $things[$rr['obj_verb']] = array(); - $things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['term_hash'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun')); + $things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun')); } $sorted_things = array(); if($things) { diff --git a/include/text.php b/include/text.php index e4735ac48..4d9670806 100644 --- a/include/text.php +++ b/include/text.php @@ -72,10 +72,6 @@ function notags($string) { // return(str_replace(array("<",">","\xBA","\xBC","\xBE"), array('[',']','','',''), $string)); } -// use this on "body" or "content" input where angle chars shouldn't be removed, -// and allow them to be safely displayed. - - /** * use this on "body" or "content" input where angle chars shouldn't be removed, diff --git a/include/zot.php b/include/zot.php index 4cc22ac12..fecaa7ad2 100644 --- a/include/zot.php +++ b/include/zot.php @@ -801,7 +801,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { ); } } else { - $photos = import_profile_photo($arr['photo'], $xchan_hash); + $photos = import_xchan_photo($arr['photo'], $xchan_hash); } if ($photos) { if ($photos[4]) { @@ -1637,10 +1637,9 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ } } - - $ab = q("select abook.* from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d - and abook_self = 0", - intval($channel['channel_id']) + $ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'", + intval($channel['channel_id']), + dbesc($arr['owner_xchan']) ); $abook = (($ab) ? $ab[0] : null); @@ -2842,6 +2841,8 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { */ function process_channel_sync_delivery($sender, $arr, $deliveries) { + require_once('include/import.php'); + /** @FIXME this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic. */ $result = array(); @@ -2874,6 +2875,12 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { } } + if(array_key_exists('obj',$arr) && $arr['obj']) + sync_objs($channel,$arr['obj']); + + if(array_key_exists('app',$arr) && $arr['app']) + sync_apps($channel,$arr['app']); + if(array_key_exists('channel',$arr) && is_array($arr['channel']) && count($arr['channel'])) { if(array_key_exists('channel_page_flags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) { $arr['channel']['channel_removed'] = (($arr['channel']['channel_pageflags'] & 0x8000) ? 1 : 0); diff --git a/install/schema_mysql.sql b/install/schema_mysql.sql index 5ee1ec463..1793f89c2 100644 --- a/install/schema_mysql.sql +++ b/install/schema_mysql.sql @@ -108,6 +108,8 @@ CREATE TABLE IF NOT EXISTS `app` ( `app_price` char(255) NOT NULL DEFAULT '', `app_page` char(255) NOT NULL DEFAULT '', `app_requires` char(255) NOT NULL DEFAULT '', + `app_created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `app_edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`id`), KEY `app_id` (`app_id`), KEY `app_name` (`app_name`), @@ -115,7 +117,9 @@ CREATE TABLE IF NOT EXISTS `app` ( KEY `app_photo` (`app_photo`), KEY `app_version` (`app_version`), KEY `app_channel` (`app_channel`), - KEY `app_price` (`app_price`) + KEY `app_price` (`app_price`), + KEY `app_created` (`app_created`), + KEY `app_edited` (`app_edited`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `attach` ( @@ -823,6 +827,11 @@ CREATE TABLE IF NOT EXISTS `obj` ( `obj_type` int(10) unsigned NOT NULL DEFAULT '0', `obj_obj` char(255) NOT NULL DEFAULT '', `obj_channel` int(10) unsigned NOT NULL DEFAULT '0', + `obj_term` char(255) NOT NULL DEFAULT '', + `obj_url` char(255) NOT NULL DEFAULT '', + `obj_imgurl` char(255) NOT NULL DEFAULT '', + `obj_created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `obj_edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `allow_cid` mediumtext NOT NULL, `allow_gid` mediumtext NOT NULL, `deny_cid` mediumtext NOT NULL, @@ -832,6 +841,11 @@ CREATE TABLE IF NOT EXISTS `obj` ( KEY `obj_page` (`obj_page`), KEY `obj_type` (`obj_type`), KEY `obj_channel` (`obj_channel`), + KEY `obj_term` (`obj_term`), + KEY `obj_url` (`obj_url`), + KEY `obj_imgurl` (`obj_imgurl`), + KEY `obj_created` (`obj_created`), + KEY `obj_edited` (`obj_edited`), KEY `obj_obj` (`obj_obj`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql index c594d0f87..d31c304eb 100644 --- a/install/schema_postgres.sql +++ b/install/schema_postgres.sql @@ -107,6 +107,8 @@ CREATE TABLE "app" ( "app_price" text NOT NULL DEFAULT '', "app_page" text NOT NULL DEFAULT '', "app_requires" text NOT NULL DEFAULT '', + "app_created" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', + "app_edited" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', PRIMARY KEY ("id") ); create index "app_id" on app ("app_id"); @@ -116,6 +118,8 @@ create index "app_photo" on app ("app_photo"); create index "app_version" on app ("app_version"); create index "app_channel" on app ("app_channel"); create index "app_price" on app ("app_price"); +create index "app_created" on app ("app_created"); +create index "app_edited" on app ("app_edited"); CREATE TABLE "attach" ( "id" serial NOT NULL, "aid" bigint NOT NULL DEFAULT '0', @@ -812,6 +816,11 @@ CREATE TABLE "obj" ( "obj_type" bigint NOT NULL DEFAULT '0', "obj_obj" text NOT NULL DEFAULT '', "obj_channel" bigint NOT NULL DEFAULT '0', + "obj_term" char(255) NOT NULL DEFAULT '', + "obj_url" char(255) NOT NULL DEFAULT '', + "obj_imgurl" char(255) NOT NULL DEFAULT '', + "obj_created" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', + "obj_edited" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00', "allow_cid" text NOT NULL, "allow_gid" text NOT NULL, "deny_cid" text NOT NULL, @@ -824,6 +833,11 @@ create index "obj_page" on obj ("obj_page"); create index "obj_type" on obj ("obj_type"); create index "obj_channel" on obj ("obj_channel"); create index "obj_obj" on obj ("obj_obj"); +create index "obj_term" on obj ("obj_term"); +create index "obj_url" on obj ("obj_url"); +create index "obj_imgurl" on obj ("obj_imgurl"); +create index "obj_created" on obj ("obj_created"); +create index "obj_edited" on obj ("obj_edited"); CREATE TABLE "outq" ( "outq_hash" text NOT NULL, diff --git a/install/update.php b/install/update.php index b398711b2..8e531b595 100644 --- a/install/update.php +++ b/install/update.php @@ -1,6 +1,6 @@ get_channel(); + + if(! $channel) { + logger('mod_import: channel not found. ', print_r($channel,true)); + notice( t('No channel. Import failed.') . EOL); + return; + } - $configs = $data['config']; - if($configs) { - foreach($configs as $config) { - unset($config['id']); - $config['uid'] = $channel['channel_id']; - dbesc_array($config); - $r = dbq("INSERT INTO pconfig (`" - . implode("`, `", array_keys($config)) - . "`) VALUES ('" - . implode("', '", array_values($config)) - . "')" ); - } + + if($completed < 2) { + if(is_array($data['config'])) { + import_config($channel,$data['config']); } + logger('import step 2'); $_SESSION['import_step'] = 2; ref_session_write(session_id(), serialize($_SESSION)); @@ -244,27 +169,9 @@ function import_post(&$a) { import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],get_account_id(),$channel['channel_id']); } - $profiles = $data['profile']; - if($profiles) { - foreach($profiles as $profile) { - unset($profile['id']); - $profile['aid'] = get_account_id(); - $profile['uid'] = $channel['channel_id']; + if(is_array($data['profiles'])) + import_profiles($channel,$data['profiles']); - // we are going to reset all profile photos to the original - // somebody will have to fix this later and put all the applicable photos into the export - - $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; - $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; - - dbesc_array($profile); - $r = dbq("INSERT INTO profile (`" - . implode("`, `", array_keys($profile)) - . "`) VALUES ('" - . implode("', '", array_values($profile)) - . "')" ); - } - } logger('import step 3'); $_SESSION['import_step'] = 3; ref_session_write(session_id(), serialize($_SESSION)); @@ -272,43 +179,10 @@ function import_post(&$a) { if($completed < 4) { - $hublocs = $data['hubloc']; - if($hublocs) { - foreach($hublocs as $hubloc) { - $hash = make_xchan_hash($hubloc['hubloc_guid'],$hubloc['hubloc_guid_sig']); - if($hubloc['hubloc_network'] === 'zot' && $hash !== $hubloc['hubloc_hash']) { - logger('forged hubloc: ' . print_r($hubloc,true)); - continue; - } + if(is_array($data['hubloc'])) { + import_hublocs($channel,$data['hubloc'],$seize); - if(! array_key_exists('hubloc_primary',$hubloc)) { - $hubloc['hubloc_primary'] = (($hubloc['hubloc_flags'] & 0x0001) ? 1 : 0); - $hubloc['hubloc_orphancheck'] = (($hubloc['hubloc_flags'] & 0x0004) ? 1 : 0); - $hubloc['hubloc_error'] = (($hubloc['hubloc_status'] & 0x0003) ? 1 : 0); - $hubloc['hubloc_deleted'] = (($hubloc['hubloc_flags'] & 0x1000) ? 1 : 0); - } - - $arr = array( - 'guid' => $hubloc['hubloc_guid'], - 'guid_sig' => $hubloc['hubloc_guid_sig'], - 'url' => $hubloc['hubloc_url'], - 'url_sig' => $hubloc['hubloc_url_sig'] - ); - if(($hubloc['hubloc_hash'] === $channel['channel_hash']) && intval($hubloc['hubloc_primary']) && ($seize)) - $hubloc['hubloc_primary'] = 0; - - if(! zot_gethub($arr)) { - unset($hubloc['hubloc_id']); - dbesc_array($hubloc); - - $r = dbq("INSERT INTO hubloc (`" - . implode("`, `", array_keys($hubloc)) - . "`) VALUES ('" - . implode("', '", array_values($hubloc)) - . "')" ); - } - } } logger('import step 4'); $_SESSION['import_step'] = 4; @@ -422,7 +296,7 @@ function import_post(&$a) { require_once('include/photo/photo_driver.php'); - $photos = import_profile_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']); + $photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']); if($photos[4]) $photodate = NULL_DATE; else @@ -556,23 +430,11 @@ function import_post(&$a) { ref_session_write(session_id(), serialize($_SESSION)); } + if(is_array($data['obj'])) + import_objs($channel,$data['obj']); -// This needs more work - we also need the term where otype = 6 to link with this, and the terms need to be relocated. -// $objs = $data['obj']; -// if($objs) { -// foreach($objs as $obj) { -// unset($obj['obj_id']); -// $obj['channel'] = $channel['channel_id']; - -// dbesc_array($obj); -// $r = dbq("INSERT INTO obj (`" -// . implode("`, `", array_keys($obj)) -// . "`) VALUES ('" -// . implode("', '", array_values($obj)) -// . "')" ); -// } -// } - + if(is_array($data['app'])) + import_apps($channel,$data['app']); $saved_notification_flags = notifications_off($channel['channel_id']); diff --git a/mod/item.php b/mod/item.php index ec5d1b3a1..c93560771 100644 --- a/mod/item.php +++ b/mod/item.php @@ -318,7 +318,7 @@ function item_post(&$a) { $private = 0; // webpages are allowed to change ACLs after the fact. Normal conversation items aren't. if($webpage) { - $acl->set_from_arry($_REQUEST); + $acl->set_from_array($_REQUEST); } else { $acl->set($orig_post); diff --git a/mod/like.php b/mod/like.php index 0d0a1a8c2..42ff9bb8a 100755 --- a/mod/like.php +++ b/mod/like.php @@ -117,8 +117,7 @@ function like_content(&$a) { } elseif($obj_type == 'thing') { - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' - and obj_type = %d and term_hash = '%s' limit 1", + $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1", intval(TERM_OBJ_THING), dbesc(argv(2)) ); @@ -146,18 +145,18 @@ function like_content(&$a) { $links = array(); $links[] = array('rel' => 'alternate', 'type' => 'text/html', - 'href' => z_root() . '/thing/' . $r[0]['term_hash']); + 'href' => z_root() . '/thing/' . $r[0]['obj_obj']); if($r[0]['imgurl']) - $links[] = array('rel' => 'photo', 'href' => $r[0]['imgurl']); + $links[] = array('rel' => 'photo', 'href' => $r[0]['obj_imgurl']); $target = json_encode(array( 'type' => $tgttype, - 'title' => $r[0]['term'], - 'id' => z_root() . '/thing/' . $r[0]['term_hash'], + 'title' => $r[0]['obj_term'], + 'id' => z_root() . '/thing/' . $r[0]['obj_obj'], 'link' => $links )); - $plink = '[zrl=' . z_root() . '/thing/' . $r[0]['term_hash'] . ']' . $r[0]['term'] . '[/zrl]'; + $plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]'; } diff --git a/mod/openid.php b/mod/openid.php index 70da2690a..b9ca672a9 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -155,7 +155,7 @@ function openid_content(&$a) { ); if($r) { - $photos = import_profile_photo($pphoto,$url); + $photos = import_xchan_photo($pphoto,$url); if($photos) { $z = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", diff --git a/mod/thing.php b/mod/thing.php index b4b8ad027..03dc7db5b 100644 --- a/mod/thing.php +++ b/mod/thing.php @@ -5,8 +5,9 @@ */ require_once('include/items.php'); +require_once('include/security.php'); require_once('include/contact_selectors.php'); - +require_once('include/acl_selectors.php'); function thing_init(&$a) { @@ -65,33 +66,58 @@ function thing_init(&$a) { if((! $name) || (! $translated_verb)) return; + $acl = new AccessList($channel); + + if(array_key_exists('contact_allow',$_REQUEST) + || array_key_exists('group_allow',$_REQUEST) + || array_key_exists('contact_deny',$_REQUEST) + || array_key_exists('group_deny',$_REQUEST)) { + $acl->set_from_array($_REQUEST); + } + + $x = $acl->get(); + if($term_hash) { - $t = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", - intval(TERM_OBJ_THING), - dbesc($term_hash) + $t = q("select * from obj where obj_obj = '%s' and obj_channel = %d limit 1", + dbesc($term_hash), + intval(local_channel()) ); if(! $t) { notice( t('Item not found.') . EOL); return; } $orig_record = $t[0]; - if($photo != $orig_record['imgurl']) { - $arr = import_profile_photo($photo,get_observer_hash(),true); + if($photo != $orig_record['obj_imgurl']) { + $arr = import_xchan_photo($photo,get_observer_hash(),true); $local_photo = $arr[0]; $local_photo_type = $arr[3]; } else - $local_photo = $orig_record['imgurl']; + $local_photo = $orig_record['obj_imgurl']; - $r = q("update term set term = '%s', url = '%s', imgurl = '%s' where term_hash = '%s' and uid = %d", + $r = q("update obj set obj_term = '%s', obj_url = '%s', obj_imgurl = '%s', obj_edited = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where obj_obj = '%s' and obj_channel = %d ", dbesc($name), dbesc(($url) ? $url : z_root() . '/thing/' . $term_hash), dbesc($local_photo), + dbesc(datetime_convert()), + dbesc($x['allow_cid']), + dbesc($x['allow_gid']), + dbesc($x['deny_cid']), + dbesc($x['deny_gid']), dbesc($term_hash), intval(local_channel()) ); info( t('Thing updated') . EOL); + + $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1", + intval(local_channel()), + dbesc($term_hash) + ); + if($r) { + build_sync_packet(0, array('obj' => $r)); + } + return; } @@ -108,45 +134,29 @@ function thing_init(&$a) { $local_photo = null; if($photo) { - $arr = import_profile_photo($photo,get_observer_hash(),true); + $arr = import_xchan_photo($photo,get_observer_hash(),true); $local_photo = $arr[0]; $local_photo_type = $arr[3]; } - $r = q("select * from term where uid = %d and otype = %d and type = %d and term = '%s' limit 1", - intval(local_channel()), - intval(TERM_OBJ_THING), - intval(TERM_THING), - dbesc($name) - ); - if(! $r) { - $r = q("insert into term ( aid, uid, oid, otype, type, term, url, imgurl, term_hash ) - values( %d, %d, %d, %d, %d, '%s', '%s', '%s', '%s' ) ", - intval($account_id), - intval(local_channel()), - 0, - intval(TERM_OBJ_THING), - intval(TERM_THING), - dbesc($name), - dbesc(($url) ? $url : z_root() . '/thing/' . $hash), - dbesc(($photo) ? $local_photo : ''), - dbesc($hash) - ); - $r = q("select * from term where uid = %d and otype = %d and type = %d and term = '%s' limit 1", - intval(local_channel()), - intval(TERM_OBJ_THING), - intval(TERM_THING), - dbesc($name) - ); - } - $term = $r[0]; + $created = datetime_convert(); + $url = (($url) ? $url : z_root() . '/thing/' . $hash); - $r = q("insert into obj ( obj_page, obj_verb, obj_type, obj_channel, obj_obj) values ('%s','%s', %d, %d, '%s') ", + $r = q("insert into obj ( obj_page, obj_verb, obj_type, obj_channel, obj_obj, obj_term, obj_url, obj_imgurl, obj_created, obj_edited, allow_cid, allow_gid, deny_cid, deny_gid ) values ('%s','%s', %d, %d, '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s') ", dbesc($profile['profile_guid']), dbesc($verb), intval(TERM_OBJ_THING), intval(local_channel()), - dbesc($term['term_hash']) + dbesc($hash), + dbesc($name), + dbesc($url), + dbesc(($photo) ? $local_photo : ''), + dbesc($created), + dbesc($created), + dbesc($x['allow_cid']), + dbesc($x['allow_gid']), + dbesc($x['deny_cid']), + dbesc($x['deny_gid']) ); if(! $r) { @@ -155,10 +165,18 @@ function thing_init(&$a) { } info( t('Thing added')); + + $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1", + intval(local_channel()), + dbesc($hash) + ); + if($r) { + build_sync_packet(0, array('obj' => $r)); + } if($activity) { $arr = array(); - $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $term['url'])); + $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $url)); if($local_photo) $links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo); @@ -166,10 +184,10 @@ function thing_init(&$a) { $obj = json_encode(array( 'type' => $objtype, - 'id' => $term['url'], + 'id' => $url, 'link' => $links, - 'title' => $term['term'], - 'content' => $term['term'] + 'title' => $name, + 'content' => $name )); $bodyverb = str_replace('OBJ: ', '',t('OBJ: %1$s %2$s %3$s')); @@ -182,7 +200,7 @@ function thing_init(&$a) { $arr['item_thread_top'] = 1; $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]'; - $plink = '[zrl=' . $term['url'] . ']' . $term['term'] . '[/zrl]'; + $plink = '[zrl=' . $url . ']' . $name . '[/zrl]'; $arr['body'] = sprintf( $bodyverb, $ulink, $translated_verb, $plink ); @@ -218,7 +236,9 @@ function thing_content(&$a) { if(argc() == 2) { - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", + $sql_extra = permissions_sql(); + + $r = q("select * from obj where obj_type = %d and obj_obj = '%s' $sql_extra limit 1", intval(TERM_OBJ_THING), dbesc(argv(1)) ); @@ -244,12 +264,17 @@ function thing_content(&$a) { return; } + $acl = new AccessList($channel); + $channel_acl = $acl->get(); + + $lockstate = (($acl->is_private()) ? 'lock' : 'unlock'); + $thing_hash = ''; if(argc() == 3 && argv(1) === 'edit') { $thing_hash = argv(2); - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", + $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1", intval(TERM_OBJ_THING), dbesc($thing_hash) ); @@ -269,11 +294,14 @@ function thing_content(&$a) { '$activity' => array('activity',t('Post an activity'),true,t('Only sends to viewers of the applicable profile')), '$thing_hash' => $thing_hash, '$thing_lbl' => t('Name of thing e.g. something'), - '$thething' => $r[0]['term'], + '$thething' => $r[0]['obj_term'], '$url_lbl' => t('URL of thing (optional)'), - '$theurl' => $r[0]['url'], + '$theurl' => $r[0]['obj_url'], '$img_lbl' => t('URL for photo of thing (optional)'), - '$imgurl' => $r[0]['imgurl'], + '$imgurl' => $r[0]['obj_imgurl'], + '$permissions' => t('Permissions'), + '$aclselect' => populate_acl($channel_acl,false), + '$lockstate' => $lockstate, '$submit' => t('Submit') )); @@ -283,7 +311,7 @@ function thing_content(&$a) { if(argc() == 3 && argv(1) === 'drop') { $thing_hash = argv(2); - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", + $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1", intval(TERM_OBJ_THING), dbesc($thing_hash) ); @@ -298,10 +326,10 @@ function thing_content(&$a) { intval(TERM_OBJ_THING), intval(local_channel()) ); - $x = q("delete from term where term_hash = '%s' and uid = %d", - dbesc($thing_hash), - intval(local_channel()) - ); + + $r[0]['obj_deleted'] = 1; + + build_sync_packet(0,array('obj' => $r)); return $o; } @@ -317,6 +345,9 @@ function thing_content(&$a) { '$thing_lbl' => t('Name of thing e.g. something'), '$url_lbl' => t('URL of thing (optional)'), '$img_lbl' => t('URL for photo of thing (optional)'), + '$permissions' => t('Permissions'), + '$aclselect' => populate_acl($channel_acl,false), + '$lockstate' => $lockstate, '$submit' => t('Submit') )); diff --git a/version.inc b/version.inc index cafba0e02..da2499cde 100644 --- a/version.inc +++ b/version.inc @@ -1 +1 @@ -2015-08-31.1141 +2015-09-02.1143 diff --git a/view/css/mod_apps.css b/view/css/mod_apps.css index 5e98a6a18..cfaf5ef87 100644 --- a/view/css/mod_apps.css +++ b/view/css/mod_apps.css @@ -1,6 +1,16 @@ .app-container { float: left; width: 125px; - height: 160px; + height: 180px; padding: 20px; } + +.app-detail { + height: 130px; + overflow-x: hidden; + overflow-y: hidden; +} + +.app-tools { + margin-bottom: 0; +} diff --git a/view/tpl/app.tpl b/view/tpl/app.tpl index cebc17d45..727be5eba 100644 --- a/view/tpl/app.tpl +++ b/view/tpl/app.tpl @@ -1,4 +1,5 @@