diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/Contact.php | 15 | ||||
-rw-r--r-- | include/Scrape.php | 2 | ||||
-rw-r--r-- | include/acl_selectors.php | 4 | ||||
-rw-r--r-- | include/api.php | 2 | ||||
-rw-r--r-- | include/cache.php | 42 | ||||
-rw-r--r-- | include/contact_widgets.php | 56 | ||||
-rw-r--r-- | include/dba.php | 28 | ||||
-rw-r--r-- | include/delivery.php | 11 | ||||
-rw-r--r-- | include/enotify.php | 4 | ||||
-rw-r--r-- | include/gprobe.php | 65 | ||||
-rw-r--r-- | include/items.php | 103 | ||||
-rw-r--r-- | include/network.php | 6 | ||||
-rw-r--r-- | include/notifier.php | 11 | ||||
-rw-r--r-- | include/onepoll.php | 519 | ||||
-rw-r--r-- | include/plugin.php | 12 | ||||
-rw-r--r-- | include/poller.php | 450 | ||||
-rw-r--r-- | include/profile_selectors.php | 18 | ||||
-rw-r--r-- | include/socgraph.php | 91 | ||||
-rw-r--r-- | include/text.php | 18 |
19 files changed, 917 insertions, 540 deletions
diff --git a/include/Contact.php b/include/Contact.php index 537850e00..2523fc023 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -51,6 +51,21 @@ function user_remove($uid) { function contact_remove($id) { + + $r = q("select uid from contact where id = %d limit 1", + intval($id) + ); + if((! count($r)) || (! intval($r[0]['uid']))) + return; + + $archive = get_pconfig($r[0]['uid'], 'system','archive_removed_contacts'); + if($archive) { + q("update contact set `archive` = 1, `network` = 'none', `writable` = 0 where id = %d limit 1", + intval($id) + ); + return; + } + q("DELETE FROM `contact` WHERE `id` = %d LIMIT 1", intval($id) ); diff --git a/include/Scrape.php b/include/Scrape.php index b20d7d604..227252600 100644 --- a/include/Scrape.php +++ b/include/Scrape.php @@ -282,7 +282,7 @@ function scrape_feed($url) { } } if(! $basename) - $basename = substr($url,0,strrpos($url,'/')) . '/'; + $basename = implode('/', array_slice(explode('/',$url),0,3)) . '/'; $items = $dom->getElementsByTagName('link'); diff --git a/include/acl_selectors.php b/include/acl_selectors.php index a5f5aff53..461ad0c36 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -122,7 +122,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) { $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"" . $x['size'] . "$\" $tabindex >\r\n"; $r = q("SELECT `id`, `name`, `url`, `network` FROM `contact` - WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `notify` != '' + WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != '' $sql_extra ORDER BY `name` ASC ", intval(local_user()) @@ -188,7 +188,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" $tabindex >\r\n"; $r = q("SELECT `id`, `name`, `url`, `network` FROM `contact` - WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `notify` != '' + WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != '' $sql_extra ORDER BY `name` ASC ", intval(local_user()) diff --git a/include/api.php b/include/api.php index f9be68c3d..a693a32c8 100644 --- a/include/api.php +++ b/include/api.php @@ -380,7 +380,7 @@ $nick = $name; // Generating a random ID - if (!array_key_exists($nick, $usercache)) + if (is_null($usercache[$nick]) or !array_key_exists($nick, $usercache)) $usercache[$nick] = mt_rand(2000000, 2100000); $ret = array( diff --git a/include/cache.php b/include/cache.php index 3c8a3f713..360c4acbd 100644 --- a/include/cache.php +++ b/include/cache.php @@ -14,22 +14,40 @@ } public static function set($key,$value) { - $r = q("SELECT * FROM `cache` WHERE `k`='%s' limit 1", - dbesc($key) - ); - if(count($r)) { - q("UPDATE `cache` SET `v` = '%s', `updated = '%s' WHERE `k` = '%s' limit 1", - dbesc($value), - dbesc(datetime_convert()), - dbesc($key)); - } - else { - q("INSERT INTO `cache` (`k`,`v`,`updated`) VALUES ('%s','%s','%s')", + + q("REPLACE INTO `cache` (`k`,`v`,`updated`) VALUES ('%s','%s','%s')", dbesc($key), dbesc($value), dbesc(datetime_convert())); - } } + + +/* + * + * Leaving this legacy code temporaily to see how REPLACE fares + * as opposed to non-atomic checks when faced with fast moving key duplication. + * As a MySQL extension it isn't portable, but we're not yet very portable. + */ + +/* + * $r = q("SELECT * FROM `cache` WHERE `k`='%s' limit 1", + * dbesc($key) + * ); + * if(count($r)) { + * q("UPDATE `cache` SET `v` = '%s', `updated = '%s' WHERE `k` = '%s' limit 1", + * dbesc($value), + * dbesc(datetime_convert()), + * dbesc($key)); + * } + * else { + * q("INSERT INTO `cache` (`k`,`v`,`updated`) VALUES ('%s','%s','%s')", + * dbesc($key), + * dbesc($value), + * dbesc(datetime_convert())); + * } + * } + */ + public static function clear(){ q("DELETE FROM `cache` WHERE `updated` < '%s'", diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 96b02f293..42d3afdee 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -133,3 +133,59 @@ function categories_widget($baseurl,$selected = '') { )); } +function common_friends_visitor_widget($profile_uid) { + + $a = get_app(); + + if(local_user() == $profile_uid) + return; + + $cid = $zcid = 0; + + if(can_write_wall($a,$profile_uid)) + $cid = remote_user(); + else { + if(get_my_url()) { + $r = q("select id from contact where nurl = '%s' and uid = %d limit 1", + dbesc(normalise_link(get_my_url())), + intval($profile_uid) + ); + if(count($r)) + $cid = $r[0]['id']; + else { + $r = q("select id from gcontact where nurl = '%s' limit 1", + dbesc(normalise_link(get_my_url())) + ); + if(count($r)) + $zcid = $r[0]['id']; + } + } + } + + if($cid == 0 && $zcid == 0) + return; + + require_once('include/socgraph.php'); + + if($cid) + $t = count_common_friends($profile_uid,$cid); + else + $t = count_common_friends_zcid($profile_uid,$zcid); + if(! $t) + return; + + if($cid) + $r = common_friends($profile_uid,$cid,0,5,true); + else + $r = common_friends_zcid($profile_uid,$zcid,0,5,true); + + return replace_macros(get_markup_template('remote_friends_common.tpl'), array( + '$desc' => sprintf( tt("%d contact in common", "%d contacts in common", $t), $t), + '$base' => $a->get_baseurl(), + '$uid' => $profile_uid, + '$cid' => $cid, + '$more' => t('show more'), + '$items' => $r + )); + +};
\ No newline at end of file diff --git a/include/dba.php b/include/dba.php index 44a663eac..c9f880241 100644 --- a/include/dba.php +++ b/include/dba.php @@ -75,22 +75,28 @@ class dba { if((! $this->db) || (! $this->connected)) return false; + $this->error = ''; + if($this->mysqli) $result = @$this->db->query($sql); else $result = @mysql_query($sql,$this->db); + if($this->mysqli) { + if($this->db->errno) + $this->error = $this->db->error; + } + elseif(mysql_errno($this->db)) + $this->error = mysql_error($this->db); + + if(strlen($this->error)) { + logger('dba: ' . $this->error); + } + if($this->debug) { $mesg = ''; - if($this->mysqli) { - if($this->db->errno) - logger('dba: ' . $this->db->error); - } - elseif(mysql_errno($this->db)) - logger('dba: ' . mysql_error($this->db)); - if($result === false) $mesg = 'false'; elseif($result === true) @@ -102,7 +108,9 @@ class dba { $mesg = mysql_num_rows($result) . ' results' . EOL; } - $str = 'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg . EOL; + $str = 'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg + . (($this->error) ? ' error: ' . $this->error : '') + . EOL; logger('dba: ' . $str ); } @@ -114,9 +122,9 @@ class dba { */ if($result === false) { - logger('dba: ' . printable($sql) . ' returned false.'); + logger('dba: ' . printable($sql) . ' returned false.' . "\n" . $this->error); if(file_exists('dbfail.out')) - file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . ' returned false' . "\n", FILE_APPEND); + file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . ' returned false' . "\n" . $this->error . "\n", FILE_APPEND); } if(($result === true) || ($result === false)) diff --git a/include/delivery.php b/include/delivery.php index 794b8f27a..28d81226a 100644 --- a/include/delivery.php +++ b/include/delivery.php @@ -51,6 +51,17 @@ function delivery_run($argv, $argc){ return; } + $maxsysload = intval(get_config('system','maxloadavg')); + if($maxsysload < 1) + $maxsysload = 50; + if(function_exists('sys_getloadavg')) { + $load = sys_getloadavg(); + if(intval($load[0]) > $maxsysload) { + logger('system: load ' . $load . ' too high. Delivery deferred to next queue run.'); + return; + } + } + // It's ours to deliver. Remove it from the queue. q("delete from deliverq where cmd = '%s' and item = %d and contact = %d limit 1", diff --git a/include/enotify.php b/include/enotify.php index 8385bdec5..ca134ac86 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -402,8 +402,8 @@ class enotify { */ static public function send($params) { - $fromName = email_header_encode($params['fromName'],'UTF-8'); - $messageSubject = email_header_encode($params['messageSubject'],'UTF-8'); + $fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8'); + $messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8'); // generate a mime boundary $mimeBoundary =rand(0,9)."-" diff --git a/include/gprobe.php b/include/gprobe.php new file mode 100644 index 000000000..5ca42729a --- /dev/null +++ b/include/gprobe.php @@ -0,0 +1,65 @@ +<?php + +require_once("boot.php"); +require_once('include/Scrape.php'); +require_once('include/socgraph.php'); + +function gprobe_run($argv, $argc){ + global $a, $db; + + if(is_null($a)) { + $a = new App; + } + + if(is_null($db)) { + @include(".htconfig.php"); + require_once("dba.php"); + $db = new dba($db_host, $db_user, $db_pass, $db_data); + unset($db_host, $db_user, $db_pass, $db_data); + }; + + require_once('include/session.php'); + require_once('include/datetime.php'); + + load_config('config'); + load_config('system'); + + $a->set_baseurl(get_config('system','url')); + + load_hooks(); + + if($argc != 2) + return; + + $url = hex2bin($argv[1]); + + $r = q("select * from gcontact where nurl = '%s' limit 1", + dbesc(normalise_link($url)) + ); + + if(! count($r)) { + + $arr = probe_url($url); + if(count($arr) && x($arr,'network') && $arr['network'] === NETWORK_DFRN) { + q("insert into `gcontact` (`name`,`url`,`nurl`,`photo`) + values ( '%s', '%s', '%s', '%s') ", + dbesc($arr['name']), + dbesc($arr['url']), + dbesc(normalise_link($arr['url'])), + dbesc($arr['photo']) + ); + } + $r = q("select * from gcontact where nurl = '%s' limit 1", + dbesc(normalise_link($url)) + ); + } + if(count($r)) + poco_load(0,0,$r[0]['id'], str_replace('/profile/','/poco/',$r[0]['url'])); + + return; +} + +if (array_search(__file__,get_included_files())===0){ + gprobe_run($argv,$argc); + killme(); +} diff --git a/include/items.php b/include/items.php index 07f62ece5..e9df9b00c 100644 --- a/include/items.php +++ b/include/items.php @@ -2227,10 +2227,10 @@ function local_delivery($importer,$data) { logger('local_delivery: received remote comment'); $is_like = false; // remote reply to our post. Import and then notify everybody else. - $datarray = get_atom_elements($feed,$item); + $datarray = get_atom_elements($feed,$item); - $r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid']) ); @@ -2266,14 +2266,22 @@ function local_delivery($importer,$data) { // return 0; // } + // our user with $importer['importer_uid'] is the owner + + $own = q("select name,url,thumb from contact where uid = %d and self = 1 limit 1", + intval($importer['importer_uid']) + ); + + $datarray['type'] = 'remote-comment'; $datarray['wall'] = 1; $datarray['parent-uri'] = $parent_uri; $datarray['uid'] = $importer['importer_uid']; - $datarray['owner-name'] = $r[0]['name']; - $datarray['owner-link'] = $r[0]['url']; - $datarray['owner-avatar'] = $r[0]['thumb']; + $datarray['owner-name'] = $own[0]['name']; + $datarray['owner-link'] = $own[0]['url']; + $datarray['owner-avatar'] = $own[0]['thumb']; $datarray['contact-id'] = $importer['id']; + if(($datarray['verb'] === ACTIVITY_LIKE) || ($datarray['verb'] === ACTIVITY_DISLIKE)) { $is_like = true; $datarray['type'] = 'activity'; @@ -2290,26 +2298,34 @@ function local_delivery($importer,$data) { } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { - - + $xo = parse_xml_string($datarray['object'],false); $xt = parse_xml_string($datarray['target'],false); - if(($xt->type == ACTIVITY_OBJ_NOTE) && ($xt->id == $r[0]['uri'])) { + if(($xt->type == ACTIVITY_OBJ_NOTE) && ($xt->id)) { + + // fetch the parent item + + $tagp = q("select * from item where uri = '%s' and uid = %d limit 1", + dbesc($xt->id), + intval($importer['importer_uid']) + ); + if(! count($tagp)) + continue; // extract tag, if not duplicate, and this user allows tags, add to parent item if($xo->id && $xo->content) { $newtag = '#[url=' . $xo->id . ']'. $xo->content . '[/url]'; - - if(! (stristr($r[0]['tag'],$newtag))) { + if(! (stristr($tagp[0]['tag'],$newtag))) { $i = q("SELECT `blocktags` FROM `user` where `uid` = %d LIMIT 1", intval($importer['importer_uid']) ); - if(count($i) && ! ($i[0]['blocktags'])) { - q("UPDATE item SET tag = '%s' WHERE id = %d LIMIT 1", - dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . $newtag), - intval($r[0]['id']) + if(count($i) && ! intval($i[0]['blocktags'])) { + q("UPDATE item SET tag = '%s', `edited` = '%s' WHERE id = %d LIMIT 1", + dbesc($tagp[0]['tag'] . (strlen($tagp[0]['tag']) ? ',' : '') . $newtag), + intval($tagp[0]['id']), + dbesc(datetime_convert()) ); } } @@ -3013,32 +3029,7 @@ function item_expire($uid,$days) { if($expire_items==0 && $item['type']!='note') continue; - - $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - dbesc(datetime_convert()), - intval($item['id']) - ); - - $r = q("DELETE FROM item_id where iid in (select id from item where parent = %d) and uid = %d", - intval($item['id']), - intval($uid) - ); - - $r = q("DELETE FROM sign where iid in (select id from item where parent = %d) and uid = %d", - intval($item['id']), - intval($uid) - ); - - // kill the kids - - $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($item['parent-uri']), - intval($item['uid']) - ); - + drop_item($item['id'],false); } proc_run('php',"include/notifier.php","expire","$uid"); @@ -3100,6 +3091,25 @@ function drop_item($id,$interactive = true) { intval($item['id']) ); + // clean up categories and tags so they don't end up as orphans + + $matches = false; + $cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + file_tag_unsave_file($item['uid'],$item['id'],$mtch[1],true); + } + } + + $matches = false; + + $cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + file_tag_unsave_file($item['uid'],$item['id'],$mtch[1],false); + } + } + // If item is a link to a photo resource, nuke all the associated photos // (visitors will not have photo resources) // This only applies to photos uploaded from the photos page. Photos inserted into a post do not @@ -3123,6 +3133,17 @@ function drop_item($id,$interactive = true) { // ignore the result } + // clean up item_id and sign meta-data tables + + $r = q("DELETE FROM item_id where iid in (select id from item where parent = %d and uid = %d)", + intval($item['id']), + intval($item['uid']) + ); + + $r = q("DELETE FROM sign where iid in (select id from item where parent = %d and uid = %d)", + intval($item['id']), + intval($item['uid']) + ); // If it's the parent of a comment thread, kill all the kids @@ -3155,7 +3176,7 @@ function drop_item($id,$interactive = true) { } } $drop_id = intval($item['id']); - + // send the notification upstream/downstream as the case may be if(! $interactive) diff --git a/include/network.php b/include/network.php index 4bec4a172..27a45ec40 100644 --- a/include/network.php +++ b/include/network.php @@ -583,7 +583,7 @@ function fetch_xrd_links($url) { // Take a URL from the wild, prepend http:// if necessary -// and check DNS to see if it's real +// and check DNS to see if it's real (or check if is a valid IP address) // return true if it's OK, false if something is wrong with it if(! function_exists('validate_url')) { @@ -596,7 +596,7 @@ function validate_url(&$url) { $url = 'http://' . $url; $h = @parse_url($url); - if(($h) && (dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR))) { + if(($h) && (dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { return true; } return false; @@ -611,7 +611,7 @@ function validate_email($addr) { return false; $h = substr($addr,strpos($addr,'@') + 1); - if(($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX))) { + if(($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { return true; } return false; diff --git a/include/notifier.php b/include/notifier.php index ca7c7b92e..6ce281372 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -47,7 +47,7 @@ function notifier_run($argv, $argc){ $a->set_baseurl(get_config('system','url')); - logger('notifier: invoked: ' . print_r($argv,true)); + logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG); $cmd = $argv[1]; @@ -304,7 +304,7 @@ function notifier_run($argv, $argc){ $conversant_str = dbesc(implode(', ',$conversants)); } - $r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0"); + $r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0"); if(count($r)) $contacts = $r; @@ -520,7 +520,8 @@ function notifier_run($argv, $argc){ `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 + WHERE `contact`.`blocked` = 0 AND `contact`.`archive` = 0 + AND `contact`.`pending` = 0 AND `contact`.`network` = '%s' AND `user`.`nickname` = '%s' $sql_extra AND `user`.`account_expired` = 0 LIMIT 1", @@ -769,7 +770,7 @@ function notifier_run($argv, $argc){ ); $r2 = q("SELECT `id`, `name`,`network` FROM `contact` - WHERE `network` in ( '%s', '%s') AND `uid` = %d AND `blocked` = 0 AND `pending` = 0 + WHERE `network` in ( '%s', '%s') AND `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `rel` != %d order by rand() ", dbesc(NETWORK_DFRN), dbesc(NETWORK_MAIL2), @@ -832,6 +833,8 @@ function notifier_run($argv, $argc){ } + logger('notifier: calling hooks', LOGGER_DEBUG); + if($normal_mode) call_hooks('notifier_normal',$target_item); diff --git a/include/onepoll.php b/include/onepoll.php new file mode 100644 index 000000000..42bce0f68 --- /dev/null +++ b/include/onepoll.php @@ -0,0 +1,519 @@ +<?php + +require_once("boot.php"); + +function onepoll_run($argv, $argc){ + global $a, $db; + + if(is_null($a)) { + $a = new App; + } + + if(is_null($db)) { + @include(".htconfig.php"); + require_once("dba.php"); + $db = new dba($db_host, $db_user, $db_pass, $db_data); + unset($db_host, $db_user, $db_pass, $db_data); + }; + + + require_once('include/session.php'); + require_once('include/datetime.php'); + require_once('library/simplepie/simplepie.inc'); + require_once('include/items.php'); + require_once('include/Contact.php'); + require_once('include/email.php'); + require_once('include/socgraph.php'); + require_once('include/pidfile.php'); + + load_config('config'); + load_config('system'); + + $a->set_baseurl(get_config('system','url')); + + load_hooks(); + + logger('onepoll: start'); + + $abandon_days = intval(get_config('system','account_abandon_days')); + if($abandon_days < 1) + $abandon_days = 0; + + + $manual_id = 0; + $generation = 0; + $hub_update = false; + $force = false; + $restart = false; + + if(($argc > 1) && (intval($argv[1]))) + $contact_id = intval($argv[1]); + + if(! $contact_id) { + logger('onepoll: no contact'); + return; + } + + $d = datetime_convert(); + + // Only poll from those with suitable relationships, + // and which have a polling address and ignore Diaspora since + // we are unable to match those posts with a Diaspora GUID and prevent duplicates. + + $abandon_sql = (($abandon_days) + ? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days)) + : '' + ); + + $contacts = q("SELECT `contact`.* FROM `contact` + WHERE ( `rel` = %d OR `rel` = %d ) AND `poll` != '' + AND NOT `network` IN ( '%s', '%s' ) + AND `contact`.`id` = %d + AND `self` = 0 AND `contact`.`blocked` = 0 AND `contact`.`readonly` = 0 + AND `contact`.`archive` = 0 LIMIT 1", + intval(CONTACT_IS_SHARING), + intval(CONTACT_IS_FRIEND), + dbesc(NETWORK_DIASPORA), + dbesc(NETWORK_FACEBOOK), + intval($contact_id) + ); + + if(! count($contacts)) { + return; + } + + $contact = $contacts[0]; + + + $xml = false; + + $t = $contact['last-update']; + + if($contact['subhub']) { + $interval = get_config('system','pushpoll_frequency'); + $contact['priority'] = (($interval !== false) ? intval($interval) : 3); + $hub_update = false; + + if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day")) + $hub_update = true; + } + else + $hub_update = false; + + + $importer_uid = $contact['uid']; + + $r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` LEFT JOIN `user` on `contact`.`uid` = `user`.`uid` WHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", + intval($importer_uid) + ); + if(! count($r)) + return; + + $importer = $r[0]; + + logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['name']}, CONTACT: {$contact['name']}"); + + $last_update = (($contact['last-update'] === '0000-00-00 00:00:00') + ? datetime_convert('UTC','UTC','now - 7 days', ATOM_TIME) + : datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME) + ); + + if($contact['network'] === NETWORK_DFRN) { + + $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); + if(intval($contact['duplex']) && $contact['dfrn-id']) + $idtosend = '0:' . $orig_id; + if(intval($contact['duplex']) && $contact['issued-id']) + $idtosend = '1:' . $orig_id; + + // they have permission to write to us. We already filtered this in the contact query. + $perm = 'rw'; + + $url = $contact['poll'] . '?dfrn_id=' . $idtosend + . '&dfrn_version=' . DFRN_PROTOCOL_VERSION + . '&type=data&last_update=' . $last_update + . '&perm=' . $perm ; + + $handshake_xml = fetch_url($url); + + logger('onepoll: handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA); + + + if(! $handshake_xml) { + logger("poller: $url appears to be dead - marking for death "); + // dead connection - might be a transient event, or this might + // mean the software was uninstalled or the domain expired. + // Will keep trying for one month. + mark_for_death($contact); + + // set the last-update so we don't keep polling + $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", + dbesc(datetime_convert()), + intval($contact['id']) + ); + + return; + } + + if(! strstr($handshake_xml,'<?xml')) { + logger('poller: response from ' . $url . ' did not contain XML.'); + $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", + dbesc(datetime_convert()), + intval($contact['id']) + ); + return; + } + + + $res = parse_xml_string($handshake_xml); + + if(intval($res->status) == 1) { + logger("poller: $url replied status 1 - marking for death "); + + // we may not be friends anymore. Will keep trying for one month. + // set the last-update so we don't keep polling + + + $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", + dbesc(datetime_convert()), + intval($contact['id']) + ); + mark_for_death($contact); + } + else { + if($contact['term-date'] != '0000-00-00 00:00:00') { + logger("poller: $url back from the dead - removing mark for death"); + unmark_for_death($contact); + } + } + + if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) + return; + + if(((float) $res->dfrn_version > 2.21) && ($contact['poco'] == '')) { + q("update contact set poco = '%s' where id = %d limit 1", + dbesc(str_replace('/profile/','/poco/', $contact['url'])), + intval($contact['id']) + ); + } + + $postvars = array(); + + $sent_dfrn_id = hex2bin((string) $res->dfrn_id); + $challenge = hex2bin((string) $res->challenge); + + $final_dfrn_id = ''; + + if(($contact['duplex']) && strlen($contact['prvkey'])) { + openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']); + openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']); + } + else { + openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']); + openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']); + } + + $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); + + if(strpos($final_dfrn_id,':') == 1) + $final_dfrn_id = substr($final_dfrn_id,2); + + if($final_dfrn_id != $orig_id) { + logger('poller: ID did not decode: ' . $contact['id'] . ' orig: ' . $orig_id . ' final: ' . $final_dfrn_id); + // did not decode properly - cannot trust this site + return; + } + + $postvars['dfrn_id'] = $idtosend; + $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; + $postvars['perm'] = 'rw'; + + $xml = post_url($contact['poll'],$postvars); + + } + elseif(($contact['network'] === NETWORK_OSTATUS) + || ($contact['network'] === NETWORK_DIASPORA) + || ($contact['network'] === NETWORK_FEED) ) { + + // Upgrading DB fields from an older Friendica version + // Will only do this once per notify-enabled OStatus contact + // or if relationship changes + + $stat_writeable = ((($contact['notify']) && ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['rel'] == CONTACT_IS_FRIEND)) ? 1 : 0); + + if($stat_writeable != $contact['writable']) { + q("UPDATE `contact` SET `writable` = %d WHERE `id` = %d LIMIT 1", + intval($stat_writeable), + intval($contact['id']) + ); + } + + // Are we allowed to import from this person? + + if($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly']) + return; + + $xml = fetch_url($contact['poll']); + } + elseif($contact['network'] === NETWORK_MAIL || $contact['network'] === NETWORK_MAIL2) { + + logger("onepoll: mail: Fetching", LOGGER_DEBUG); + + $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1); + if($mail_disabled) + return; + + logger("onepoll: Mail: Enabled", LOGGER_DEBUG); + + $mbox = null; + $x = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", + intval($importer_uid) + ); + $mailconf = q("SELECT * FROM `mailacct` WHERE `server` != '' AND `uid` = %d LIMIT 1", + intval($importer_uid) + ); + if(count($x) && count($mailconf)) { + $mailbox = construct_mailbox_name($mailconf[0]); + $password = ''; + openssl_private_decrypt(hex2bin($mailconf[0]['pass']),$password,$x[0]['prvkey']); + $mbox = email_connect($mailbox,$mailconf[0]['user'],$password); + unset($password); + logger("Mail: Connect"); + if($mbox) { + q("UPDATE `mailacct` SET `last_check` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", + dbesc(datetime_convert()), + intval($mailconf[0]['id']), + intval($importer_uid) + ); + } + } + if($mbox) { + + $msgs = email_poll($mbox,$contact['addr']); + + if(count($msgs)) { + logger("Mail: Parsing ".count($msgs)." mails.", LOGGER_DEBUG); + + foreach($msgs as $msg_uid) { + logger("Mail: Parsing mail ".$msg_uid, LOGGER_DATA); + + $datarray = array(); + $meta = email_msg_meta($mbox,$msg_uid); + $headers = email_msg_headers($mbox,$msg_uid); + + // look for a 'references' header and try and match with a parent item we have locally. + + $raw_refs = ((x($headers,'references')) ? str_replace("\t",'',$headers['references']) : ''); + $datarray['uri'] = msgid2iri(trim($meta->message_id,'<>')); + + if($raw_refs) { + $refs_arr = explode(' ', $raw_refs); + if(count($refs_arr)) { + for($x = 0; $x < count($refs_arr); $x ++) + $refs_arr[$x] = "'" . msgid2iri(str_replace(array('<','>',' '),array('','',''),dbesc($refs_arr[$x]))) . "'"; + } + $qstr = implode(',',$refs_arr); + $r = q("SELECT `uri` , `parent-uri` FROM `item` WHERE `uri` IN ( $qstr ) AND `uid` = %d LIMIT 1", + intval($importer_uid) + ); + if(count($r)) + $datarray['parent-uri'] = $r[0]['uri']; + } + + + if(! x($datarray,'parent-uri')) + $datarray['parent-uri'] = $datarray['uri']; + + // Have we seen it before? + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1", + intval($importer_uid), + dbesc($datarray['uri']) + ); + + if(count($r)) { +// logger("Mail: Seen before ".$msg_uid); + if($meta->deleted && ! $r[0]['deleted']) { + q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1", + dbesc(datetime_convert()), + intval($r[0]['id']) + ); + } + switch ($mailconf[0]['action']) { + case 0: + break; + case 1: + logger("Mail: Deleting ".$msg_uid); + imap_delete($mbox, $msg_uid, FT_UID); + break; + case 2: + logger("Mail: Mark as seen ".$msg_uid); + imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); + break; + case 3: + logger("Mail: Moving ".$msg_uid." to ".$mailconf[0]['movetofolder']); + imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); + if ($mailconf[0]['movetofolder'] != "") + imap_mail_move($mbox, $msg_uid, $mailconf[0]['movetofolder'], FT_UID); + break; + } + continue; + } + + // Decoding the header + $subject = imap_mime_header_decode($meta->subject); + $datarray['title'] = ""; + foreach($subject as $subpart) + if ($subpart->charset != "default") + $datarray['title'] .= iconv($subpart->charset, 'UTF-8//IGNORE', $subpart->text); + else + $datarray['title'] .= $subpart->text; + + $datarray['title'] = notags(trim($datarray['title'])); + + //$datarray['title'] = notags(trim($meta->subject)); + $datarray['created'] = datetime_convert('UTC','UTC',$meta->date); + + // Is it reply? + $reply = ((substr(strtolower($datarray['title']), 0, 3) == "re:") or + (substr(strtolower($datarray['title']), 0, 3) == "re-") or + (raw_refs != "")); + + $r = email_get_msg($mbox,$msg_uid, $reply); + if(! $r) { + logger("Mail: can't fetch msg ".$msg_uid); + continue; + } + $datarray['body'] = escape_tags($r['body']); + + logger("Mail: Importing ".$msg_uid); + + // some mailing lists have the original author as 'from' - add this sender info to msg body. + // todo: adding a gravatar for the original author would be cool + + if(! stristr($meta->from,$contact['addr'])) { + $from = imap_mime_header_decode($meta->from); + $fromdecoded = ""; + foreach($from as $frompart) + if ($frompart->charset != "default") + $fromdecoded .= iconv($frompart->charset, 'UTF-8//IGNORE', $frompart->text); + else + $fromdecoded .= $frompart->text; + + $datarray['body'] = "[b]".t('From: ') . escape_tags($fromdecoded) . "[/b]\n\n" . $datarray['body']; + } + + $datarray['uid'] = $importer_uid; + $datarray['contact-id'] = $contact['id']; + if($datarray['parent-uri'] === $datarray['uri']) + $datarray['private'] = 1; + if(($contact['network'] === NETWORK_MAIL) && (! get_pconfig($importer_uid,'system','allow_public_email_replies'))) { + $datarray['private'] = 1; + $datarray['allow_cid'] = '<' . $contact['id'] . '>'; + } + $datarray['author-name'] = $contact['name']; + $datarray['author-link'] = 'mailbox'; + $datarray['author-avatar'] = $contact['photo']; + + $stored_item = item_store($datarray); + q("UPDATE `item` SET `last-child` = 0 WHERE `parent-uri` = '%s' AND `uid` = %d", + dbesc($datarray['parent-uri']), + intval($importer_uid) + ); + q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1", + intval($stored_item) + ); + switch ($mailconf[0]['action']) { + case 0: + break; + case 1: + logger("Mail: Deleting ".$msg_uid); + imap_delete($mbox, $msg_uid, FT_UID); + break; + case 2: + logger("Mail: Mark as seen ".$msg_uid); + imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); + break; + case 3: + logger("Mail: Moving ".$msg_uid." to ".$mailconf[0]['movetofolder']); + imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); + if ($mailconf[0]['movetofolder'] != "") + imap_mail_move($mbox, $msg_uid, $mailconf[0]['movetofolder'], FT_UID); + break; + } + } + } + imap_close($mbox); + } + } + elseif($contact['network'] === NETWORK_FACEBOOK) { + // This is picked up by the Facebook plugin on a cron hook. + // Ignored here. + } + + if($xml) { + logger('poller: received xml : ' . $xml, LOGGER_DATA); + if(! strstr($xml,'<?xml')) { + logger('poller: post_handshake: response from ' . $url . ' did not contain XML.'); + $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", + dbesc(datetime_convert()), + intval($contact['id']) + ); + return; + } + + + consume_feed($xml,$importer,$contact,$hub,1,1); + + + // do it twice. Ensures that children of parents which may be later in the stream aren't tossed + + consume_feed($xml,$importer,$contact,$hub,1,2); + + $hubmode = 'subscribe'; + if($contact['network'] === NETWORK_DFRN || $contact['blocked'] || $contact['readonly']) + $hubmode = 'unsubscribe'; + + if((strlen($hub)) && ($hub_update) && ($contact['rel'] != CONTACT_IS_FOLLOWER)) { + logger('poller: hub ' . $hubmode . ' : ' . $hub . ' contact name : ' . $contact['name'] . ' local user : ' . $importer['name']); + $hubs = explode(',', $hub); + if(count($hubs)) { + foreach($hubs as $h) { + $h = trim($h); + if(! strlen($h)) + continue; + subscribe_to_hub($h,$importer,$contact,$hubmode); + } + } + } + } + + $updated = datetime_convert(); + + $r = q("UPDATE `contact` SET `last-update` = '%s', `success_update` = '%s' WHERE `id` = %d LIMIT 1", + dbesc($updated), + dbesc($updated), + intval($contact['id']) + ); + + + // load current friends if possible. + + if($contact['poco']) { + $r = q("SELECT count(*) as total from glink + where `cid` = %d and updated > UTC_TIMESTAMP() - INTERVAL 1 DAY", + intval($contact['id']) + ); + } + if(count($r)) { + if(! $r[0]['total']) { + poco_load($contact['id'],$importer_uid,0,$contact['poco']); + } + } + + return; +} + +if (array_search(__file__,get_included_files())===0){ + onepoll_run($argv,$argc); + killme(); +} diff --git a/include/plugin.php b/include/plugin.php index 8196e8756..4ff78a8b4 100644 --- a/include/plugin.php +++ b/include/plugin.php @@ -5,7 +5,7 @@ if (! function_exists('uninstall_plugin')){ function uninstall_plugin($plugin){ logger("Addons: uninstalling " . $plugin); - q("DELETE FROM `addon` WHERE `name` = '%s' LIMIT 1", + q("DELETE FROM `addon` WHERE `name` = '%s' ", dbesc($plugin) ); @@ -37,6 +37,16 @@ function install_plugin($plugin) { intval($t), $plugin_admin ); + + // we can add the following with the previous SQL + // once most site tables have been updated. + // This way the system won't fall over dead during the update. + + if(file_exists('addon/' . $plugin . '/.hidden')) { + q("update addon set hidden = 1 where name = '%s' limit 1", + dbesc($plugin) + ); + } return true; } else { diff --git a/include/poller.php b/include/poller.php index 499483d00..f6553c846 100644 --- a/include/poller.php +++ b/include/poller.php @@ -30,6 +30,17 @@ function poller_run($argv, $argc){ load_config('config'); load_config('system'); + $maxsysload = intval(get_config('system','maxloadavg')); + if($maxsysload < 1) + $maxsysload = 50; + if(function_exists('sys_getloadavg')) { + $load = sys_getloadavg(); + if(intval($load[0]) > $maxsysload) { + logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.'); + return; + } + } + $lockpath = get_config('system','lockpath'); if ($lockpath != '') { $pidfile = new pidfile($lockpath, 'poller.lck'); @@ -39,6 +50,8 @@ function poller_run($argv, $argc){ } } + + $a->set_baseurl(get_config('system','url')); load_hooks(); @@ -113,6 +126,8 @@ function poller_run($argv, $argc){ $force = true; } + $interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval'))); + $sql_extra = (($manual_id) ? " AND `id` = $manual_id " : ""); reload_plugins(); @@ -136,6 +151,7 @@ function poller_run($argv, $argc){ AND NOT `network` IN ( '%s', '%s' ) $sql_extra AND `self` = 0 AND `contact`.`blocked` = 0 AND `contact`.`readonly` = 0 + AND `contact`.`archive` = 0 AND `user`.`account_expired` = 0 $abandon_sql ORDER BY RAND()", intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND), @@ -224,440 +240,12 @@ function poller_run($argv, $argc){ continue; } - // Check to see if we are running out of memory - if so spawn a new process and kill this one - - $avail_memory = return_bytes(ini_get('memory_limit')); - $memused = memory_get_peak_usage(true); - if(intval($avail_memory)) { - if(($memused / $avail_memory) > 0.95) { - if($generation + 1 > 10) { - logger('poller: maximum number of spawns exceeded. Terminating.'); - killme(); - } - logger('poller: memory exceeded. ' . $memused . ' bytes used. Spawning new poll.'); - proc_run('php', 'include/poller.php', 'restart', (string) $generation + 1); - killme(); - } - } - - $importer_uid = $contact['uid']; - - $r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` LEFT JOIN `user` on `contact`.`uid` = `user`.`uid` WHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", - intval($importer_uid) - ); - if(! count($r)) - continue; - - $importer = $r[0]; - - logger("poller: poll: ({$contact['id']}) IMPORTER: {$importer['name']}, CONTACT: {$contact['name']}"); - - $last_update = (($contact['last-update'] === '0000-00-00 00:00:00') - ? datetime_convert('UTC','UTC','now - 30 days', ATOM_TIME) - : datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME) - ); - - if($contact['network'] === NETWORK_DFRN) { - - $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); - - if(intval($contact['duplex']) && $contact['dfrn-id']) - $idtosend = '0:' . $orig_id; - if(intval($contact['duplex']) && $contact['issued-id']) - $idtosend = '1:' . $orig_id; - - // they have permission to write to us. We already filtered this in the contact query. - $perm = 'rw'; - - $url = $contact['poll'] . '?dfrn_id=' . $idtosend - . '&dfrn_version=' . DFRN_PROTOCOL_VERSION - . '&type=data&last_update=' . $last_update - . '&perm=' . $perm ; - - $handshake_xml = fetch_url($url); - - logger('poller: handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA); - - - if(! $handshake_xml) { - logger("poller: $url appears to be dead - marking for death "); - // dead connection - might be a transient event, or this might - // mean the software was uninstalled or the domain expired. - // Will keep trying for one month. - mark_for_death($contact); - - // set the last-update so we don't keep polling - - $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($contact['id']) - ); - - continue; - } - - if(! strstr($handshake_xml,'<?xml')) { - logger('poller: response from ' . $url . ' did not contain XML.'); - $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($contact['id']) - ); - continue; - } - - - $res = parse_xml_string($handshake_xml); - - if(intval($res->status) == 1) { - logger("poller: $url replied status 1 - marking for death "); - - // we may not be friends anymore. Will keep trying for one month. - // set the last-update so we don't keep polling - - $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($contact['id']) - ); - - mark_for_death($contact); - } - else { - if($contact['term-date'] != '0000-00-00 00:00:00') { - logger("poller: $url back from the dead - removing mark for death"); - unmark_for_death($contact); - } - } - - if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) - continue; - - if(((float) $res->dfrn_version > 2.21) && ($contact['poco'] == '')) { - q("update contact set poco = '%s' where id = %d limit 1", - dbesc(str_replace('/profile/','/poco/', $contact['url'])), - intval($contact['id']) - ); - } - - $postvars = array(); - - $sent_dfrn_id = hex2bin((string) $res->dfrn_id); - $challenge = hex2bin((string) $res->challenge); - - $final_dfrn_id = ''; - - if(($contact['duplex']) && strlen($contact['prvkey'])) { - openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']); - openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']); - } - else { - openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']); - openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']); - } - - $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); - - if(strpos($final_dfrn_id,':') == 1) - $final_dfrn_id = substr($final_dfrn_id,2); - - if($final_dfrn_id != $orig_id) { - logger('poller: ID did not decode: ' . $contact['id'] . ' orig: ' . $orig_id . ' final: ' . $final_dfrn_id); - // did not decode properly - cannot trust this site - continue; - } - - $postvars['dfrn_id'] = $idtosend; - $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; - $postvars['perm'] = 'rw'; - - $xml = post_url($contact['poll'],$postvars); - } - elseif(($contact['network'] === NETWORK_OSTATUS) - || ($contact['network'] === NETWORK_DIASPORA) - || ($contact['network'] === NETWORK_FEED) ) { - - // Upgrading DB fields from an older Friendica version - // Will only do this once per notify-enabled OStatus contact - // or if relationship changes - - $stat_writeable = ((($contact['notify']) && ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['rel'] == CONTACT_IS_FRIEND)) ? 1 : 0); - - if($stat_writeable != $contact['writable']) { - q("UPDATE `contact` SET `writable` = %d WHERE `id` = %d LIMIT 1", - intval($stat_writeable), - intval($contact['id']) - ); - } - - // Are we allowed to import from this person? - - if($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly']) - continue; - - $xml = fetch_url($contact['poll']); - } - elseif($contact['network'] === NETWORK_MAIL || $contact['network'] === NETWORK_MAIL2) { - - logger("Mail: Fetching"); - - $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1); - if($mail_disabled) - continue; - - logger("Mail: Enabled"); - - $mbox = null; - $x = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", - intval($importer_uid) - ); - $mailconf = q("SELECT * FROM `mailacct` WHERE `server` != '' AND `uid` = %d LIMIT 1", - intval($importer_uid) - ); - if(count($x) && count($mailconf)) { - $mailbox = construct_mailbox_name($mailconf[0]); - $password = ''; - openssl_private_decrypt(hex2bin($mailconf[0]['pass']),$password,$x[0]['prvkey']); - $mbox = email_connect($mailbox,$mailconf[0]['user'],$password); - unset($password); - logger("Mail: Connect"); - if($mbox) { - q("UPDATE `mailacct` SET `last_check` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($mailconf[0]['id']), - intval($importer_uid) - ); - } - } - if($mbox) { - logger("Mail: mbox"); - - $msgs = email_poll($mbox,$contact['addr']); - - if(count($msgs)) { - logger("Mail: Parsing ".count($msgs)." mails."); - - foreach($msgs as $msg_uid) { - logger("Mail: Parsing mail ".$msg_uid); - - $datarray = array(); - $meta = email_msg_meta($mbox,$msg_uid); - $headers = email_msg_headers($mbox,$msg_uid); - - // look for a 'references' header and try and match with a parent item we have locally. - - $raw_refs = ((x($headers,'references')) ? str_replace("\t",'',$headers['references']) : ''); - $datarray['uri'] = msgid2iri(trim($meta->message_id,'<>')); - - if($raw_refs) { - $refs_arr = explode(' ', $raw_refs); - if(count($refs_arr)) { - for($x = 0; $x < count($refs_arr); $x ++) - $refs_arr[$x] = "'" . msgid2iri(str_replace(array('<','>',' '),array('','',''),dbesc($refs_arr[$x]))) . "'"; - } - $qstr = implode(',',$refs_arr); - $r = q("SELECT `uri` , `parent-uri` FROM `item` WHERE `uri` IN ( $qstr ) AND `uid` = %d LIMIT 1", - intval($importer_uid) - ); - if(count($r)) - $datarray['parent-uri'] = $r[0]['uri']; - } - - - if(! x($datarray,'parent-uri')) - $datarray['parent-uri'] = $datarray['uri']; - - // Have we seen it before? - $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1", - intval($importer_uid), - dbesc($datarray['uri']) - ); - - if(count($r)) { - logger("Mail: Seen before ".$msg_uid); - if($meta->deleted && ! $r[0]['deleted']) { - q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($r[0]['id']) - ); - } - switch ($mailconf[0]['action']) { - case 0: - break; - case 1: - logger("Mail: Deleting ".$msg_uid); - imap_delete($mbox, $msg_uid, FT_UID); - break; - case 2: - logger("Mail: Mark as seen ".$msg_uid); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - break; - case 3: - logger("Mail: Moving ".$msg_uid." to ".$mailconf[0]['movetofolder']); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - if ($mailconf[0]['movetofolder'] != "") - imap_mail_move($mbox, $msg_uid, $mailconf[0]['movetofolder'], FT_UID); - break; - } - continue; - } - - // Decoding the header - $subject = imap_mime_header_decode($meta->subject); - $datarray['title'] = ""; - foreach($subject as $subpart) - if ($subpart->charset != "default") - $datarray['title'] .= iconv($subpart->charset, 'UTF-8//IGNORE', $subpart->text); - else - $datarray['title'] .= $subpart->text; - - $datarray['title'] = notags(trim($datarray['title'])); - - //$datarray['title'] = notags(trim($meta->subject)); - $datarray['created'] = datetime_convert('UTC','UTC',$meta->date); - - // Is it reply? - $reply = ((substr(strtolower($datarray['title']), 0, 3) == "re:") or - (substr(strtolower($datarray['title']), 0, 3) == "re-") or - (raw_refs != "")); - - $r = email_get_msg($mbox,$msg_uid, $reply); - if(! $r) { - logger("Mail: can't fetch msg ".$msg_uid); - continue; - } - $datarray['body'] = escape_tags($r['body']); - - logger("Mail: Importing ".$msg_uid); - - // some mailing lists have the original author as 'from' - add this sender info to msg body. - // todo: adding a gravatar for the original author would be cool - - if(! stristr($meta->from,$contact['addr'])) { - $from = imap_mime_header_decode($meta->from); - $fromdecoded = ""; - foreach($from as $frompart) - if ($frompart->charset != "default") - $fromdecoded .= iconv($frompart->charset, 'UTF-8//IGNORE', $frompart->text); - else - $fromdecoded .= $frompart->text; - - $datarray['body'] = "[b]".t('From: ') . escape_tags($fromdecoded) . "[/b]\n\n" . $datarray['body']; - } - - $datarray['uid'] = $importer_uid; - $datarray['contact-id'] = $contact['id']; - if($datarray['parent-uri'] === $datarray['uri']) - $datarray['private'] = 1; - if(($contact['network'] === NETWORK_MAIL) && (! get_pconfig($importer_uid,'system','allow_public_email_replies'))) { - $datarray['private'] = 1; - $datarray['allow_cid'] = '<' . $contact['id'] . '>'; - } - $datarray['author-name'] = $contact['name']; - $datarray['author-link'] = 'mailbox'; - $datarray['author-avatar'] = $contact['photo']; - - $stored_item = item_store($datarray); - q("UPDATE `item` SET `last-child` = 0 WHERE `parent-uri` = '%s' AND `uid` = %d", - dbesc($datarray['parent-uri']), - intval($importer_uid) - ); - q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1", - intval($stored_item) - ); - switch ($mailconf[0]['action']) { - case 0: - break; - case 1: - logger("Mail: Deleting ".$msg_uid); - imap_delete($mbox, $msg_uid, FT_UID); - break; - case 2: - logger("Mail: Mark as seen ".$msg_uid); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - break; - case 3: - logger("Mail: Moving ".$msg_uid." to ".$mailconf[0]['movetofolder']); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - if ($mailconf[0]['movetofolder'] != "") - imap_mail_move($mbox, $msg_uid, $mailconf[0]['movetofolder'], FT_UID); - break; - } - } - } - - imap_close($mbox); - } - } - elseif($contact['network'] === NETWORK_FACEBOOK) { - // This is picked up by the Facebook plugin on a cron hook. - // Ignored here. - } - - if($xml) { - logger('poller: received xml : ' . $xml, LOGGER_DATA); - - if(! strstr($xml,'<?xml')) { - logger('poller: post_handshake: response from ' . $url . ' did not contain XML.'); - $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($contact['id']) - ); - continue; - } - - - consume_feed($xml,$importer,$contact,$hub,1,1); - - // do it twice. Ensures that children of parents which may be later in the stream aren't tossed - - consume_feed($xml,$importer,$contact,$hub,1,2); - - $hubmode = 'subscribe'; - if($contact['network'] === NETWORK_DFRN || $contact['blocked'] || $contact['readonly']) - $hubmode = 'unsubscribe'; - - if((strlen($hub)) && ($hub_update) && ($contact['rel'] != CONTACT_IS_FOLLOWER)) { - logger('poller: hub ' . $hubmode . ' : ' . $hub . ' contact name : ' . $contact['name'] . ' local user : ' . $importer['name']); - $hubs = explode(',', $hub); - if(count($hubs)) { - foreach($hubs as $h) { - $h = trim($h); - if(! strlen($h)) - continue; - subscribe_to_hub($h,$importer,$contact,$hubmode); - } - } - } - } - - - $updated = datetime_convert(); - - $r = q("UPDATE `contact` SET `last-update` = '%s', `success_update` = '%s' WHERE `id` = %d LIMIT 1", - dbesc($updated), - dbesc($updated), - intval($contact['id']) - ); - - - // load current friends if possible. - - if($contact['poco']) { - $r = q("SELECT count(*) as total from glink - where `cid` = %d and updated > UTC_TIMESTAMP() - INTERVAL 1 DAY", - intval($contact['id']) - ); - } - if(count($r)) { - if(! $r[0]['total']) { - poco_load($contact['id'],$importer_uid,$contact['poco']); - } - } - - // loop - next contact + proc_run('php','include/onepoll.php',$contact['id']); + if($interval) + @time_sleep_until(microtime(true) + (float) $interval); } } - return; } diff --git a/include/profile_selectors.php b/include/profile_selectors.php index a2cef959d..4700bb96f 100644 --- a/include/profile_selectors.php +++ b/include/profile_selectors.php @@ -7,8 +7,10 @@ function gender_selector($current="",$suffix="") { $o .= "<select name=\"gender$suffix\" id=\"gender-select$suffix\" size=\"1\" >"; foreach($select as $selection) { - $selected = (($selection == $current) ? ' selected="selected" ' : ''); - $o .= "<option value=\"$selection\" $selected >$selection</option>"; + if($selection !== 'NOTRANSLATION') { + $selected = (($selection == $current) ? ' selected="selected" ' : ''); + $o .= "<option value=\"$selection\" $selected >$selection</option>"; + } } $o .= '</select>'; return $o; @@ -20,8 +22,10 @@ function sexpref_selector($current="",$suffix="") { $o .= "<select name=\"sexual$suffix\" id=\"sexual-select$suffix\" size=\"1\" >"; foreach($select as $selection) { - $selected = (($selection == $current) ? ' selected="selected" ' : ''); - $o .= "<option value=\"$selection\" $selected >$selection</option>"; + if($selection !== 'NOTRANSLATION') { + $selected = (($selection == $current) ? ' selected="selected" ' : ''); + $o .= "<option value=\"$selection\" $selected >$selection</option>"; + } } $o .= '</select>'; return $o; @@ -34,8 +38,10 @@ function marital_selector($current="",$suffix="") { $o .= "<select name=\"marital\" id=\"marital-select\" size=\"1\" >"; foreach($select as $selection) { - $selected = (($selection == $current) ? ' selected="selected" ' : ''); - $o .= "<option value=\"$selection\" $selected >$selection</option>"; + if($selection !== 'NOTRANSLATION') { + $selected = (($selection == $current) ? ' selected="selected" ' : ''); + $o .= "<option value=\"$selection\" $selected >$selection</option>"; + } } $o .= '</select>'; return $o; diff --git a/include/socgraph.php b/include/socgraph.php index 3f5194049..592779089 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -20,7 +20,7 @@ require_once('include/datetime.php'); -function poco_load($cid,$uid = 0,$url = null) { +function poco_load($cid,$uid = 0,$zcid = 0,$url = null) { $a = get_app(); if($cid) { @@ -53,7 +53,6 @@ function poco_load($cid,$uid = 0,$url = null) { if(($a->get_curl_code() > 299) || (! $s)) return; - $j = json_decode($s); logger('poco_load: json: ' . print_r($j,true),LOGGER_DATA); @@ -81,7 +80,6 @@ function poco_load($cid,$uid = 0,$url = null) { $connect_url = str_replace('acct:' , '', $url->value); continue; } - } foreach($entry->photos as $photo) { if($photo->type == 'profile') { @@ -101,11 +99,12 @@ function poco_load($cid,$uid = 0,$url = null) { $gcid = $x[0]['id']; if($x[0]['name'] != $name || $x[0]['photo'] != $profile_photo) { - q("update gcontact set `name` = '%s', `photo` = '%s', `connect` = '%s' + q("update gcontact set `name` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s' where `nurl` = '%s' limit 1", dbesc($name), dbesc($profile_photo), dbesc($connect_url), + dbesc($profile_url), dbesc(normalise_link($profile_url)) ); } @@ -128,34 +127,38 @@ function poco_load($cid,$uid = 0,$url = null) { if(! $gcid) return; - $r = q("select * from glink where `cid` = %d and `uid` = %d and `gcid` = %d limit 1", + $r = q("select * from glink where `cid` = %d and `uid` = %d and `gcid` = %d and `zcid` = %d limit 1", intval($cid), intval($uid), - intval($gcid) + intval($gcid), + intval($zcid) ); if(! count($r)) { - q("insert into glink ( `cid`,`uid`,`gcid`,`updated`) values (%d,%d,%d,'%s') ", + q("insert into glink ( `cid`,`uid`,`gcid`,`zcid`, `updated`) values (%d,%d,%d,%d, '%s') ", intval($cid), intval($uid), intval($gcid), + intval($zcid), dbesc(datetime_convert()) ); } else { - q("update glink set updated = '%s' where `cid` = %d and `uid` = %d and `gcid` = %d limit 1", + q("update glink set updated = '%s' where `cid` = %d and `uid` = %d and `gcid` = %d and zcid = %d limit 1", dbesc(datetime_convert()), intval($cid), intval($uid), - intval($gcid) + intval($gcid), + intval($zcid) ); } } logger("poco_load: loaded $total entries",LOGGER_DEBUG); - q("delete from glink where `cid` = %d and `uid` = %d and `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", + q("delete from glink where `cid` = %d and `uid` = %d and `zcid` = %d and `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", intval($cid), - intval($uid) + intval($uid), + intval($zcid) ); } @@ -166,13 +169,14 @@ function count_common_friends($uid,$cid) { $r = q("SELECT count(*) as `total` FROM `glink` left join `gcontact` on `glink`.`gcid` = `gcontact`.`id` where `glink`.`cid` = %d and `glink`.`uid` = %d - and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and id != %d ) ", + and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) ", intval($cid), intval($uid), intval($uid), intval($cid) ); +// logger("count_common_friends: $uid $cid {$r[0]['total']}"); if(count($r)) return $r[0]['total']; return 0; @@ -180,23 +184,70 @@ function count_common_friends($uid,$cid) { } -function common_friends($uid,$cid) { +function common_friends($uid,$cid,$start = 0,$limit=9999,$shuffle = false) { + + if($shuffle) + $sql_extra = " order by rand() "; + else + $sql_extra = " order by `gcontact`.`name` asc "; $r = q("SELECT `gcontact`.* FROM `glink` left join `gcontact` on `glink`.`gcid` = `gcontact`.`id` where `glink`.`cid` = %d and `glink`.`uid` = %d - and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and id != %d ) - order by `gcontact`.`name` asc ", + and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) + $sql_extra limit %d, %d", intval($cid), intval($uid), intval($uid), - intval($cid) + intval($cid), + intval($start), + intval($limit) + ); + + return $r; + +} + + +function count_common_friends_zcid($uid,$zcid) { + + $r = q("SELECT count(*) as `total` + FROM `glink` left join `gcontact` on `glink`.`gcid` = `gcontact`.`id` + where `glink`.`zcid` = %d + and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) ", + intval($zcid), + intval($uid) + ); + + if(count($r)) + return $r[0]['total']; + return 0; + +} + +function common_friends_zcid($uid,$zcid,$start = 0, $limit = 9999,$shuffle) { + + if($shuffle) + $sql_extra = " order by rand() "; + else + $sql_extra = " order by `gcontact`.`name` asc "; + + $r = q("SELECT `gcontact`.* + FROM `glink` left join `gcontact` on `glink`.`gcid` = `gcontact`.`id` + where `glink`.`zcid` = %d + and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) + $sql_extra limit %d, %d", + intval($zcid), + intval($uid), + intval($start), + intval($limit) ); return $r; } + function count_all_friends($uid,$cid) { $r = q("SELECT count(*) as `total` @@ -254,7 +305,7 @@ function suggestion_query($uid, $start = 0, $limit = 80) { $r2 = q("SELECT gcontact.* from gcontact left join glink on glink.gcid = gcontact.id - where glink.uid = 0 and glink.cid = 0 and not gcontact.nurl in ( select nurl from contact where uid = %d ) + where glink.uid = 0 and glink.cid = 0 and glink.zcid = 0 and not gcontact.nurl in ( select nurl from contact where uid = %d ) and not gcontact.name in ( select name from contact where uid = %d ) and not gcontact.id in ( select gcid from gcign where uid = %d ) order by rand() limit %d, %d ", @@ -276,7 +327,7 @@ function update_suggestions() { $done = array(); - poco_load(0,0,$a->get_baseurl() . '/poco'); + poco_load(0,0,0,$a->get_baseurl() . '/poco'); $done[] = $a->get_baseurl() . '/poco'; @@ -288,7 +339,7 @@ function update_suggestions() { foreach($j->entries as $entry) { $url = $entry->url . '/poco'; if(! in_array($url,$done)) - poco_load(0,0,$entry->url . '/poco'); + poco_load(0,0,0,$entry->url . '/poco'); } } } @@ -302,7 +353,7 @@ function update_suggestions() { foreach($r as $rr) { $base = substr($rr['poco'],0,strrpos($rr['poco'],'/')); if(! in_array($base,$done)) - poco_load(0,0,$base); + poco_load(0,0,0,$base); } } } diff --git a/include/text.php b/include/text.php index 8c8db66a9..1b5b0afd4 100644 --- a/include/text.php +++ b/include/text.php @@ -558,7 +558,7 @@ function contact_block() { if((! is_array($a->profile)) || ($a->profile['hide-friends'])) return $o; - $r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 AND `hidden` = 0", + $r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 AND `hidden` = 0 AND `archive` = 0", intval($a->profile['uid']) ); if(count($r)) { @@ -569,7 +569,7 @@ function contact_block() { $micropro = Null; } else { - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 AND `hidden` = 0 ORDER BY RAND() LIMIT %d", + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 AND `hidden` = 0 AND `archive` = 0 ORDER BY RAND() LIMIT %d", intval($a->profile['uid']), intval($shown) ); @@ -930,7 +930,8 @@ function prepare_body($item,$attach = false) { foreach($matches as $mtch) { if(strlen($x)) $x .= ','; - $x .= xmlify(file_tag_decode($mtch[1])); + $x .= xmlify(file_tag_decode($mtch[1])) + . ((local_user() == $item['uid']) ? ' <a href="' . $a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&cat=' . xmlify(file_tag_decode($mtch[1])) . '" title="' . t('remove') . '" >' . t('[remove]') . '</a>' : ''); } if(strlen($x)) $s .= '<div class="categorytags"><span>' . t('Categories:') . ' </span>' . $x . '</div>'; @@ -1466,12 +1467,16 @@ function file_tag_save_file($uid,$item,$file) { return true; } -function file_tag_unsave_file($uid,$item,$file) { +function file_tag_unsave_file($uid,$item,$file,$cat = false) { $result = false; if(! intval($uid)) return false; - $pattern = '[' . file_tag_encode($file) . ']' ; + if($cat == true) + $pattern = '<' . file_tag_encode($file) . '>' ; + else + $pattern = '[' . file_tag_encode($file) . ']' ; + $r = q("select file from item where id = %d and uid = %d limit 1", intval($item), @@ -1486,13 +1491,14 @@ function file_tag_unsave_file($uid,$item,$file) { intval($uid) ); - $r = q("select file from item where uid = %d " . file_tag_file_query('item',$file), + $r = q("select file from item where uid = %d and deleted = 0 " . file_tag_file_query('item',$file,(($cat) ? 'category' : 'file')), intval($uid) ); if(! count($r)) { $saved = get_pconfig($uid,'system','filetags'); set_pconfig($uid,'system','filetags',str_replace($pattern,'',$saved)); + } return true; } |