diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/RedDAV/RedBrowser.php | 2 | ||||
-rw-r--r-- | include/account.php | 4 | ||||
-rw-r--r-- | include/acl_selectors.php | 26 | ||||
-rw-r--r-- | include/api.php | 91 | ||||
-rw-r--r-- | include/api_auth.php | 84 | ||||
-rw-r--r-- | include/attach.php | 6 | ||||
-rw-r--r-- | include/bb2diaspora.php | 12 | ||||
-rw-r--r-- | include/comanche.php | 8 | ||||
-rw-r--r-- | include/conversation.php | 2 | ||||
-rw-r--r-- | include/deliver.php | 113 | ||||
-rw-r--r-- | include/directory.php | 26 | ||||
-rw-r--r-- | include/follow.php | 32 | ||||
-rw-r--r-- | include/identity.php | 10 | ||||
-rwxr-xr-x | include/items.php | 13 | ||||
-rw-r--r-- | include/message.php | 1 | ||||
-rw-r--r-- | include/network.php | 27 | ||||
-rw-r--r-- | include/notifier.php | 261 | ||||
-rw-r--r-- | include/oauth.php | 161 | ||||
-rw-r--r-- | include/photos.php | 49 | ||||
-rwxr-xr-x | include/plugin.php | 35 | ||||
-rw-r--r-- | include/queue.php | 57 | ||||
-rw-r--r-- | include/queue_fn.php | 165 | ||||
-rw-r--r-- | include/ratenotif.php | 20 | ||||
-rw-r--r-- | include/security.php | 18 | ||||
-rw-r--r-- | include/text.php | 50 | ||||
-rw-r--r-- | include/widgets.php | 2 | ||||
-rw-r--r-- | include/zot.php | 570 |
27 files changed, 1158 insertions, 687 deletions
diff --git a/include/RedDAV/RedBrowser.php b/include/RedDAV/RedBrowser.php index efea5d92f..1aa5f435e 100644 --- a/include/RedDAV/RedBrowser.php +++ b/include/RedDAV/RedBrowser.php @@ -188,7 +188,7 @@ class RedBrowser extends DAV\Browser\Plugin { $parentHash = ''; $owner = $this->auth->owner_id; - $splitPath = split('/', $fullPath); + $splitPath = explode('/', $fullPath); if (count($splitPath) > 3) { for ($i = 3; $i < count($splitPath); $i++) { $attachName = urldecode($splitPath[$i]); diff --git a/include/account.php b/include/account.php index b3a520fd4..e448bdcc6 100644 --- a/include/account.php +++ b/include/account.php @@ -67,7 +67,7 @@ function check_account_invite($invite_code) { $result['message'] .= t('An invitation is required.') . EOL; } $r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_code)); - if(! results($r)) { + if(! $r) { $result['message'] .= t('Invitation could not be verified.') . EOL; } } @@ -718,4 +718,4 @@ function upgrade_message($bbcode = false) { function upgrade_bool_message($bbcode = false) { $x = upgrade_link($bbcode); return t('This action is not available under your subscription plan.') . (($x) ? ' ' . $x : '') ; -}
\ No newline at end of file +} diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 4d44ec12e..3c8f34321 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -210,10 +210,13 @@ function fixacl(&$item) { $item = str_replace(array('<','>'),array('',''),$item); } -function populate_acl($defaults = null,$show_jotnets = true) { +function populate_acl($defaults = null,$show_jotnets = true, $showall = '') { $allow_cid = $allow_gid = $deny_cid = $deny_gid = false; + if(! $showall) + $showall = t('Visible to your default audience'); + if(is_array($defaults)) { $allow_cid = ((strlen($defaults['allow_cid'])) ? explode('><', $defaults['allow_cid']) : array() ); @@ -231,22 +234,21 @@ function populate_acl($defaults = null,$show_jotnets = true) { $jotnets = ''; if($show_jotnets) { -logger('jot_networks'); call_hooks('jot_networks', $jotnets); } $tpl = get_markup_template("acl_selector.tpl"); $o = replace_macros($tpl, array( - '$showall'=> t("Visible to your default audience"), - '$show' => t("Show"), - '$hide' => t("Don't show"), - '$allowcid' => json_encode($allow_cid), - '$allowgid' => json_encode($allow_gid), - '$denycid' => json_encode($deny_cid), - '$denygid' => json_encode($deny_gid), - '$jnetModalTitle' => t('Other networks and post services'), - '$jotnets' => $jotnets, - '$aclModalTitle' => t('Permissions'), + '$showall' => $showall, + '$show' => t("Show"), + '$hide' => t("Don't show"), + '$allowcid' => json_encode($allow_cid), + '$allowgid' => json_encode($allow_gid), + '$denycid' => json_encode($deny_cid), + '$denygid' => json_encode($deny_gid), + '$jnetModalTitle' => t('Other networks and post services'), + '$jotnets' => $jotnets, + '$aclModalTitle' => t('Permissions'), '$aclModalDismiss' => t('Close') )); diff --git a/include/api.php b/include/api.php index e60583a01..5053977c5 100644 --- a/include/api.php +++ b/include/api.php @@ -1,10 +1,10 @@ <?php /** @file */ -require_once("bbcode.php"); -require_once("datetime.php"); -require_once("conversation.php"); -require_once("oauth.php"); -require_once("html2plain.php"); +require_once("include/bbcode.php"); +require_once("include/datetime.php"); +require_once("include/conversation.php"); +require_once("include/oauth.php"); +require_once("include/html2plain.php"); require_once('include/security.php'); require_once('include/photos.php'); require_once('include/items.php'); @@ -112,8 +112,11 @@ require_once('include/api_auth.php'); break; case "json": header ("Content-Type: application/json"); - foreach($r as $rr) + foreach($r as $rr) { + if(! $rr) + $rr = array(); $json = json_encode($rr); + } if ($_GET['callback']) $json = $_GET['callback']."(".$json.")"; return $json; @@ -248,6 +251,7 @@ require_once('include/api_auth.php'); if (count($uinfo)==0) { return False; } + $following = false; if(intval($uinfo[0]['abook_self'])) { $usr = q("select * from channel where channel_id = %d limit 1", @@ -263,18 +267,22 @@ require_once('include/api_auth.php'); $r = q("SELECT COUNT(`id`) as `count` FROM `item` WHERE `uid` = %d AND item_wall = 1 $item_normal - AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''", + AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`='' + AND item_private = 0 ", intval($usr[0]['channel_id']) ); $countitms = $r[0]['count']; + $following = true; } else { $r = q("SELECT COUNT(`id`) as `count` FROM `item` WHERE author_xchan = '%s' - AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''", + AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`='' + AND item_private = 0 ", intval($uinfo[0]['xchan_hash']) ); $countitms = $r[0]['count']; + $following = (($uinfo[0]['abook_myperms'] & PERMS_R_STREAM) ? true : false ); } @@ -310,7 +318,6 @@ require_once('include/api_auth.php'); 'location' => ($usr) ? $usr[0]['channel_location'] : '', 'profile_image_url' => $uinfo[0]['xchan_photo_l'], 'url' => $uinfo[0]['xchan_url'], -//FIXME 'contact_url' => $a->get_baseurl() . "/connections/".$uinfo[0]['abook_id'], 'protected' => false, 'friends_count' => intval($countfriends), @@ -334,7 +341,7 @@ require_once('include/api_auth.php'); 'profile_background_tile' => false, 'profile_use_background_image' => false, 'notifications' => false, - 'following' => '', // #XXX: fix me + 'following' => $following, 'verified' => true // #XXX: fix me ); @@ -414,7 +421,7 @@ require_once('include/api_auth.php'); 'utc_offset' => 0, // #XXX: fix me 'time_zone' => '', //$uinfo[0]['timezone'], 'statuses_count' => 0, - 'following' => 1, + 'following' => false, 'statusnet_blocking' => false, 'notifications' => false, 'uid' => 0, @@ -852,13 +859,38 @@ require_once('include/api_auth.php'); $_REQUEST['type'] = 'wall'; if(x($_FILES,'media')) { - $_FILES['userfile'] = $_FILES['media']; - // upload the image if we have one - $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo - require_once('mod/wall_attach.php'); - $media = wall_attach_post($a); - if(strlen($media)>0) - $_REQUEST['body'] .= "\n\n".$media; + if(is_array($_FILES['media']['name'])) { + $num_uploads = count($_FILES['media']['name']); + for($x = 0; $x < $num_uploads; $x ++) { + $_FILES['userfile'] = array(); + $_FILES['userfile']['name'] = $_FILES['media']['name'][$x]; + $_FILES['userfile']['type'] = $_FILES['media']['type'][$x]; + $_FILES['userfile']['tmp_name'] = $_FILES['media']['tmp_name'][$x]; + $_FILES['userfile']['error'] = $_FILES['media']['error'][$x]; + $_FILES['userfile']['size'] = $_FILES['media']['size'][$x]; + + // upload each image if we have any + $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo + require_once('mod/wall_attach.php'); + $a->data['api_info'] = $user_info; + $media = wall_attach_post($a); + + if(strlen($media)>0) + $_REQUEST['body'] .= "\n\n" . $media; + } + } + else { + // AndStatus doesn't present media as an array + $_FILES['userfile'] = $_FILES['media']; + // upload each image if we have any + $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo + require_once('mod/wall_attach.php'); + $a->data['api_info'] = $user_info; + $media = wall_attach_post($a); + + if(strlen($media)>0) + $_REQUEST['body'] .= "\n\n" . $media; + } } } @@ -870,6 +902,7 @@ require_once('include/api_auth.php'); // this should output the last post (the one we just posted). return api_status_show($a,$type); } + api_register_func('api/statuses/update_with_media','api_statuses_update', true); api_register_func('api/statuses/update','api_statuses_update', true); @@ -1078,6 +1111,8 @@ require_once('include/api_auth.php'); 'contributors' => '' ); $status_info['user'] = $user_info; + if(array_key_exists('status',$status_info['user'])) + unset($status_info['user']['status']); } return api_apply_template("status", $type, array('$status' => $status_info)); @@ -1319,6 +1354,8 @@ require_once('include/api_auth.php'); // params $id = intval(argv(3)); + if(! $id) + $id = $_REQUEST['id']; logger('API: api_statuses_show: '.$id); @@ -1335,10 +1372,12 @@ require_once('include/api_auth.php'); $r = q("select * from item where true $item_normal $sql_extra", intval($id) ); + xchan_query($r,true); $ret = api_format_items($r,$user_info); + if ($conversation) { $data = array('$statuses' => $ret); return api_apply_template("timeline", $type, $data); @@ -2298,28 +2337,28 @@ require_once('include/api_auth.php'); api_register_func('api/direct_messages','api_direct_messages_inbox',true); - function api_oauth_request_token(&$a, $type){ try{ - $oauth = new FKOAuth1(); - $req = OAuthRequest::from_request(); -logger('Req: ' . var_export($req,true)); + $oauth = new ZotOAuth1(); + $req = OAuth1Request::from_request(); + logger('Req: ' . var_export($req,true),LOGGER_DATA); $r = $oauth->fetch_request_token($req); }catch(Exception $e){ logger('oauth_exception: ' . print_r($e->getMessage(),true)); - echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); + echo "error=". OAuth1Util::urlencode_rfc3986($e->getMessage()); killme(); } echo $r; killme(); } + function api_oauth_access_token(&$a, $type){ try{ - $oauth = new FKOAuth1(); - $req = OAuthRequest::from_request(); + $oauth = new ZotOAuth1(); + $req = OAuth1Request::from_request(); $r = $oauth->fetch_access_token($req); }catch(Exception $e){ - echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme(); + echo "error=". OAuth1Util::urlencode_rfc3986($e->getMessage()); killme(); } echo $r; killme(); diff --git a/include/api_auth.php b/include/api_auth.php index ee9db3f55..26a9df8d4 100644 --- a/include/api_auth.php +++ b/include/api_auth.php @@ -1,17 +1,19 @@ <?php /** @file */ -require_once("oauth.php"); - - /** - * Simple HTTP Login + * API Login via basic-auth or OAuth */ function api_login(&$a){ + + $record = null; + + require_once('include/oauth.php'); + // login with oauth try { - $oauth = new FKOAuth1(); - $req = OAuthRequest::from_request(); + $oauth = new ZotOAuth1(); + $req = OAuth1Request::from_request(); list($consumer,$token) = $oauth->verify_request($req); @@ -23,16 +25,14 @@ function api_login(&$a){ call_hooks('logged_in', $a->user); return; } - echo __file__.__line__.__function__."<pre>"; -// var_dump($consumer, $token); - die(); + killme(); } catch(Exception $e) { - logger(__file__.__line__.__function__."\n".$e); + logger($e->getMessage()); } - - // workaround for HTTP-auth in CGI mode + // workarounds for HTTP-auth in CGI mode + if(x($_SERVER,'REDIRECT_REMOTE_USER')) { $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"],6)) ; if(strlen($userpass)) { @@ -51,45 +51,49 @@ function api_login(&$a){ } } + require_once('include/auth.php'); + require_once('include/security.php'); - if (!isset($_SERVER['PHP_AUTH_USER'])) { - logger('API_login: ' . print_r($_SERVER,true), LOGGER_DEBUG); - header('WWW-Authenticate: Basic realm="Red"'); - header('HTTP/1.0 401 Unauthorized'); - die('This api requires login'); - } - // process normal login request - require_once('include/auth.php'); - $channel_login = 0; - $record = account_verify_password($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']); - if(! $record) { - $r = q("select * from channel where channel_address = '%s' limit 1", + + if(isset($_SERVER['PHP_AUTH_USER'])) { + $channel_login = 0; + $record = account_verify_password($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']); + if(! $record) { + $r = q("select * from channel left join account on account.account_id = channel.channel_account_id + where channel.channel_address = '%s' limit 1", dbesc($_SERVER['PHP_AUTH_USER']) ); if ($r) { - $x = q("select * from account where account_id = %d limit 1", - intval($r[0]['channel_account_id']) - ); - if ($x) { - $record = account_verify_password($x[0]['account_email'],$_SERVER['PHP_AUTH_PW']); + $record = account_verify_password($r[0]['account_email'],$_SERVER['PHP_AUTH_PW']); if($record) $channel_login = $r[0]['channel_id']; } } - if(! $record) { - logger('API_login failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); - header('WWW-Authenticate: Basic realm="Red"'); - header('HTTP/1.0 401 Unauthorized'); - die('This api requires login'); - } } - require_once('include/security.php'); - authenticate_success($record); + if($record) { + authenticate_success($record); - if($channel_login) - change_channel($channel_login); + if($channel_login) + change_channel($channel_login); + + $_SESSION['allow_api'] = true; + return true; + } + else { + $_SERVER['PHP_AUTH_PW'] = '*****'; + logger('API_login failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); + log_failed_login('API login failure'); + retry_basic_auth(); + } - $_SESSION['allow_api'] = true; } + + +function retry_basic_auth() { + header('WWW-Authenticate: Basic realm="Hubzilla"'); + header('HTTP/1.0 401 Unauthorized'); + echo('This api requires login'); + killme(); +}
\ No newline at end of file diff --git a/include/attach.php b/include/attach.php index 36b971712..8595d5d86 100644 --- a/include/attach.php +++ b/include/attach.php @@ -430,7 +430,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $observer = $x[0]; } - logger('arr: ' . print_r($arr,true)); + logger('arr: ' . print_r($arr,true), LOGGER_DATA); if(! perm_is_allowed($channel_id,$observer_hash, 'write_storage')) { $ret['message'] = t('Permission denied.'); @@ -503,6 +503,10 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { } } + // AndStatus sends jpegs with a non-standard mimetype + if($type === 'image/jpg') + $type = 'image/jpeg'; + $existing_size = 0; if($options === 'replace') { diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index 1be7caa19..81b95b30b 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -305,15 +305,6 @@ function bb2diaspora_itembody($item, $force_update = false) { $matches = array(); - //if we have a photo item just prepend the photo bbcode to item['body'] - $is_photo = (($item['obj_type'] == ACTIVITY_OBJ_PHOTO) ? true : false); - if($is_photo) { - $object = json_decode($item['object'],true); - if($object['bbcode']) { - $item['body'] = (($item['body']) ? $object['bbcode'] . "\r\n" . $item['body'] : $object['bbcode']); - } - } - if(($item['diaspora_meta']) && (! $force_update)) { $diaspora_meta = json_decode($item['diaspora_meta'],true); if($diaspora_meta) { @@ -333,6 +324,8 @@ function bb2diaspora_itembody($item, $force_update = false) { } } + create_export_photo_body($item); + $newitem = $item; if(array_key_exists('item_obscured',$item) && intval($item['item_obscured'])) { @@ -346,6 +339,7 @@ function bb2diaspora_itembody($item, $force_update = false) { } } + bb2diaspora_itemwallwall($newitem); $title = $newitem['title']; diff --git a/include/comanche.php b/include/comanche.php index ef71886f2..ca3ad336b 100644 --- a/include/comanche.php +++ b/include/comanche.php @@ -284,8 +284,12 @@ function comanche_widget($name, $text) { $func = 'widget_' . trim($name); - if((! function_exists($func)) && file_exists('widget/' . trim($name) . '.php')) - require_once('widget/' . trim($name) . '.php'); + if(! function_exists($func)) { + if(file_exists('widget/' . trim($name) . '.php')) + require_once('widget/' . trim($name) . '.php'); + elseif(file_exists('widget/' . trim($name) . '/' . trim($name) . '.php')) + require_once('widget/' . trim($name) . '/' . trim($name) . '.php'); + } else { $theme_widget = $func . '.php'; if((! function_exists($func)) && theme_include($theme_widget)) diff --git a/include/conversation.php b/include/conversation.php index 3b534dc69..747bb5d0a 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1227,7 +1227,7 @@ function status_editor($a, $x, $popup = false) { '$wait' => t('Please wait'), '$permset' => t('Permission settings'), '$shortpermset' => t('permissions'), - '$ptyp' => (($notes_cid) ? 'note' : 'wall'), + '$ptyp' => '', '$content' => ((x($x,'body')) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8') : ''), '$attachment' => ((x($x, 'attachment')) ? $x['attachment'] : ''), '$post_id' => '', diff --git a/include/deliver.php b/include/deliver.php index de93e316e..40df543d5 100644 --- a/include/deliver.php +++ b/include/deliver.php @@ -2,6 +2,7 @@ require_once('include/cli_startup.php'); require_once('include/zot.php'); +require_once('include/queue_fn.php'); function deliver_run($argv, $argc) { @@ -15,7 +16,6 @@ function deliver_run($argv, $argc) { logger('deliver: invoked: ' . print_r($argv,true), LOGGER_DATA); - for($x = 1; $x < $argc; $x ++) { $dresult = null; @@ -24,87 +24,6 @@ function deliver_run($argv, $argc) { ); if($r) { - /** - * Check to see if we have any recent communications with this hub (in the last month). - * If not, reduce the outq_priority. - */ - - $base = ''; - - $h = parse_url($r[0]['outq_posturl']); - if($h) { - $base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : ''); - if($base !== z_root()) { - $y = q("select site_update, site_dead from site where site_url = '%s' ", - dbesc($base) - ); - if($y) { - if(intval($y[0]['site_dead'])) { - q("delete from outq where outq_posturl = '%s'", - dbesc($r[0]['outq_posturl']) - ); - logger('dead site ignored ' . $base); - continue; - } - if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) { - q("update outq set outq_priority = %d where outq_hash = '%s'", - intval($r[0]['outq_priority'] + 10), - dbesc($r[0]['outq_hash']) - ); - logger('immediate delivery deferred for site ' . $base); - continue; - } - } - else { - - // zot sites should all have a site record, unless they've been dead for as long as - // your site has existed. Since we don't know for sure what these sites are, - // call them unknown - - q("insert into site (site_url, site_update, site_dead, site_type) values ('%s','%s',0,%d) ", - dbesc($base), - dbesc(datetime_convert()), - intval(($r[0]['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN) - ); - } - } - } - - // "post" queue driver - used for diaspora and friendica-over-diaspora communications. - - if($r[0]['outq_driver'] === 'post') { - - - $result = z_post_url($r[0]['outq_posturl'],$r[0]['outq_msg']); - if($result['success'] && $result['return_code'] < 300) { - logger('deliver: queue post success to ' . $r[0]['outq_posturl'], LOGGER_DEBUG); - if($base) { - q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ", - dbesc(datetime_convert()), - dbesc($base) - ); - } - q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s' limit 1", - dbesc('accepted for delivery'), - dbesc(datetime_convert()), - dbesc($argv[$x]) - ); - - $y = q("delete from outq where outq_hash = '%s'", - dbesc($argv[$x]) - ); - - } - else { - logger('deliver: queue post returned ' . $result['return_code'] . ' from ' . $r[0]['outq_posturl'],LOGGER_DEBUG); - $y = q("update outq set outq_updated = '%s' where outq_hash = '%s'", - dbesc(datetime_convert()), - dbesc($argv[$x]) - ); - } - continue; - } - $notify = json_decode($r[0]['outq_notify'],true); // Messages without an outq_msg will need to go via the web, even if it's a @@ -112,6 +31,7 @@ function deliver_run($argv, $argc) { if(($r[0]['outq_posturl'] === z_root() . '/post') && ($r[0]['outq_msg'])) { logger('deliver: local delivery', LOGGER_DEBUG); + // local delivery // we should probably batch these and save a few delivery processes @@ -127,9 +47,9 @@ function deliver_run($argv, $argc) { $msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m))))); $dresult = zot_import($msg,z_root()); } - $r = q("delete from outq where outq_hash = '%s'", - dbesc($argv[$x]) - ); + + remove_queue_item($r[0]['outq_hash']); + if($dresult && is_array($dresult)) { foreach($dresult as $xx) { if(is_array($xx) && array_key_exists('message_id',$xx)) { @@ -147,27 +67,16 @@ function deliver_run($argv, $argc) { } } - q("delete from dreport where dreport_queue = '%s' limit 1", - dbesc($argv[$x]) - ); - } - } - else { - logger('deliver: dest: ' . $r[0]['outq_posturl'], LOGGER_DEBUG); - $result = zot_zot($r[0]['outq_posturl'],$r[0]['outq_notify']); - if($result['success']) { - logger('deliver: remote zot delivery succeeded to ' . $r[0]['outq_posturl']); - zot_process_response($r[0]['outq_posturl'],$result, $r[0]); - } - else { - logger('deliver: remote zot delivery failed to ' . $r[0]['outq_posturl']); - logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA); - $y = q("update outq set outq_updated = '%s' where outq_hash = '%s'", - dbesc(datetime_convert()), + q("delete from dreport where dreport_queue = '%s'", dbesc($argv[$x]) ); } } + + // otherwise it's a remote delivery - call queue_deliver() with the $immediate flag + + queue_deliver($r[0],true); + } } } diff --git a/include/directory.php b/include/directory.php index 9ab1d805b..8792a15e1 100644 --- a/include/directory.php +++ b/include/directory.php @@ -8,6 +8,7 @@ require_once('boot.php'); require_once('include/zot.php'); require_once('include/cli_startup.php'); require_once('include/dir_fns.php'); +require_once('include/queue_fn.php'); /** * @brief @@ -83,20 +84,17 @@ function directory_run($argv, $argc){ */ $hash = random_string(); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) - values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($channel['channel_account_id']), - intval($channel['channel_id']), - dbesc('zot'), - dbesc($url), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($packet), - dbesc('') - ); - } else { + + queue_insert(array( + 'hash' => $hash, + 'account_id' => $channel['channel_account_id'], + 'channel_id' => $channel['channel_id'], + 'posturl' => $url, + 'notify' => $packet, + )); + + } + else { q("update channel set channel_dirdate = '%s' where channel_id = %d", dbesc(datetime_convert()), intval($channel['channel_id']) diff --git a/include/follow.php b/include/follow.php index 40ad2c299..5e1146657 100644 --- a/include/follow.php +++ b/include/follow.php @@ -122,6 +122,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) else $permissions = $j['permissions']; + foreach($permissions as $k => $v) { if($v) { $their_perms = $their_perms | intval($global_perms[$k][1]); @@ -161,18 +162,20 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) } } if($r) { + $xchan = $r[0]; $xchan_hash = $r[0]['xchan_hash']; $their_perms = 0; } } + if(! $xchan_hash) { $result['message'] = t('Channel discovery failed.'); logger('follow: ' . $result['message']); return $result; } - $x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => 1); + $x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => 1, 'singleton' => 0); call_hooks('follow_allow',$x); @@ -180,7 +183,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) $result['message'] = t('Protocol disabled.'); return $result; } - + $singleton = intval($x['singleton']); if((local_channel()) && $uid == local_channel()) { $aid = get_account_id(); @@ -201,6 +204,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) $default_group = $r[0]['channel_default_group']; } + if($is_http) { @@ -221,24 +225,34 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) return $result; } - $r = q("select abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d limit 1", + $r = q("select abook_xchan, abook_instance from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($xchan_hash), intval($uid) ); + + if($r) { - $x = q("update abook set abook_their_perms = %d where abook_id = %d", + $abook_instance = $r[0]['abook_instance']; + + if(($singleton) && strpos($abook_instance,z_root()) === false) { + if($abook_instance) + $abook_instance .= ','; + $abook_instance .= z_root(); + } + + $x = q("update abook set abook_their_perms = %d, abook_instance = '%s' where abook_id = %d", intval($their_perms), + dbesc($abook_instance), intval($r[0]['abook_id']) ); } else { - $closeness = get_pconfig($uid,'system','new_abook_closeness'); if($closeness === false) $closeness = 80; - $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_feed, abook_their_perms, abook_my_perms, abook_created, abook_updated ) - values( %d, %d, %d, '%s', %d, %d, %d, '%s', '%s' ) ", + $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_feed, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_instance ) + values( %d, %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s' ) ", intval($aid), intval($uid), intval($closeness), @@ -247,7 +261,8 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) intval(($is_http) ? $their_perms|PERMS_R_STREAM|PERMS_A_REPUBLISH : $their_perms), intval($my_perms), dbesc(datetime_convert()), - dbesc(datetime_convert()) + dbesc(datetime_convert()), + dbesc(($singleton) ? z_root() : '') ); } @@ -259,6 +274,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) dbesc($xchan_hash), intval($uid) ); + if($r) { $result['abook'] = $r[0]; proc_run('php', 'include/notifier.php', 'permission_create', $result['abook']['abook_id']); diff --git a/include/identity.php b/include/identity.php index 95ade3b28..cfedd243a 100644 --- a/include/identity.php +++ b/include/identity.php @@ -178,7 +178,7 @@ function create_identity($arr) { $ret = array('success' => false); if(! $arr['account_id']) { - $ret['message'] = t('No account identifier'); + $ret['message'] = t('No account identifier'); return $ret; } $ret = identity_check_service_class($arr['account_id']); @@ -352,7 +352,7 @@ function create_identity($arr) { ); if($role_permissions) { - $myperms = ((array_key_exists('perms_auto',$role_permissions) && $role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0); + $myperms = ((array_key_exists('perms_accept',$role_permissions)) ? intval($role_permissions['perms_accept']) : 0); } else $myperms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK @@ -896,12 +896,6 @@ function profile_load(&$a, $nickname, $profile = '') { $_SESSION['theme'] = $p[0]['channel_theme']; -// $a->set_template_engine(); // reset the template engine to the default in case the user's theme doesn't specify one - -// $theme_info_file = "view/theme/".current_theme()."/php/theme.php"; -// if (file_exists($theme_info_file)){ -// require_once($theme_info_file); -// } } /** diff --git a/include/items.php b/include/items.php index ef1867c14..44f9633a9 100755 --- a/include/items.php +++ b/include/items.php @@ -2349,7 +2349,7 @@ function item_store($arr, $allow_exec = false) { return $ret; } - if($arr['obj_type'] == ACTIVITY_OBJ_NOTE) + if(($arr['obj_type'] == ACTIVITY_OBJ_NOTE) && (! $arr['object'])) $arr['obj_type'] = ACTIVITY_OBJ_COMMENT; // is the new message multi-level threaded? @@ -2870,6 +2870,7 @@ function send_status_notifications($post_id,$item) { if($x) { foreach($x as $xx) { if($xx['author_xchan'] === $r[0]['channel_hash']) { + $notify = true; // check for an unfollow thread activity - we should probably decode the obj and check the id @@ -3334,7 +3335,6 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { if((! $private) && $new_public_policy) $private = 1; - $item_wall = 1; $item_origin = 1; $item_uplink = 0; @@ -3385,8 +3385,13 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { if($r) proc_run('php','include/notifier.php','tgroup',$item_id); - else + else { logger('start_delivery_chain: failed to update item'); + // reset the source xchan to prevent loops + $r = q("update item set source_xchan = '' where id = %d", + intval($item_id) + ); + } } /** @@ -3949,6 +3954,8 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { return '<at:deleted-entry ref="' . xmlify($item['mid']) . '" when="' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '" />' . "\r\n"; + create_export_photo_body($item); + if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) $body = fix_private_photos($item['body'],$owner['uid'],$item,$cid); else diff --git a/include/message.php b/include/message.php index 6a9e8328a..940fcc275 100644 --- a/include/message.php +++ b/include/message.php @@ -506,3 +506,4 @@ function private_messages_fetch_conversation($channel_id, $messageitem_id, $upda return $messages; } + diff --git a/include/network.php b/include/network.php index f386afc8e..859a60650 100644 --- a/include/network.php +++ b/include/network.php @@ -1796,6 +1796,7 @@ function get_site_info() { 'url' => z_root(), 'plugins' => $visible_plugins, 'register_policy' => $register_policy[get_config('system','register_policy')], + 'invitation_only' => intval(get_config('system','invitation_only')), 'directory_mode' => $directory_mode[get_config('system','directory_mode')], 'language' => get_config('system','language'), 'rss_connections' => get_config('system','feed_contacts'), @@ -1822,6 +1823,13 @@ function check_siteallowed($url) { $retvalue = true; + + $arr = array('url' => $url); + call_hooks('check_siteallowed',$arr); + + if(array_key_exists('allowed',$arr)) + return $arr['allowed']; + $bl1 = get_config('system','whitelisted_sites'); if(is_array($bl1) && $bl1) { foreach($bl1 as $bl) { @@ -1848,6 +1856,12 @@ function check_channelallowed($hash) { $retvalue = true; + $arr = array('hash' => $hash); + call_hooks('check_channelallowed',$arr); + + if(array_key_exists('allowed',$arr)) + return $arr['allowed']; + $bl1 = get_config('system','whitelisted_channels'); if(is_array($bl1) && $bl1) { foreach($bl1 as $bl) { @@ -1870,3 +1884,16 @@ function check_channelallowed($hash) { return $retvalue; } +function deliverable_singleton($xchan) { + $r = q("select abook_instance from abook where abook_xchan = '%s' limit 1", + dbesc($xchan['xchan_hash']) + ); + if($r) { + if(! $r[0]['abook_instance']) + return true; + if(strpos($r[0]['abook_instance'],z_root()) !== false) + return true; + } + return false; +} + diff --git a/include/notifier.php b/include/notifier.php index b7830285a..32d702cb5 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -44,7 +44,6 @@ require_once('include/html2plain.php'); * expire (in items.php) * like (in like.php, poke.php) * mail (in message.php) - * suggest (in fsuggest.php) * tag (in photos.php, poke.php, tagger.php) * tgroup (in items.php) * wall-new (in photos.php, item.php) @@ -52,11 +51,14 @@ require_once('include/html2plain.php'); * and ITEM_ID is the id of the item in the database that needs to be sent to others. * * ZOT + * permission_create abook_id * permission_update abook_id * refresh_all channel_id * purge_all channel_id * expire channel_id * relay item_id (item was relayed to owner, we will deliver it as owner) + * single_activity item_id (deliver to a singleton network from the appropriate clone) + * single_mail mail_id (deliver to a singleton network from the appropriate clone) * location channel_id * request channel_id xchan_hash message_id * rating xlink_id @@ -66,6 +68,12 @@ require_once('include/html2plain.php'); require_once('include/cli_startup.php'); require_once('include/zot.php'); require_once('include/queue_fn.php'); +require_once('include/session.php'); +require_once('include/datetime.php'); +require_once('include/items.php'); +require_once('include/bbcode.php'); +require_once('include/identity.php'); +require_once('include/Contact.php'); function notifier_run($argv, $argc){ @@ -73,15 +81,10 @@ function notifier_run($argv, $argc){ $a = get_app(); - require_once("session.php"); - require_once("datetime.php"); - require_once('include/items.php'); - require_once('include/bbcode.php'); if($argc < 3) return; - logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG); $cmd = $argv[1]; @@ -93,7 +96,6 @@ function notifier_run($argv, $argc){ if(! $item_id) return; - require_once('include/identity.php'); $sys = get_sys_channel(); $deliveries = array(); @@ -108,87 +110,8 @@ function notifier_run($argv, $argc){ } - if($cmd == 'permission_update' || $cmd == 'permission_create') { - // Get the recipient - $r = q("select abook.*, hubloc.* from abook - left join hubloc on hubloc_hash = abook_xchan - where abook_id = %d and abook_self = 0 - and not (hubloc_flags & %d) > 0 and not (hubloc_status & %d) > 0 limit 1", - intval($item_id), - intval(HUBLOC_FLAGS_DELETED), - intval(HUBLOC_OFFLINE) - ); - - if($r) { - // Get the sender - $s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", - intval($r[0]['abook_channel']) - ); - if($s) { - $perm_update = array('sender' => $s[0], 'recipient' => $r[0], 'success' => false, 'deliveries' => ''); - - if($cmd == 'permission_create') - call_hooks('permissions_create',$perm_update); - else - call_hooks('permissions_update',$perm_update); - - if($perm_update['success'] && $perm_update['deliveries']) - $deliveries[] = $perm_update['deliveries']; - - if(! $perm_update['success']) { - // send a refresh message to each hub they have registered here - $h = q("select * from hubloc where hubloc_hash = '%s' - and not (hubloc_flags & %d) > 0 and not (hubloc_status & %d) > 0", - dbesc($r[0]['hubloc_hash']), - intval(HUBLOC_FLAGS_DELETED), - intval(HUBLOC_OFFLINE) - ); - if($h) { - foreach($h as $hh) { - if(in_array($hh['hubloc_url'],$dead_hubs)) { - logger('skipping dead hub: ' . $hh['hubloc_url'], LOGGER_DEBUG); - continue; - } - - $data = zot_build_packet($s[0],'refresh',array(array( - 'guid' => $hh['hubloc_guid'], - 'guid_sig' => $hh['hubloc_guid_sig'], - 'url' => $hh['hubloc_url']) - )); - if($data) { - $hash = random_string(); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) - values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($s[0]['channel_account_id']), - intval($s[0]['channel_id']), - dbesc('zot'), - dbesc($hh['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($data), - dbesc('') - ); - $deliveries[] = $hash; - } - } - - } - } - - if($deliveries) - do_delivery($deliveries); - } - } - return; - } - - - $expire = false; $request = false; $mail = false; - $fsuggest = false; $top_level = false; $location = false; $recipients = array(); @@ -237,51 +160,43 @@ function notifier_run($argv, $argc){ $packet_type = 'request'; $normal_mode = false; } - elseif($cmd === 'expire') { - - // FIXME - // This will require a special zot packet containing a list of item message_id's to be expired. - // This packet will be public, since we cannot selectively deliver here. - // We need the handling on this end to create the array, and the handling on the remote end - // to verify permissions (for each item) and process it. Until this is complete, the expire feature will be disabled. - - return; - - $normal_mode = false; - $expire = true; - $items = q("SELECT * FROM item WHERE uid = %d AND item_wall = 1 - AND item_deleted = 1 AND `changed` > %s - INTERVAL %s", - intval($item_id), - db_utcnow(), db_quoteinterval('10 MINUTE') + elseif($cmd == 'permission_update' || $cmd == 'permission_create') { + // Get the (single) recipient + $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0", + intval($item_id) ); - $uid = $item_id; - $item_id = 0; - if(! $items) - return; + if($r) { + $uid = $r[0]['abook_channel']; + // Get the sender + $channel = channelx_by_n($uid); + if($channel) { + $perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''); - } - elseif($cmd === 'suggest') { - $normal_mode = false; - $fsuggest = true; + if($cmd == 'permission_create') + call_hooks('permissions_create',$perm_update); + else + call_hooks('permissions_update',$perm_update); - $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1", - intval($item_id) - ); - if(! count($suggest)) - return; - $uid = $suggest[0]['uid']; - $recipients[] = $suggest[0]['cid']; - $item = $suggest[0]; + if($perm_update['success']) { + if($perm_update['deliveries']) { + $deliveries[] = $perm_update['deliveries']; + do_delivery($deliveries); + } + return; + } + else { + $recipients[] = $r[0]['abook_xchan']; + $private = false; + $packet_type = 'refresh'; + $packet_recips = array(array('guid' => $r[0]['xchan_guid'],'guid_sig' => $r[0]['xchan_guid_sig'],'hash' => $r[0]['xchan_hash'])); + } + } + } } elseif($cmd === 'refresh_all') { logger('notifier: refresh_all: ' . $item_id); - $s = q("select * from channel where channel_id = %d limit 1", - intval($item_id) - ); - if($s) - $channel = $s[0]; $uid = $item_id; - $recipients = array(); + $channel = channelx_by_n($item_id); $r = q("select abook_xchan from abook where abook_channel = %d", intval($item_id) ); @@ -383,7 +298,7 @@ function notifier_run($argv, $argc){ $channel = $s[0]; if($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) { - logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}"); + logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING); return; } @@ -402,7 +317,7 @@ function notifier_run($argv, $argc){ return; if(strpos($r[0]['postopts'],'nodeliver') !== false) { - logger('notifier: target item is undeliverable', LOGGER_DEBUG); + logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE); return; } @@ -438,8 +353,8 @@ function notifier_run($argv, $argc){ // $cmd === 'relay' indicates the owner is sending it to the original recipients // don't allow the item in the relay command to relay to owner under any circumstances, it will loop - logger('notifier: relay_to_owner: ' . (($relay_to_owner) ? 'true' : 'false'), LOGGER_DATA); - logger('notifier: top_level_post: ' . (($top_level_post) ? 'true' : 'false'), LOGGER_DATA); + logger('notifier: relay_to_owner: ' . (($relay_to_owner) ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG); + logger('notifier: top_level_post: ' . (($top_level_post) ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG); // tag_deliver'd post which needs to be sent back to the original author @@ -464,9 +379,12 @@ function notifier_run($argv, $argc){ // if our parent is a tag_delivery recipient, uplink to the original author causing // a delivery fork. - if(intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) { - logger('notifier: uplinking this item'); - proc_run('php','include/notifier.php','uplink',$item_id); + if(($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) { + // don't uplink a relayed post to the relay owner + if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) { + logger('notifier: uplinking this item'); + proc_run('php','include/notifier.php','uplink',$item_id); + } } $private = false; @@ -478,7 +396,7 @@ function notifier_run($argv, $argc){ // TODO verify this is needed - copied logic from same place in old code if(intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) { - logger('notifier: ignoring delete notification for non-wall item'); + logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE); return; } } @@ -493,13 +411,13 @@ function notifier_run($argv, $argc){ $x = $encoded_item; $x['title'] = 'private'; $x['body'] = 'private'; - logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA); + logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG); stringify_array_elms($recipients); if(! $recipients) return; -// logger('notifier: recipients: ' . print_r($recipients,true)); +// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG); $env_recips = (($private) ? array() : null); @@ -527,7 +445,7 @@ function notifier_run($argv, $argc){ if(($private) && (! $env_recips)) { // shouldn't happen - logger('notifier: private message with no envelope recipients.' . print_r($argv,true)); + logger('notifier: private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE); } logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG); @@ -542,7 +460,7 @@ function notifier_run($argv, $argc){ if(! $r) { - logger('notifier: no hubs'); + logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE); return; } @@ -565,7 +483,7 @@ function notifier_run($argv, $argc){ foreach($hubs as $hub) { if(in_array($hub['hubloc_url'],$dead_hubs)) { - logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG); + logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG, LOG_INFO); continue; } @@ -585,7 +503,7 @@ function notifier_run($argv, $argc){ } } - logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG); + logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG); foreach($dhubs as $hub) { @@ -595,6 +513,7 @@ function notifier_run($argv, $argc){ $narr = array( 'channel' => $channel, 'env_recips' => $env_recips, + 'packet_recips' => $packet_recips, 'recipients' => $recipients, 'item' => $item, 'target_item' => $target_item, @@ -605,10 +524,8 @@ function notifier_run($argv, $argc){ 'relay_to_owner' => $relay_to_owner, 'uplink' => $uplink, 'cmd' => $cmd, - 'expire' => $expire, 'mail' => $mail, 'location' => $location, - 'fsuggest' => $fsuggest, 'request' => $request, 'normal_mode' => $normal_mode, 'packet_type' => $packet_type, @@ -628,52 +545,38 @@ function notifier_run($argv, $argc){ // default: zot protocol - $hash = random_string(); + $packet = null; + if($packet_type === 'refresh' || $packet_type === 'purge') { - $n = zot_build_packet($channel,$packet_type); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($channel['channel_account_id']), - intval($channel['channel_id']), - dbesc('zot'), - dbesc($hub['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc('') - ); + $packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null)); } elseif($packet_type === 'request') { - $n = zot_build_packet($channel,'request',$env_recips,$hub['hubloc_sitekey'],$hash,array('message_id' => $request_message_id)); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($channel['channel_account_id']), - intval($channel['channel_id']), - dbesc('zot'), - dbesc($hub['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc('') + $packet = zot_build_packet($channel,$packet_type,$env_recips,$hub['hubloc_sitekey'],$hash, + array('message_id' => $request_message_id) ); } + + if($packet) { + queue_insert(array( + 'hash' => $hash, + 'account_id' => $channel['channel_account_id'], + 'channel_id' => $channel['channel_id'], + 'posturl' => $hub['hubloc_callback'], + 'notify' => $packet + )); + } else { - $n = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($target_item['aid']), - intval($target_item['uid']), - dbesc('zot'), - dbesc($hub['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc(json_encode($encoded_item)) - ); + $packet = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash); + queue_insert(array( + 'hash' => $hash, + 'account_id' => $target_item['aid'], + 'channel_id' => $target_item['uid'], + 'posturl' => $hub['hubloc_callback'], + 'notify' => $packet, + 'msg' => json_encode($encoded_item) + )); + // only create delivery reports for normal undeleted items if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted'])) { q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ", diff --git a/include/oauth.php b/include/oauth.php index 80336f906..f3d144158 100644 --- a/include/oauth.php +++ b/include/oauth.php @@ -1,4 +1,5 @@ <?php /** @file */ + /** * OAuth server * Based on oauth2-php <http://code.google.com/p/oauth2-php/> @@ -9,16 +10,17 @@ define('REQUEST_TOKEN_DURATION', 300); define('ACCESS_TOKEN_DURATION', 31536000); require_once("library/OAuth1.php"); -require_once("library/oauth2-php/lib/OAuth2.inc"); -class FKOAuthDataStore extends OAuthDataStore { - function gen_token(){ +//require_once("library/oauth2-php/lib/OAuth2.inc"); + +class ZotOAuth1DataStore extends OAuth1DataStore { + + function gen_token(){ return md5(base64_encode(pack('N6', mt_rand(), mt_rand(), mt_rand(), mt_rand(), mt_rand(), uniqid()))); - } + } - function lookup_consumer($consumer_key) { - logger(__function__.":".$consumer_key); -// echo "<pre>"; var_dump($consumer_key); killme(); + function lookup_consumer($consumer_key) { + logger('consumer_key: ' . $consumer_key, LOGGER_DEBUG); $r = q("SELECT client_id, pw, redirect_uri FROM clients WHERE client_id = '%s'", dbesc($consumer_key) @@ -26,13 +28,14 @@ class FKOAuthDataStore extends OAuthDataStore { if($r) { get_app()->set_oauth_key($consumer_key); - return new OAuthConsumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']); + return new OAuth1Consumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']); } return null; - } + } - function lookup_token($consumer, $token_type, $token) { - logger(__function__.":".$consumer.", ". $token_type.", ".$token); + function lookup_token($consumer, $token_type, $token) { + + logger(__function__.":".$consumer.", ". $token_type.", ".$token, LOGGER_DEBUG); $r = q("SELECT id, secret, scope, expires, uid FROM tokens WHERE client_id = '%s' AND scope = '%s' AND id = '%s'", dbesc($consumer->key), @@ -41,17 +44,16 @@ class FKOAuthDataStore extends OAuthDataStore { ); if (count($r)){ - $ot=new OAuthToken($r[0]['id'],$r[0]['secret']); + $ot=new OAuth1Token($r[0]['id'],$r[0]['secret']); $ot->scope=$r[0]['scope']; $ot->expires = $r[0]['expires']; $ot->uid = $r[0]['uid']; return $ot; } return null; - } + } - function lookup_nonce($consumer, $token, $nonce, $timestamp) { -// echo __file__.":".__line__."<pre>"; var_dump($consumer,$key); killme(); + function lookup_nonce($consumer, $token, $nonce, $timestamp) { $r = q("SELECT id, secret FROM tokens WHERE client_id = '%s' AND id = '%s' AND expires = %d", dbesc($consumer->key), @@ -60,12 +62,14 @@ class FKOAuthDataStore extends OAuthDataStore { ); if (count($r)) - return new OAuthToken($r[0]['id'],$r[0]['secret']); + return new OAuth1Token($r[0]['id'],$r[0]['secret']); return null; - } + } + + function new_request_token($consumer, $callback = null) { + + logger(__function__.":".$consumer.", ". $callback, LOGGER_DEBUG); - function new_request_token($consumer, $callback = null) { - logger(__function__.":".$consumer.", ". $callback); $key = $this->gen_token(); $sec = $this->gen_token(); @@ -82,29 +86,31 @@ class FKOAuthDataStore extends OAuthDataStore { 'request', time()+intval(REQUEST_TOKEN_DURATION)); - if (!$r) return null; - return new OAuthToken($key,$sec); - } + if(! $r) + return null; + return new OAuth1Token($key,$sec); + } - function new_access_token($token, $consumer, $verifier = null) { - logger(__function__.":".$token.", ". $consumer.", ". $verifier); - - // return a new access token attached to this consumer - // for the user associated with this token if the request token - // is authorized - // should also invalidate the request token - - $ret=Null; + function new_access_token($token, $consumer, $verifier = null) { + + logger(__function__.":".$token.", ". $consumer.", ". $verifier, LOGGER_DEBUG); - // get user for this verifier - $uverifier = get_config("oauth", $verifier); - logger(__function__.":".$verifier.",".$uverifier); - if (is_null($verifier) || ($uverifier!==false)){ + // return a new access token attached to this consumer + // for the user associated with this token if the request token + // is authorized + // should also invalidate the request token + + $ret=Null; + + // get user for this verifier + $uverifier = get_config("oauth", $verifier); + logger(__function__.":".$verifier.",".$uverifier, LOGGER_DEBUG); + if (is_null($verifier) || ($uverifier!==false)) { - $key = $this->gen_token(); - $sec = $this->gen_token(); + $key = $this->gen_token(); + $sec = $this->gen_token(); - $r = q("INSERT INTO tokens (id, secret, client_id, scope, expires, uid) VALUES ('%s','%s','%s','%s', %d, %d)", + $r = q("INSERT INTO tokens (id, secret, client_id, scope, expires, uid) VALUES ('%s','%s','%s','%s', %d, %d)", dbesc($key), dbesc($sec), dbesc($consumer->key), @@ -112,81 +118,70 @@ class FKOAuthDataStore extends OAuthDataStore { time()+intval(ACCESS_TOKEN_DURATION), intval($uverifier)); - if ($r) - $ret = new OAuthToken($key,$sec); - } + if ($r) + $ret = new OAuth1Token($key,$sec); + } - q("DELETE FROM tokens WHERE id='%s'", $token->key); + q("DELETE FROM tokens WHERE id='%s'", $token->key); - if (!is_null($ret) && $uverifier!==false){ - del_config("oauth", $verifier); - /* $apps = get_pconfig($uverifier, "oauth", "apps"); - if ($apps===false) $apps=array(); - $apps[] = $consumer->key; - set_pconfig($uverifier, "oauth", "apps", $apps);*/ + if (!is_null($ret) && $uverifier!==false) { + del_config("oauth", $verifier); + + // $apps = get_pconfig($uverifier, "oauth", "apps"); + // if ($apps===false) $apps=array(); + // $apps[] = $consumer->key; + // set_pconfig($uverifier, "oauth", "apps", $apps); + } + return $ret; } - - return $ret; - - } } -class FKOAuth1 extends OAuthServer { +class ZotOAuth1 extends OAuth1Server { function __construct() { - parent::__construct(new FKOAuthDataStore()); - $this->add_signature_method(new OAuthSignatureMethod_PLAINTEXT()); - $this->add_signature_method(new OAuthSignatureMethod_HMAC_SHA1()); + parent::__construct(new ZotOAuth1DataStore()); + $this->add_signature_method(new OAuth1SignatureMethod_PLAINTEXT()); + $this->add_signature_method(new OAuth1SignatureMethod_HMAC_SHA1()); } function loginUser($uid){ - logger("RedOAuth1::loginUser $uid"); - $a = get_app(); + + logger("ZotOAuth1::loginUser $uid"); + $r = q("SELECT * FROM channel WHERE channel_id = %d LIMIT 1", intval($uid) ); if(count($r)){ $record = $r[0]; } else { - logger('FKOAuth1::loginUser failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); - header('HTTP/1.0 401 Unauthorized'); - die('This api requires login'); + logger('ZotOAuth1::loginUser failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); + header('HTTP/1.0 401 Unauthorized'); + echo('This api requires login'); + killme(); } $_SESSION['uid'] = $record['channel_id']; - $_SESSION['theme'] = $record['channel_theme']; - $_SESSION['account_id'] = $record['channel_account_id']; - $_SESSION['mobile_theme'] = get_pconfig($record['channel_id'], 'system', 'mobile_theme'); - $_SESSION['authenticated'] = 1; - $_SESSION['my_url'] = $a->get_baseurl() . '/channel/' . $record['channel_address']; $_SESSION['addr'] = $_SERVER['REMOTE_ADDR']; - $_SESSION['allow_api'] = true; + $x = q("select * from account where account_id = %d limit 1", intval($record['channel_account_id']) ); - if($x) - $a->account = $x[0]; - - change_channel($record['channel_id']); - - $a->channel = $record; - - if(strlen($a->channel['channel_timezone'])) { - date_default_timezone_set($a->channel['channel_timezone']); + if($x) { + require_once('include/security.php'); + authenticate_success($x[0],true,false,true,true); + $_SESSION['allow_api'] = true; } - -// q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1", -// dbesc(datetime_convert()), -// intval($_SESSION['uid']) -// ); -// -// call_hooks('logged_in', $a->user); } } + /* + * + + not yet used + class FKOAuth2 extends OAuth2 { private function db_secret($client_secret){ diff --git a/include/photos.php b/include/photos.php index c7360a956..93511d2c0 100644 --- a/include/photos.php +++ b/include/photos.php @@ -292,17 +292,35 @@ function photo_upload($channel, $observer, $args) { $tag = (($r2) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]'); } - $body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' + $author_link = '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $channel['channel_name'] . '[/zrl]'; + + $photo_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . t('a new photo') . '[/zrl]'; + + $album_link = '[zrl=' . z_root() . '/photos/album/' . bin2hex($album) . ']' . $album . '[/zrl]'; + + $activity_format = sprintf(t('%1$s posted %2$s to %3$s','photo_upload'), $author_link, $photo_link, $album_link); + + $summary = $activity_format . "\n\n" . (($args['body']) ? $args['body'] . "\n\n" : ''); + + $obj_body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]' . '[/zrl]'; // Create item object $object = array( - 'type' => ACTIVITY_OBJ_PHOTO, - 'title' => $title, - 'id' => rawurlencode(z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash), - 'link' => $link, - 'bbcode' => $body + 'type' => ACTIVITY_OBJ_PHOTO, + 'title' => $title, + 'created' => $p['created'], + 'edited' => $p['edited'], + 'id' => rawurlencode(z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash), + 'link' => $link, + 'body' => $obj_body + ); + + $target = array( + 'type' => ACTIVITY_OBJ_ALBUM, + 'title' => (($album) ? $album : '/'), + 'id' => rawurlencode(z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album)) ); // Create item container @@ -314,9 +332,12 @@ function photo_upload($channel, $observer, $args) { if($item['mid'] === $item['parent_mid']) { - $item['body'] = (($object) ? $args['body'] : $body . "\r\n" . $args['body']); - $item['obj_type'] = (($object) ? ACTIVITY_OBJ_PHOTO : ''); - $item['object'] = (($object) ? json_encode($object) : ''); + $item['body'] = $args['body']; + $item['obj_type'] = ACTIVITY_OBJ_PHOTO; + $item['object'] = json_encode($object); + + $item['tgt_type'] = ACTIVITY_OBJ_ALBUM; + $item['target'] = json_encode($target); if($item['author_xchan'] === $channel['channel_hash']) { $item['sig'] = base64url_encode(rsa_sign($item['body'],$channel['channel_prvkey'])); @@ -370,14 +391,16 @@ function photo_upload($channel, $observer, $args) { $arr['deny_cid'] = $ac['deny_cid']; $arr['deny_gid'] = $ac['deny_gid']; $arr['verb'] = ACTIVITY_POST; - $arr['obj_type'] = (($object) ? ACTIVITY_OBJ_PHOTO : ''); - $arr['object'] = (($object) ? json_encode($object) : ''); + $arr['obj_type'] = ACTIVITY_OBJ_PHOTO; + $arr['object'] = json_encode($object); + $arr['tgt_type'] = ACTIVITY_OBJ_ALBUM; + $arr['target'] = json_encode($target); $arr['item_wall'] = 1; $arr['item_origin'] = 1; $arr['item_thread_top'] = 1; $arr['item_private'] = intval($acl->is_private()); $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid']; - $arr['body'] = (($object) ? $args['body'] : $body . "\r\n" . $args['body']); + $arr['body'] = $summary; // this one is tricky because the item and the photo have the same permissions, those of the photo. @@ -402,7 +425,7 @@ function photo_upload($channel, $observer, $args) { $ret['success'] = true; $ret['item'] = $arr; - $ret['body'] = $body; + $ret['body'] = $obj_body; $ret['resource_id'] = $photo_hash; $ret['photoitem_id'] = $item_id; diff --git a/include/plugin.php b/include/plugin.php index 1d4caac0f..4da73dfd8 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -313,7 +313,6 @@ function call_hooks($name, &$data = null) { * * Version: 1.2.3 * * Author: John <profile url> * * Author: Jane <email> - * * Compat: Red [(version)], Friendica [(version)] * * *\endcode * @param string $plugin the name of the plugin @@ -325,8 +324,8 @@ function get_plugin_info($plugin){ 'name' => $plugin, 'description' => '', 'author' => array(), - 'version' => '', - 'compat' => '' + 'maintainer' => array(), + 'version' => '' ); if (!is_file("addon/$plugin/$plugin.php")) @@ -342,22 +341,23 @@ function get_plugin_info($plugin){ if ($l != ""){ list($k, $v) = array_map("trim", explode(":", $l, 2)); $k = strtolower($k); - if ($k == 'author'){ + if ($k == 'author' || $k == 'maintainer'){ $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { - $info['author'][] = array('name' => $m[1], 'link' => $m[2]); + $info[$k][] = array('name' => $m[1], 'link' => $m[2]); } else { - $info['author'][] = array('name' => $v); + $info[$k][] = array('name' => $v); } } else { - if (array_key_exists($k, $info)){ +// if (array_key_exists($k, $info)){ $info[$k] = $v; - } +// } } } } } + return $info; } @@ -495,6 +495,15 @@ function format_css_if_exists($source) { return '<link rel="stylesheet" href="' . script_path() . '/' . $path . '" type="text/css" media="' . $source[1] . '">' . "\r\n"; } +/* + * This basically calculates the baseurl. We have other functions to do that, but + * there was an issue with script paths and mixed-content whose details are arcane + * and perhaps lost in the message archives. The short answer is that we're ignoring + * the URL which we are "supposed" to use, and generating script paths relative to + * the URL which we are currently using; in order to ensure they are found and aren't + * blocked due to mixed content issues. + */ + function script_path() { if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) $scheme = 'https'; @@ -627,3 +636,13 @@ function get_std_version() { return STD_VERSION; return '0.0.0'; } + + +function folder_exists($folder) +{ + // Get canonicalized absolute pathname + $path = realpath($folder); + + // If it exist, check if it's a directory + return (($path !== false) && is_dir($path)) ? $path : false; +}
\ No newline at end of file diff --git a/include/queue.php b/include/queue.php index 71ac50c83..8a3b2aa58 100644 --- a/include/queue.php +++ b/include/queue.php @@ -18,11 +18,8 @@ function queue_run($argv, $argc){ else $queue_id = 0; - $deadguys = array(); - logger('queue: start'); - // delete all queue items more than 3 days old // but first mark these sites dead if we haven't heard from them in a month @@ -88,59 +85,7 @@ function queue_run($argv, $argc){ return; foreach($r as $rr) { - - $dresult = null; - - if(in_array($rr['outq_posturl'],$deadguys)) - continue; - - $base = ''; - $h = parse_url($rr['outq_posturl']); - if($h) - $base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : ''); - - if($rr['outq_driver'] === 'post') { - $result = z_post_url($rr['outq_posturl'],$rr['outq_msg']); - if($result['success'] && $result['return_code'] < 300) { - logger('queue: queue post success to ' . $rr['outq_posturl'], LOGGER_DEBUG); - if($base) { - q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ", - dbesc(datetime_convert()), - dbesc($base) - ); - } - q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s' limit 1", - dbesc('accepted for delivery'), - dbesc(datetime_convert()), - dbesc($rr['outq_hash']) - ); - $y = q("delete from outq where outq_hash = '%s'", - dbesc($rr['outq_hash']) - ); - } - else { - logger('queue: queue post returned ' . $result['return_code'] . ' from ' . $rr['outq_posturl'],LOGGER_DEBUG); - $y = q("update outq set outq_updated = '%s', outq_priority = outq_priority + 10 where outq_hash = '%s'", - dbesc(datetime_convert()), - dbesc($rr['outq_hash']) - ); - $deadguys[] = $rr['outq_posturl']; - } - continue; - } - $result = zot_zot($rr['outq_posturl'],$rr['outq_notify']); - if($result['success']) { - logger('queue: deliver zot success to ' . $rr['outq_posturl'], LOGGER_DEBUG); - zot_process_response($rr['outq_posturl'],$result, $rr); - } - else { - $deadguys[] = $rr['outq_posturl']; - logger('queue: deliver zot returned ' . $result['return_code'] . ' from ' . $rr['outq_posturl'],LOGGER_DEBUG); - $y = q("update outq set outq_updated = '%s', outq_priority = outq_priority + 10 where outq_hash = '%s'", - dbesc(datetime_convert()), - dbesc($rr['outq_hash']) - ); - } + queue_deliver($rr); } } diff --git a/include/queue_fn.php b/include/queue_fn.php index 22580bc48..0708aab56 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -1,18 +1,171 @@ <?php /** @file */ -function update_queue_time($id) { - logger('queue: requeue item ' . $id); - q("UPDATE outq SET outq_updated = '%s' WHERE outq_hash = '%s'", +function update_queue_item($id, $add_priority = 0) { + logger('queue: requeue item ' . $id,LOGGER_DEBUG); + q("UPDATE outq SET outq_updated = '%s', outq_priority = outq_priority + %d WHERE outq_hash = '%s'", dbesc(datetime_convert()), + intval($add_priority), dbesc($id) ); } -function remove_queue_item($id) { - logger('queue: remove queue item ' . $id); - q("DELETE FROM outq WHERE hash = '%s'", +function remove_queue_item($id,$channel_id = 0) { + logger('queue: remove queue item ' . $id,LOGGER_DEBUG); + $sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : ''); + + q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra", dbesc($id) ); } +function remove_queue_by_posturl($posturl) { + logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG); + + q("DELETE FROM outq WHERE outq_posturl = '%s' ", + dbesc($posturl) + ); +} + + + +function queue_set_delivered($id,$channel = 0) { + logger('queue: set delivered ' . $id,LOGGER_DEBUG); + $sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : ''); + + q("update outq set outq_delivered = 1, outq_updated = '%s' where outq_hash = '%s' $sql_extra ", + dbesc(datetime_convert()), + dbesc($id) + ); +} + + + +function queue_insert($arr) { + + $x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority, + outq_created, outq_updated, outq_notify, outq_msg ) + values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' )", + dbesc($arr['hash']), + intval($arr['account_id']), + intval($arr['channel_id']), + dbesc(($arr['driver']) ? $arr['driver'] : 'zot'), + dbesc($arr['posturl']), + intval(1), + intval(($arr['priority']) ? $arr['priority'] : 0), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($arr['notify']), + dbesc(($arr['msg']) ? $arr['msg'] : '') + ); + return $x; + +} + + + +function queue_deliver($outq, $immediate = false) { + + $base = null; + $h = parse_url($outq['outq_posturl']); + if($h) + $base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : ''); + + if(($base) && ($base !== z_root()) && ($immediate)) { + $y = q("select site_update, site_dead from site where site_url = '%s' ", + dbesc($base) + ); + if($y) { + if(intval($y[0]['site_dead'])) { + remove_queue_by_posturl($outq['outq_posturl']); + logger('dead site ignored ' . $base); + return; + } + if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) { + update_queue_item($outq['outq_hash'],10); + logger('immediate delivery deferred for site ' . $base); + return; + } + } + else { + + // zot sites should all have a site record, unless they've been dead for as long as + // your site has existed. Since we don't know for sure what these sites are, + // call them unknown + + q("insert into site (site_url, site_update, site_dead, site_type) values ('%s','%s',0,%d) ", + dbesc($base), + dbesc(datetime_convert()), + intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN) + ); + } + } + + $arr = array('outq' => $outq, 'handled' => false, 'immediate' => $immediate); + call_hooks('queue_deliver',$arr); + if($arr['handled']) + return; + + // "post" queue driver - used for diaspora and friendica-over-diaspora communications. + + if($outq['outq_driver'] === 'post') { + $result = z_post_url($outq['outq_posturl'],$outq['outq_msg']); + if($result['success'] && $result['return_code'] < 300) { + logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG); + if($base) { + q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ", + dbesc(datetime_convert()), + dbesc($base) + ); + } + q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s' limit 1", + dbesc('accepted for delivery'), + dbesc(datetime_convert()), + dbesc($outq['outq_hash']) + ); + remove_queue_item($outq['outq_hash']); + + // server is responding - see if anything else is going to this destination and is piled up + // and try to send some more. We're relying on the fact that delivery_loop() results in an + // immediate delivery otherwise we could get into a queue loop. + + if(! $immediate) { + $x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0", + dbesc($outq['outq_posturl']) + ); + + $piled_up = array(); + if($x) { + foreach($x as $xx) { + $piled_up[] = $xx['outq_hash']; + } + } + if($piled_up) { + delivery_loop($piled_up); + } + } + } + else { + logger('deliver: queue post returned ' . $result['return_code'] + . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG); + update_queue_item($outq['outq_posturl']); + } + return; + } + + // normal zot delivery + + logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG); + $result = zot_zot($outq['outq_posturl'],$outq['outq_notify']); + if($result['success']) { + logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']); + zot_process_response($outq['outq_posturl'],$result, $outq); + } + else { + logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']); + logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA); + update_queue_item($outq['outq_hash'],10); + } + return; +} + diff --git a/include/ratenotif.php b/include/ratenotif.php index 63fd7c2ee..e94f30247 100644 --- a/include/ratenotif.php +++ b/include/ratenotif.php @@ -82,18 +82,14 @@ function ratenotif_run($argv, $argc){ $hash = random_string(); $n = zot_build_packet($channel,'notify',null,null,$hash); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($channel['channel_account_id']), - intval($channel['channel_id']), - dbesc('zot'), - dbesc($h . '/post'), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc(json_encode($encoded_item)) - ); + queue_insert(array( + 'hash' => $hash, + 'account_id' => $channel['channel_account_id'], + 'channel_id' => $channel['channel_id'], + 'posturl' => $h . '/post', + 'notify' => $n, + 'msg' => json_encode($encoded_item) + )); $deliver[] = $hash; diff --git a/include/security.php b/include/security.php index 9a25d9e0e..d4ebe0024 100644 --- a/include/security.php +++ b/include/security.php @@ -93,6 +93,7 @@ function change_channel($change_channel) { $ret = false; if($change_channel) { + $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel_id = %d and channel_account_id = %d and channel_removed = 0 limit 1", intval($change_channel), intval(get_account_id()) @@ -136,14 +137,14 @@ function change_channel($change_channel) { } /** - * @brief Creates an addiontal SQL where statement to check permissions. + * @brief Creates an additional SQL where statement to check permissions. * * @param int $owner_id - * @param bool $remote_verified default false, not used at all - * @param string $groups this param is not used at all + * @param bool $remote_observer - if unset use current observer * * @return string additional SQL where statement */ + function permissions_sql($owner_id, $remote_observer = null) { $local_channel = local_channel(); @@ -208,8 +209,7 @@ function permissions_sql($owner_id, $remote_observer = null) { * @brief Creates an addiontal SQL where statement to check permissions for an item. * * @param int $owner_id - * @param bool $remote_verified default false, not used at all - * @param string $groups this param is not used at all + * @param bool $remote_observer, use current observer if unset * * @return string additional SQL where statement */ @@ -400,11 +400,9 @@ function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'f } -// Returns an array of group id's this contact is a member of. -// This array will only contain group id's related to the uid of this -// DFRN contact. They are *not* neccessarily unique across the entire site. +// Returns an array of group hash id's on this entire site (across all channels) that this connection is a member of. +// var $contact_id = xchan_hash of connection -if(! function_exists('init_groups_visitor')) { function init_groups_visitor($contact_id) { $groups = array(); $r = q("SELECT hash FROM `groups` left join group_member on groups.id = group_member.gid WHERE xchan = '%s' ", @@ -415,7 +413,7 @@ function init_groups_visitor($contact_id) { $groups[] = $rr['hash']; } return $groups; -}} +} diff --git a/include/text.php b/include/text.php index 4777e7a61..6f7297bb0 100644 --- a/include/text.php +++ b/include/text.php @@ -536,9 +536,10 @@ function attribute_contains($attr, $s) { * * @param string $msg Message to log * @param int $level A log level. + * @param int $priority - compatible with syslog */ -function logger($msg, $level = 0) { +function logger($msg, $level = LOGGER_NORMAL, $priority = LOG_INFO) { // turn off logger in install mode global $a; global $db; @@ -559,8 +560,8 @@ function logger($msg, $level = 0) { $where = basename($stack[0]['file']) . ':' . $stack[0]['line'] . ':' . $stack[1]['function'] . ': '; } - $s = datetime_convert() . ':' . session_id() . ' ' . $where . $msg . PHP_EOL; - $pluginfo = array('filename' => $logfile, 'loglevel' => $level, 'message' => $s,'logged' => false); + $s = datetime_convert() . ':' . log_priority_str($priority) . ':' . session_id() . ':' . $where . $msg . PHP_EOL; + $pluginfo = array('filename' => $logfile, 'loglevel' => $level, 'message' => $s,'priority' => $priority, 'logged' => false); call_hooks('logger',$pluginfo); @@ -568,6 +569,23 @@ function logger($msg, $level = 0) { @file_put_contents($pluginfo['filename'], $pluginfo['message'], FILE_APPEND); } +function log_priority_str($priority) { + $parr = array( + LOG_EMERG => 'LOG_EMERG', + LOG_ALERT => 'LOG_ALERT', + LOG_CRIT => 'LOG_CRIT', + LOG_ERR => 'LOG_ERR', + LOG_WARNING => 'LOG_WARNING', + LOG_NOTICE => 'LOG_NOTICE', + LOG_INFO => 'LOG_INFO', + LOG_DEBUG => 'LOG_DEBUG' + ); + + if($parr[$priority]) + return $parr[$priority]; + return 'LOG_UNDEFINED'; +} + /** * @brief This is a special logging facility for developers. * @@ -972,7 +990,7 @@ function get_mood_verbs() { 'tired' => t('tired'), 'perky' => t('perky'), 'angry' => t('angry'), - 'stupefied' => t('stupified'), + 'stupefied' => t('stupefied'), 'puzzled' => t('puzzled'), 'interested' => t('interested'), 'bitter' => t('bitter'), @@ -1416,20 +1434,14 @@ function format_event($jobject) { function prepare_body(&$item,$attach = false) { require_once('include/identity.php'); -// if($item['html']) { -// $s = bb_observer($item['html']); -// } -// else { - call_hooks('prepare_body_init', $item); -// unobscure($item); - $s = prepare_text($item['body'],$item['mimetype'], false); -// } + call_hooks('prepare_body_init', $item); $photo = ''; - $is_photo = (($item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false); + $is_photo = ((($item['verb'] === ACTIVITY_POST) && ($item['obj_type'] === ACTIVITY_OBJ_PHOTO)) ? true : false); if($is_photo) { + $object = json_decode($item['object'],true); // if original photo width is <= 640px prepend it to item body @@ -1444,6 +1456,8 @@ function prepare_body(&$item,$attach = false) { } } + $s = prepare_text($item['body'],$item['mimetype'], false); + $event = (($item['obj_type'] === ACTIVITY_OBJ_EVENT) ? format_event($item['object']) : false); $prep_arr = array( @@ -1602,6 +1616,16 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) { } +function create_export_photo_body(&$item) { + if(($item['verb'] === ACTIVITY_POST) && ($item['obj_type'] === ACTIVITY_OBJ_PHOTO)) { + $j = json_decode($item['object'],true); + if($j) { + $item['body'] .= "\n\n" . (($j['body']) ? $j['body'] : $j['bbcode']); + $item['sig'] = ''; + } + } +} + /** * zidify_callback() and zidify_links() work together to turn any HTML a tags with class="zrl" into zid links * These will typically be generated by a bbcode '[zrl]' tag. This is done inside prepare_text() rather than bbcode() diff --git a/include/widgets.php b/include/widgets.php index 89836f90c..4b14d6c94 100644 --- a/include/widgets.php +++ b/include/widgets.php @@ -1299,7 +1299,6 @@ function widget_album($args) { //edit album name $album_edit = null; - $photos = array(); if($r) { $twist = 'rotright'; @@ -1338,6 +1337,7 @@ function widget_album($args) { $o .= replace_macros($tpl, array( '$photos' => $photos, '$album' => (($title) ? $title : $album), + '$album_id' => rand(), '$album_edit' => array(t('Edit Album'), $album_edit), '$can_post' => false, '$upload' => array(t('Upload'), z_root() . '/photos/' . get_app()->profile['channel_address'] . '/upload/' . bin2hex($album)), diff --git a/include/zot.php b/include/zot.php index 6764072aa..a644bbd06 100644 --- a/include/zot.php +++ b/include/zot.php @@ -12,6 +12,7 @@ require_once('include/crypto.php'); require_once('include/items.php'); require_once('include/hubloc.php'); require_once('include/DReport.php'); +require_once('include/queue_fn.php'); /** @@ -141,7 +142,7 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot $data[$k] = $v; } - logger('zot_build_packet: ' . print_r($data,true), LOGGER_DATA); + logger('zot_build_packet: ' . print_r($data,true), LOGGER_DATA, LOG_DEBUG); // Hush-hush ultra top-secret mode @@ -193,7 +194,7 @@ function zot_finger($webbie, $channel = null, $autofallback = true) { logger('zot_finger: no address :' . $webbie); return array('success' => false); } - logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA); + logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA, LOG_DEBUG); // potential issue here; the xchan_addr points to the primary hub. // The webbie we were called with may not, so it might not be found @@ -210,7 +211,7 @@ function zot_finger($webbie, $channel = null, $autofallback = true) { if ($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') { logger('zot_finger: alternate network: ' . $webbie); - logger('url: '.$url.', net: '.var_export($r[0]['hubloc_network'],true), LOGGER_DATA); + logger('url: '.$url.', net: '.var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG); return array('success' => false); } } else { @@ -287,9 +288,9 @@ function zot_refresh($them, $channel = null, $force = false) { return true; } - logger('zot_refresh: them: ' . print_r($them,true), LOGGER_DATA); + logger('zot_refresh: them: ' . print_r($them,true), LOGGER_DATA, LOG_DEBUG); if ($channel) - logger('zot_refresh: channel: ' . print_r($channel,true), LOGGER_DATA); + logger('zot_refresh: channel: ' . print_r($channel,true), LOGGER_DATA, LOG_DEBUG); $url = null; @@ -352,7 +353,7 @@ function zot_refresh($them, $channel = null, $force = false) { $result = z_post_url($url . $rhs,$postvars); - logger('zot_refresh: zot-info: ' . print_r($result,true), LOGGER_DATA); + logger('zot_refresh: zot-info: ' . print_r($result,true), LOGGER_DATA, LOG_DEBUG); if ($result['success']) { @@ -380,7 +381,7 @@ function zot_refresh($them, $channel = null, $force = false) { $channel['channel_prvkey']); if($permissions) $permissions = json_decode($permissions,true); - logger('decrypted permissions: ' . print_r($permissions,true), LOGGER_DATA); + logger('decrypted permissions: ' . print_r($permissions,true), LOGGER_DATA, LOG_DEBUG); } else $permissions = $j['permissions']; @@ -613,7 +614,7 @@ function zot_register_hub($arr) { $x = z_fetch_url($url); - logger('zot_register_hub: ' . print_r($x,true), LOGGER_DATA); + logger('zot_register_hub: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG); if($x['success']) { $record = json_decode($x['body'],true); @@ -753,8 +754,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { dbesc($xchan_hash) ); - logger('import_xchan: update: existing: ' . print_r($r[0],true), LOGGER_DATA); - logger('import_xchan: update: new: ' . print_r($arr,true), LOGGER_DATA); + logger('import_xchan: update: existing: ' . print_r($r[0],true), LOGGER_DATA, LOG_DEBUG); + logger('import_xchan: update: new: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); $what .= 'xchan '; $changed = true; } @@ -954,7 +955,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $ret['hash'] = $xchan_hash; } - logger('import_xchan: result: ' . print_r($ret,true), LOGGER_DATA); + logger('import_xchan: result: ' . print_r($ret,true), LOGGER_DATA, LOG_DEBUG); return $ret; } @@ -979,7 +980,7 @@ function zot_process_response($hub, $arr, $outq) { if (! $x) { logger('zot_process_response: No json from ' . $hub); - logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA); + logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA, LOG_DEBUG); } if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { @@ -997,7 +998,9 @@ function zot_process_response($hub, $arr, $outq) { } } - q("delete from dreport where dreport_queue = '%s' limit 1", + // we have a more descriptive delivery report, so discard the per hub 'queued' report. + + q("delete from dreport where dreport_queue = '%s' ", dbesc($outq['outq_hash']) ); @@ -1011,18 +1014,8 @@ function zot_process_response($hub, $arr, $outq) { // synchronous message types are handled immediately // async messages remain in the queue until processed. - if (intval($outq['outq_async'])) { - q("update outq set outq_delivered = 1, outq_updated = '%s' where outq_hash = '%s' and outq_channel = %d", - dbesc(datetime_convert()), - dbesc($outq['outq_hash']), - intval($outq['outq_channel']) - ); - } else { - q("delete from outq where outq_hash = '%s' and outq_channel = %d", - dbesc($outq['outq_hash']), - intval($outq['outq_channel']) - ); - } + if(intval($outq['outq_async'])) + remove_queue_item($outq['outq_hash'],$outq['outq_channel']); logger('zot_process_response: ' . print_r($x,true), LOGGER_DEBUG); } @@ -1044,7 +1037,7 @@ function zot_process_response($hub, $arr, $outq) { */ function zot_fetch($arr) { - logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA); + logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); $url = $arr['sender']['url'] . $arr['callback']; @@ -1141,7 +1134,7 @@ function zot_import($arr, $sender_url) { $i['notify'] = json_decode(crypto_unencapsulate($i['notify'],get_config('system','prvkey')),true); } - logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA); + logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG); $hub = zot_gethub($i['notify']['sender']); if((! $hub) || ($hub['hubloc_url'] != $sender_url)) { @@ -1158,7 +1151,7 @@ function zot_import($arr, $sender_url) { if(array_key_exists('message',$i) && array_key_exists('type',$i['message']) && $i['message']['type'] === 'rating') { // rating messages are processed only by directory servers - logger('Rating received: ' . print_r($arr,true), LOGGER_DATA); + logger('Rating received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); $result = process_rating_delivery($i['notify']['sender'],$i['message']); continue; } @@ -1268,8 +1261,8 @@ function zot_import($arr, $sender_url) { continue; } - logger('Activity received: ' . print_r($arr,true), LOGGER_DATA); - logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA); + logger('Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG); $relay = ((array_key_exists('flags',$i['message']) && in_array('relay',$i['message']['flags'])) ? true : false); $result = process_delivery($i['notify']['sender'],$arr,$deliveries,$relay,false,$message_request); @@ -1277,16 +1270,16 @@ function zot_import($arr, $sender_url) { elseif($i['message']['type'] === 'mail') { $arr = get_mail_elements($i['message']); - logger('Mail received: ' . print_r($arr,true), LOGGER_DATA); - logger('Mail recipients: ' . print_r($deliveries,true), LOGGER_DATA); + logger('Mail received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Mail recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG); $result = process_mail_delivery($i['notify']['sender'],$arr,$deliveries); } elseif($i['message']['type'] === 'profile') { $arr = get_profile_elements($i['message']); - logger('Profile received: ' . print_r($arr,true), LOGGER_DATA); - logger('Profile recipients: ' . print_r($deliveries,true), LOGGER_DATA); + logger('Profile received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Profile recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG); $result = process_profile_delivery($i['notify']['sender'],$arr,$deliveries); } @@ -1295,16 +1288,16 @@ function zot_import($arr, $sender_url) { $arr = $i['message']; - logger('Channel sync received: ' . print_r($arr,true), LOGGER_DATA); - logger('Channel sync recipients: ' . print_r($deliveries,true), LOGGER_DATA); + logger('Channel sync received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Channel sync recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG); $result = process_channel_sync_delivery($i['notify']['sender'],$arr,$deliveries); } elseif($i['message']['type'] === 'location') { $arr = $i['message']; - logger('Location message received: ' . print_r($arr,true), LOGGER_DATA); - logger('Location message recipients: ' . print_r($deliveries,true), LOGGER_DATA); + logger('Location message received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Location message recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG); $result = process_location_delivery($i['notify']['sender'],$arr,$deliveries); } @@ -1490,7 +1483,7 @@ function public_recips($msg) { } } - logger('public_recips: ' . print_r($r,true), LOGGER_DATA); + logger('public_recips: ' . print_r($r,true), LOGGER_DATA, LOG_DEBUG); return $r; } @@ -1508,7 +1501,7 @@ function public_recips($msg) { */ function allowed_public_recips($msg) { - logger('allowed_public_recips: ' . print_r($msg,true),LOGGER_DATA); + logger('allowed_public_recips: ' . print_r($msg,true),LOGGER_DATA, LOG_DEBUG); if(array_key_exists('public_scope',$msg['message'])) $scope = $msg['message']['public_scope']; @@ -1611,6 +1604,14 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $channel = $r[0]; $DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>'); + /* blacklisted channels get a permission denied, no special message to tip them off */ + + if(! check_channelallowed($sender['hash'])) { + $DR->update('permission denied'); + $result[] = $DR->get(); + continue; + } + /** * @FIXME: Somehow we need to block normal message delivery from our clones, as the delivered * message doesn't have ACL information in it as the cloned copy does. That copy @@ -2082,6 +2083,14 @@ function process_mail_delivery($sender, $arr, $deliveries) { $channel = $r[0]; $DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>'); + /* blacklisted channels get a permission denied, no special message to tip them off */ + + if(! check_channelallowed($sender['hash'])) { + $DR->update('permission denied'); + $result[] = $DR->get(); + continue; + } + if(! perm_is_allowed($channel['channel_id'],$sender['hash'],'post_mail')) { logger("permission denied for mail delivery {$channel['channel_id']}"); $DR->update('permission denied'); @@ -2864,7 +2873,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { logger('build_sync_packet'); if($packet) - logger('packet: ' . print_r($packet, true),LOGGER_DATA); + logger('packet: ' . print_r($packet, true),LOGGER_DATA, LOG_DEBUG); if(! $uid) $uid = local_channel(); @@ -2958,24 +2967,19 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { $interval = ((get_config('system','delivery_interval') !== false) ? intval(get_config('system','delivery_interval')) : 2 ); - - logger('build_sync_packet: packet: ' . print_r($info,true), LOGGER_DATA); + logger('build_sync_packet: packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG); foreach($synchubs as $hub) { $hash = random_string(); $n = zot_build_packet($channel,'notify',$env_recips,$hub['hubloc_sitekey'],$hash); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($channel['channel_account']), - intval($channel['channel_id']), - dbesc('zot'), - dbesc($hub['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc(json_encode($info)) - ); + queue_insert(array( + 'hash' => $hash, + 'account_id' => $channel['channel_account_id'], + 'channel_id' => $channel['channel_id'], + 'posturl' => $hub['hubloc_callback'], + 'notify' => $n, + 'msg' => json_encode($info) + )); proc_run('php', 'include/deliver.php', $hash); if($interval) @@ -3478,13 +3482,13 @@ function import_author_zot($x) { * @param array $data * @return array */ -function zot_process_message_request($data) { +function zot_reply_message_request($data) { $ret = array('success' => false); if (! $data['message_id']) { $ret['message'] = 'no message_id'; logger('no message_id'); - return $ret; + json_return_and_die($ret); } $sender = $data['sender']; @@ -3502,7 +3506,7 @@ function zot_process_message_request($data) { if (! $c) { logger('recipient channel not found.'); $ret['message'] .= 'recipient not found.' . EOL; - return $ret; + json_return_and_die($ret); } /* @@ -3514,13 +3518,13 @@ function zot_process_message_request($data) { if ($messages) { $env_recips = null; - $r = q("select * from hubloc where hubloc_hash = '%s' and not hubloc_error and not hubloc_deleted + $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0 group by hubloc_sitekey", dbesc($sender_hash) ); if (! $r) { logger('no hubs'); - return $ret; + json_return_and_die($ret); } $hubs = $r; @@ -3538,20 +3542,15 @@ function zot_process_message_request($data) { */ $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id'])); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, - outq_created, outq_updated, outq_notify, outq_msg ) - values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($c[0]['channel_account_id']), - intval($c[0]['channel_id']), - dbesc('zot'), - dbesc($hub['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc($data_packet) - ); + + queue_insert(array( + 'hash' => $hash, + 'account_id' => $c[0]['channel_account_id'], + 'channel_id' => $c[0]['channel_id'], + 'posturl' => $hub['hubloc_callback'], + 'notify' => $n, + 'msg' => $data_packet + )); /* * invoke delivery to send out the notify packet @@ -3561,8 +3560,7 @@ function zot_process_message_request($data) { } } $ret['success'] = true; - - return $ret; + json_return_and_die($ret); } @@ -3783,6 +3781,7 @@ function zotinfo($arr) { $ret['site'] = array(); $ret['site']['url'] = z_root(); $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey'])); + $ret['site']['zot_auth'] = z_root() . '/magic'; $dirmode = get_config('system','directory_mode'); if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL)) @@ -3865,7 +3864,7 @@ function zotinfo($arr) { function check_zotinfo($channel,$locations,&$ret) { -// logger('locations: ' . print_r($locations,true),LOGGER_DATA); +// logger('locations: ' . print_r($locations,true),LOGGER_DATA, LOG_DEBUG); // This function will likely expand as we find more things to detect and fix. // 1. Because magic-auth is reliant on it, ensure that the system channel has a valid hubloc @@ -3973,3 +3972,420 @@ function delivery_report_is_storable($dr) { } + +function update_hub_connected($hub,$sitekey = '') { + + if($sitekey) { + + /* + * This hub has now been proven to be valid. + * Any hub with the same URL and a different sitekey cannot be valid. + * Get rid of them (mark them deleted). There's a good chance they were re-installs. + */ + + q("update hubloc set hubloc_deleted = 1, hubloc_error = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' ", + dbesc($hub['hubloc_url']), + dbesc($sitekey) + ); + + } + else { + $sitekey = $hub['sitekey']; + } + + // $sender['sitekey'] is a new addition to the protcol to distinguish + // hublocs coming from re-installed sites. Older sites will not provide + // this field and we have to still mark them valid, since we can't tell + // if this hubloc has the same sitekey as the packet we received. + + + // Update our DB to show when we last communicated successfully with this hub + // This will allow us to prune dead hubs from using up resources + + $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_sitekey = '%s' ", + dbesc(datetime_convert()), + intval($hub['hubloc_id']), + dbesc($sitekey) + ); + + // a dead hub came back to life - reset any tombstones we might have + + if(intval($hub['hubloc_error'])) { + q("update hubloc set hubloc_error = 0 where hubloc_id = %d and hubloc_sitekey = '%s' ", + intval($hub['hubloc_id']), + dbesc($sitekey) + ); + if(intval($r[0]['hubloc_orphancheck'])) { + q("update hubloc set hubloc_orhpancheck = 0 where hubloc_id = %d and hubloc_sitekey = '%s' ", + intval($hub['hubloc_id']), + dbesc($sitekey) + ); + } + q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'", + dbesc($hub['hubloc_hash']) + ); + } + + return $hub['hubloc_url']; +} + + +function zot_reply_ping() { + + $ret = array('success'=> false); + + // Useful to get a health check on a remote site. + // This will let us know if any important communication details + // that we may have stored are no longer valid, regardless of xchan details. + logger('POST: got ping send pong now back: ' . z_root() , LOGGER_DEBUG ); + + $ret['success'] = true; + $ret['site'] = array(); + $ret['site']['url'] = z_root(); + $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),get_config('system','prvkey'))); + $ret['site']['sitekey'] = get_config('system','pubkey'); + json_return_and_die($ret); +} + +function zot_reply_pickup($data) { + + $ret = array('success'=> false); + + /* + * The 'pickup' message arrives with a tracking ID which is associated with a particular outq_hash + * First verify that that the returned signatures verify, then check that we have an outbound queue item + * with the correct hash. + * If everything verifies, find any/all outbound messages in the queue for this hubloc and send them back + */ + + if((! $data['secret']) || (! $data['secret_sig'])) { + $ret['message'] = 'no verification signature'; + logger('mod_zot: pickup: ' . $ret['message'], LOGGER_DEBUG); + json_return_and_die($ret); + } + + $r = q("select distinct hubloc_sitekey from hubloc where hubloc_url = '%s' and hubloc_callback = '%s' and hubloc_sitekey != '' group by hubloc_sitekey ", + dbesc($data['url']), + dbesc($data['callback']) + ); + if(! $r) { + $ret['message'] = 'site not found'; + logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); + } + + foreach ($r as $hubsite) { + + // verify the url_sig + // If the server was re-installed at some point, there could be multiple hubs with the same url and callback. + // Only one will have a valid key. + + $forgery = true; + $secret_fail = true; + + $sitekey = $hubsite['hubloc_sitekey']; + + logger('mod_zot: Checking sitekey: ' . $sitekey, LOGGER_DATA, LOG_DEBUG); + + if(rsa_verify($data['callback'],base64url_decode($data['callback_sig']),$sitekey)) { + $forgery = false; + } + if(rsa_verify($data['secret'],base64url_decode($data['secret_sig']),$sitekey)) { + $secret_fail = false; + } + if((! $forgery) && (! $secret_fail)) + break; + } + + if($forgery) { + $ret['message'] = 'possible site forgery'; + logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); + } + + if($secret_fail) { + $ret['message'] = 'secret validation failed'; + logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); + } + + /* + * If we made it to here, the signatures verify, but we still don't know if the tracking ID is valid. + * It wouldn't be an error if the tracking ID isn't found, because we may have sent this particular + * queue item with another pickup (after the tracking ID for the other pickup was verified). + */ + + $r = q("select outq_posturl from outq where outq_hash = '%s' and outq_posturl = '%s' limit 1", + dbesc($data['secret']), + dbesc($data['callback']) + ); + if(! $r) { + $ret['message'] = 'nothing to pick up'; + logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); + } + + /* + * Everything is good if we made it here, so find all messages that are going to this location + * and send them all. + */ + + $r = q("select * from outq where outq_posturl = '%s'", + dbesc($data['callback']) + ); + if($r) { + logger('mod_zot: successful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG); + + $ret['success'] = true; + $ret['pickup'] = array(); + foreach($r as $rr) { + if($rr['outq_msg']) { + $x = json_decode($rr['outq_msg'],true); + + if(! $x) + continue; + + if(is_array($x) && array_key_exists('message_list',$x)) { + foreach($x['message_list'] as $xx) { + $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => $xx); + } + } + else + $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => $x); + + remove_queue_item($rr['outq_hash']); + } + } + } + + $encrypted = crypto_encapsulate(json_encode($ret),$sitekey); + json_return_and_die($encrypted); + + /* pickup: end */ +} + + + +function zot_reply_auth_check($data,$encrypted_packet) { + + $ret = array('success' => false); + + /* + * Requestor visits /magic/?dest=somewhere on their own site with a browser + * magic redirects them to $destsite/post [with auth args....] + * $destsite sends an auth_check packet to originator site + * The auth_check packet is handled here by the originator's site + * - the browser session is still waiting + * inside $destsite/post for everything to verify + * If everything checks out we'll return a token to $destsite + * and then $destsite will verify the token, authenticate the browser + * session and then redirect to the original destination. + * If authentication fails, the redirection to the original destination + * will still take place but without authentication. + */ + logger('mod_zot: auth_check', LOGGER_DEBUG); + + if (! $encrypted_packet) { + logger('mod_zot: auth_check packet was not encrypted.'); + $ret['message'] .= 'no packet encryption' . EOL; + json_return_and_die($ret); + } + + $arr = $data['sender']; + $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); + + // garbage collect any old unused notifications + + // This was and should be 10 minutes but my hosting provider has time lag between the DB and + // the web server. We should probably convert this to webserver time rather than DB time so + // that the different clocks won't affect it and allow us to keep the time short. + + q("delete from verify where type = 'auth' and created < %s - INTERVAL %s", + db_utcnow(), db_quoteinterval('30 MINUTE') + ); + + $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", + dbesc($sender_hash) + ); + + // We created a unique hash in mod/magic.php when we invoked remote auth, and stored it in + // the verify table. It is now coming back to us as 'secret' and is signed by a channel at the other end. + // First verify their signature. We will have obtained a zot-info packet from them as part of the sender + // verification. + + if ((! $y) || (! rsa_verify($data['secret'], base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { + logger('mod_zot: auth_check: sender not found or secret_sig invalid.'); + $ret['message'] .= 'sender not found or sig invalid ' . print_r($y,true) . EOL; + json_return_and_die($ret); + } + + // There should be exactly one recipient, the original auth requestor + + $ret['message'] .= 'recipients ' . print_r($recipients,true) . EOL; + + if ($data['recipients']) { + + $arr = $data['recipients'][0]; + $recip_hash = make_xchan_hash($arr['guid'], $arr['guid_sig']); + $c = q("select channel_id, channel_account_id, channel_prvkey from channel where channel_hash = '%s' limit 1", + dbesc($recip_hash) + ); + if (! $c) { + logger('mod_zot: auth_check: recipient channel not found.'); + $ret['message'] .= 'recipient not found.' . EOL; + json_return_and_die($ret); + } + + $confirm = base64url_encode(rsa_sign($data['secret'] . $recip_hash,$c[0]['channel_prvkey'])); + + // This additionally checks for forged sites since we already stored the expected result in meta + // and we've already verified that this is them via zot_gethub() and that their key signed our token + + $z = q("select id from verify where channel = %d and type = 'auth' and token = '%s' and meta = '%s' limit 1", + intval($c[0]['channel_id']), + dbesc($data['secret']), + dbesc($data['sender']['url']) + ); + if (! $z) { + logger('mod_zot: auth_check: verification key not found.'); + $ret['message'] .= 'verification key not found' . EOL; + json_return_and_die($ret); + } + $r = q("delete from verify where id = %d", + intval($z[0]['id']) + ); + + $u = q("select account_service_class from account where account_id = %d limit 1", + intval($c[0]['channel_account_id']) + ); + + logger('mod_zot: auth_check: success', LOGGER_DEBUG); + $ret['success'] = true; + $ret['confirm'] = $confirm; + if ($u && $u[0]['account_service_class']) + $ret['service_class'] = $u[0]['account_service_class']; + + // Set "do not track" flag if this site or this channel's profile is restricted + // in some way + + if (intval(get_config('system','block_public'))) + $ret['DNT'] = true; + if (! perm_is_allowed($c[0]['channel_id'],'','view_profile')) + $ret['DNT'] = true; + if (get_pconfig($c[0]['channel_id'],'system','do_not_track')) + $ret['DNT'] = true; + if (get_pconfig($c[0]['channel_id'],'system','hide_online_status')) + $ret['DNT'] = true; + + json_return_and_die($ret); + } + json_return_and_die($ret); +} + + +function zot_reply_purge($sender,$recipients) { + + $ret = array('success' => false); + + if ($recipients) { + // basically this means "unfriend" + foreach ($recipients as $recip) { + $r = q("select channel.*,xchan.* from channel + left join xchan on channel_hash = xchan_hash + where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", + dbesc($recip['guid']), + dbesc($recip['guid_sig']) + ); + if ($r) { + $r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1", + intval($r[0]['channel_id']), + dbesc(make_xchan_hash($sender['guid'],$sender['guid_sig'])) + ); + if ($r) { + contact_remove($r[0]['channel_id'],$r[0]['abook_id']); + } + } + } + $ret['success'] = true; + } + else { + // Unfriend everybody - basically this means the channel has committed suicide + $arr = $sender; + $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); + + require_once('include/Contact.php'); + remove_all_xchan_resources($sender_hash); + + $ret['success'] = true; + } + + json_return_and_die($ret); +} + + +function zot_reply_refresh($sender,$recipients) { + + $ret = array('success' => false); + + // remote channel info (such as permissions or photo or something) + // has been updated. Grab a fresh copy and sync it. + // The difference between refresh and force_refresh is that + // force_refresh unconditionally creates a directory update record, + // even if no changes were detected upon processing. + + if($recipients) { + + // This would be a permissions update, typically for one connection + + foreach ($recipients as $recip) { + $r = q("select channel.*,xchan.* from channel + left join xchan on channel_hash = xchan_hash + where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", + dbesc($recip['guid']), + dbesc($recip['guid_sig']) + ); + + $x = zot_refresh(array( + 'xchan_guid' => $sender['guid'], + 'xchan_guid_sig' => $sender['guid_sig'], + 'hubloc_url' => $sender['url'] + ), $r[0], (($msgtype === 'force_refresh') ? true : false)); + } + } + else { + // system wide refresh + + $x = zot_refresh(array( + 'xchan_guid' => $sender['guid'], + 'xchan_guid_sig' => $sender['guid_sig'], + 'hubloc_url' => $sender['url'] + ), null, (($msgtype === 'force_refresh') ? true : false)); + } + + $ret['success'] = true; + json_return_and_die($ret); + +} + + +function zot_reply_notify($data) { + + $ret = array('success' => false); + + logger('notify received from ' . $data['sender']['url']); + + $async = get_config('system','queued_fetch'); + + if($async) { + // add to receive queue + // qreceive_add($data); + } + else { + $x = zot_fetch($data); + $ret['delivery_report'] = $x; + } + + $ret['success'] = true; + json_return_and_die($ret); + +}
\ No newline at end of file |