diff options
Diffstat (limited to 'include')
-rw-r--r--[-rwxr-xr-x] | include/Contact.php | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | include/EmailNotification.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/Photo.php | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | include/Scrape.php | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | include/acl_selectors.php | 14 | ||||
-rw-r--r--[-rwxr-xr-x] | include/api.php | 528 | ||||
-rw-r--r--[-rwxr-xr-x] | include/attach.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/auth.php | 38 | ||||
-rw-r--r--[-rwxr-xr-x] | include/bb2diaspora.php | 0 | ||||
-rw-r--r-- | include/bbcode.php | 32 | ||||
-rw-r--r--[-rwxr-xr-x] | include/cache.php | 0 | ||||
-rwxr-xr-x | include/config.php | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | include/contact_selectors.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/contact_widgets.php | 63 | ||||
-rw-r--r--[-rwxr-xr-x] | include/conversation.php | 195 | ||||
-rw-r--r--[-rwxr-xr-x] | include/cronhooks.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/crypto.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/datetime.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/dba.php | 30 | ||||
-rw-r--r--[-rwxr-xr-x] | include/delivery.php | 43 | ||||
-rw-r--r--[-rwxr-xr-x] | include/diaspora.php | 81 | ||||
-rw-r--r--[-rwxr-xr-x] | include/directory.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/email.php | 20 | ||||
-rw-r--r--[-rwxr-xr-x] | include/enotify.php | 41 | ||||
-rw-r--r--[-rwxr-xr-x] | include/event.php | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | include/expire.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/fcontact.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/group.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/html2bbcode.php | 20 | ||||
-rw-r--r-- | include/html2plain.php | 91 | ||||
-rw-r--r--[-rwxr-xr-x] | include/items.php | 173 | ||||
-rw-r--r--[-rwxr-xr-x] | include/message.php | 85 | ||||
-rw-r--r-- | include/msgclean.php | 225 | ||||
-rw-r--r--[-rwxr-xr-x] | include/nav.php | 15 | ||||
-rw-r--r--[-rwxr-xr-x] | include/network.php | 52 | ||||
-rw-r--r--[-rwxr-xr-x] | include/notifier.php | 50 | ||||
-rw-r--r--[-rwxr-xr-x] | include/oauth.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/oembed.php | 12 | ||||
-rw-r--r--[-rwxr-xr-x] | include/pgettext.php | 0 | ||||
-rw-r--r-- | include/pidfile.php | 32 | ||||
-rw-r--r--[-rwxr-xr-x] | include/plugin.php | 20 | ||||
-rw-r--r--[-rwxr-xr-x] | include/poller.php | 40 | ||||
-rw-r--r--[-rwxr-xr-x] | include/profile_advanced.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/profile_selectors.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/profile_update.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/queue.php | 11 | ||||
-rw-r--r--[-rwxr-xr-x] | include/queue_fn.php | 0 | ||||
-rw-r--r-- | include/quoteconvert.php | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | include/remoteupdate.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/salmon.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/security.php | 141 | ||||
-rw-r--r--[-rwxr-xr-x] | include/session.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/socgraph.php | 10 | ||||
-rw-r--r--[-rwxr-xr-x] | include/system_unavailable.php | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | include/template_processor.php | 17 | ||||
-rw-r--r--[-rwxr-xr-x] | include/text.php | 326 |
56 files changed, 2060 insertions, 364 deletions
diff --git a/include/Contact.php b/include/Contact.php index baccea305..d9949b1ef 100755..100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -15,6 +15,12 @@ function user_remove($uid) { call_hooks('remove_user',$r[0]); + // save username (actually the nickname as it is guaranteed + // unique), so it cannot be re-registered in the future. + + q("insert into userd ( username ) values ( '%s' )", + $r[0]['nickname'] + ); q("DELETE FROM `contact` WHERE `uid` = %d", intval($uid)); q("DELETE FROM `group` WHERE `uid` = %d", intval($uid)); diff --git a/include/EmailNotification.php b/include/EmailNotification.php index 8861e8f5d..8861e8f5d 100755..100644 --- a/include/EmailNotification.php +++ b/include/EmailNotification.php diff --git a/include/Photo.php b/include/Photo.php index 1450374ff..4d02b5c65 100755..100644 --- a/include/Photo.php +++ b/include/Photo.php @@ -268,9 +268,9 @@ function import_profile_photo($photo,$uid,$cid) { $photo_failure = true; if($photo_failure) { - $photo = $a->get_baseurl() . '/images/default-profile.jpg'; - $thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg'; - $micro = $a->get_baseurl() . '/images/default-profile-mm.jpg'; + $photo = $a->get_baseurl() . '/images/person-175.jpg'; + $thumb = $a->get_baseurl() . '/images/person-80.jpg'; + $micro = $a->get_baseurl() . '/images/person-48.jpg'; } return(array($photo,$thumb,$micro)); diff --git a/include/Scrape.php b/include/Scrape.php index 8344aa737..9c237916b 100755..100644 --- a/include/Scrape.php +++ b/include/Scrape.php @@ -684,7 +684,7 @@ function probe_url($url, $mode = PROBE_NORMAL) { if(! x($vcard,'photo')) { $a = get_app(); - $vcard['photo'] = $a->get_baseurl() . '/images/default-profile.jpg' ; + $vcard['photo'] = $a->get_baseurl() . '/images/person-175.jpg' ; } if(! $profile) diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 67d8cebde..a5f5aff53 100755..100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -113,11 +113,13 @@ function contact_selector($selname, $selclass, $preselected = false, $options) { $str_nets = implode(',',$x['networks']); $sql_extra .= " AND `network` IN ( $str_nets ) "; } + + $tabindex = (x($options, 'tabindex') ? "tabindex=\"" . $options["tabindex"] . "\"" : ""); if($x['single']) - $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"" . $x['size'] . "\" >\r\n"; + $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"" . $x['size'] . "\" $tabindex >\r\n"; else - $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"" . $x['size'] . "$\" >\r\n"; + $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` != '' @@ -156,7 +158,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) { -function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false, $privatenet = false) { +function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false, $privatenet = false, $tabindex = null) { $a = get_app(); @@ -178,12 +180,12 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p $sql_extra .= " AND `network` IN ( 'dfrn', 'mail', 'face', 'dspr' ) "; } - + $tabindex = ($tabindex > 0 ? "tabindex=\"$tabindex\"" : ""); if($privmail) - $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\" >\r\n"; + $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\" $tabindex >\r\n"; else - $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n"; + $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` != '' diff --git a/include/api.php b/include/api.php index 013f4b97a..ab83d63be 100755..100644 --- a/include/api.php +++ b/include/api.php @@ -3,6 +3,7 @@ require_once("datetime.php"); require_once("conversation.php"); require_once("oauth.php"); + require_once("html2plain.php"); /* * Twitter-Like API * @@ -82,7 +83,7 @@ $record = $r[0]; } else { logger('API_login failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); - header('WWW-Authenticate: Basic realm="Friendika"'); + header('WWW-Authenticate: Basic realm="Friendica"'); header('HTTP/1.0 401 Unauthorized'); die('This api requires login'); } @@ -120,6 +121,7 @@ if (strpos($a->query_string, ".json")>0) $type="json"; if (strpos($a->query_string, ".rss")>0) $type="rss"; if (strpos($a->query_string, ".atom")>0) $type="atom"; + if (strpos($a->query_string, ".as")>0) $type="as"; $r = call_user_func($info['func'], $a, $type); if ($r===false) return; @@ -143,6 +145,12 @@ header ("Content-Type: application/atom+xml"); return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r; break; + case "as": + //header ("Content-Type: application/json"); + //foreach($r as $rr) + // return json_encode($rr); + return json_encode($r); + break; } //echo "<pre>"; var_dump($r); die(); @@ -306,10 +314,10 @@ } $ret = Array( + 'id' => intval($uinfo[0]['cid']), 'self' => intval($uinfo[0]['self']), 'uid' => intval($uinfo[0]['uid']), - 'id' => intval($uinfo[0]['cid']), - 'name' => $uinfo[0]['name'], + 'name' => (($uinfo[0]['name']) ? $uinfo[0]['name'] : $uinfo[0]['nick']), 'screen_name' => (($uinfo[0]['nick']) ? $uinfo[0]['nick'] : $uinfo[0]['name']), 'location' => ($usr) ? $usr[0]['default-location'] : '', 'profile_image_url' => $uinfo[0]['micro'], @@ -347,6 +355,8 @@ } function api_item_get_user(&$a, $item) { + global $usercache; + // The author is our direct contact, in a conversation with us. if(link_compare($item['url'],$item['author-link'])) { return api_get_user($a,$item['cid']); @@ -362,27 +372,40 @@ list($nick, $name) = array_map("trim",explode("(",$item['author-name'])); $name=str_replace(")","",$name); - + + if ($name == '') + $name = $nick; + + if ($nick == '') + $nick = $name; + + // Generating a random ID + if (!array_key_exists($nick, $usercache)) + $usercache[$nick] = mt_rand(2000000, 2100000); + $ret = array( - 'uid' => 0, - 'id' => 0, + 'id' => $usercache[$nick], 'name' => $name, 'screen_name' => $nick, 'location' => '', //$uinfo[0]['default-location'], + 'description' => '', 'profile_image_url' => $item['author-avatar'], 'url' => $item['author-link'], - 'contact_url' => 0, 'protected' => false, # + 'followers_count' => 0, 'friends_count' => 0, 'created_at' => '', + 'favourites_count' => 0, 'utc_offset' => 0, #XXX: fix me 'time_zone' => '', //$uinfo[0]['timezone'], - 'geo_enabled' => false, 'statuses_count' => 0, + 'following' => 1, + 'statusnet_blocking' => false, + 'notifications' => false, + 'uid' => 0, + 'contact_url' => 0, + 'geo_enabled' => false, 'lang' => 'en', #XXX: fix me - 'description' => '', - 'followers_count' => 0, - 'favourites_count' => 0, 'contributors_enabled' => false, 'follow_request_sent' => false, 'profile_background_color' => 'cfe8f6', @@ -393,7 +416,6 @@ 'profile_background_image_url' => '', 'profile_background_tile' => false, 'profile_use_background_image' => false, - 'notifications' => false, 'verified' => true, #XXX: fix me 'followers' => '', #XXX: fix me 'status' => array() @@ -591,16 +613,16 @@ $in_reply_to_screen_name = $lastwall['reply_author']; } $status_info = array( - 'created_at' => api_date($lastwall['created']), - 'id' => $lastwall['contact-id'], - 'text' => strip_tags(bbcode($lastwall['body'])), - 'source' => (($lastwall['app']) ? $lastwall['app'] : 'web'), + 'text' => html2plain(bbcode($lastwall['body']), 0), 'truncated' => false, + 'created_at' => api_date($lastwall['created']), 'in_reply_to_status_id' => $in_reply_to_status_id, + 'source' => (($lastwall['app']) ? $lastwall['app'] : 'web'), + 'id' => $lastwall['contact-id'], 'in_reply_to_user_id' => $in_reply_to_user_id, - 'favorited' => false, 'in_reply_to_screen_name' => $in_reply_to_screen_name, 'geo' => '', + 'favorited' => false, 'coordinates' => $lastwall['coord'], 'place' => $lastwall['location'], 'contributors' => '' @@ -650,7 +672,7 @@ $user_info['status'] = array( 'created_at' => api_date($lastwall['created']), 'id' => $lastwall['contact-id'], - 'text' => strip_tags(bbcode($lastwall['body'])), + 'text' => html2plain(bbcode($lastwall['body']), 0), 'source' => (($lastwall['app']) ? $lastwall['app'] : 'web'), 'truncated' => false, 'in_reply_to_status_id' => $in_reply_to_status_id, @@ -686,10 +708,17 @@ $count = (x($_REQUEST,'count')?$_REQUEST['count']:20); $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); if ($page<0) $page=0; - $since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + $since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + $max_id = (x($_REQUEST,'max_id')?$_REQUEST['max_id']:0); + //$since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); $start = $page*$count; + //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false); + + if ($max_id > 0) + $sql_extra = 'AND `item`.`id` <= '.intval($max_id); + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, @@ -715,6 +744,13 @@ case "atom": case "rss": $data = api_rss_extra($a, $data, $user_info); + break; + case "as": + $as = api_format_as($a, $ret, $user_info); + $as['title'] = $a->config['sitename']." Home Timeline"; + $as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all"; + return($as); + break; } return api_apply_template("timeline", $type, $data); @@ -722,6 +758,271 @@ api_register_func('api/statuses/home_timeline','api_statuses_home_timeline', true); api_register_func('api/statuses/friends_timeline','api_statuses_home_timeline', true); + function api_statuses_public_timeline(&$a, $type){ + if (local_user()===false) return false; + + $user_info = api_get_user($a); + // get last newtork messages + + + // params + $count = (x($_REQUEST,'count')?$_REQUEST['count']:20); + $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); + if ($page<0) $page=0; + $since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + $max_id = (x($_REQUEST,'max_id')?$_REQUEST['max_id']:0); + //$since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + + $start = $page*$count; + + //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false); + + if ($max_id > 0) + $sql_extra = 'AND `item`.`id` <= '.intval($max_id); + + /*$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, + `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid` + FROM `item`, `contact` + WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0 + AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' + AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' + AND `item`.`private` = 0 AND `item`.`wall` = 1 AND `user`.`hidewall` = 0 + AND `contact`.`id` = `item`.`contact-id` + AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 + $sql_extra + AND `item`.`id`>%d + ORDER BY `item`.`received` DESC LIMIT %d ,%d ", + intval($since_id), + intval($start), intval($count) + );*/ + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, + `contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`, + `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`, + `user`.`nickname`, `user`.`hidewall` + FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + LEFT JOIN `user` ON `user`.`uid` = `item`.`uid` + WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0 + AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' + AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' + AND `item`.`private` = 0 AND `item`.`wall` = 1 AND `user`.`hidewall` = 0 + AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 + $sql_extra + AND `item`.`id`>%d + ORDER BY `received` DESC LIMIT %d, %d ", + intval($since_id), + intval($start), + intval($count)); + + $ret = api_format_items($r,$user_info); + + + $data = array('$statuses' => $ret); + switch($type){ + case "atom": + case "rss": + $data = api_rss_extra($a, $data, $user_info); + break; + case "as": + $as = api_format_as($a, $ret, $user_info); + $as['title'] = $a->config['sitename']." Public Timeline"; + $as['link']['url'] = $a->get_baseurl()."/"; + return($as); + break; + } + + return api_apply_template("timeline", $type, $data); + } + api_register_func('api/statuses/public_timeline','api_statuses_public_timeline', true); + + /** + * + */ + function api_statuses_show(&$a, $type){ + if (local_user()===false) return false; + + $user_info = api_get_user($a); + + // params + $id = intval($a->argv[3]); + + logger('API: api_statuses_show: '.$id); + + //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false); + + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, + `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid` + FROM `item`, `contact` + WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0 + AND `contact`.`id` = `item`.`contact-id` + AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 + $sql_extra + AND `item`.`id`=%d", + intval($id) + ); + + $ret = api_format_items($r,$user_info); + + $data = array('$status' => $ret[0]); + /*switch($type){ + case "atom": + case "rss": + $data = api_rss_extra($a, $data, $user_info); + }*/ + return api_apply_template("status", $type, $data); + } + api_register_func('api/statuses/show','api_statuses_show', true); + + + /** + * + */ + function api_statuses_repeat(&$a, $type){ + if (local_user()===false) return false; + + $user_info = api_get_user($a); + + // params + $id = intval($a->argv[3]); + + logger('API: api_statuses_repeat: '.$id); + + //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false); + + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `contact`.`nick` as `reply_author`, + `contact`.`name`, `contact`.`photo`, `contact`.`url` as `reply_url`, `contact`.`rel`, + `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid` + FROM `item`, `contact` + WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0 + AND `contact`.`id` = `item`.`contact-id` + AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 + $sql_extra + AND `item`.`id`=%d", + intval($id) + ); + + $_REQUEST['body'] = html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8')."[url=".$r[0]['reply_url']."]".$r[0]['reply_author']."[/url] \n".$r[0]['body']; + $_REQUEST['profile_uid'] = local_user(); + $_REQUEST['type'] = 'wall'; + $_REQUEST['api_source'] = true; + + require_once('mod/item.php'); + item_post($a); + + if ($type == 'xml') + $ok = "true"; + else + $ok = "ok"; + + return api_apply_template('test', $type, array('$ok' => $ok)); + } + api_register_func('api/statuses/retweet','api_statuses_repeat', true); + + /** + * + */ + function api_statuses_destroy(&$a, $type){ + if (local_user()===false) return false; + + $user_info = api_get_user($a); + + // params + $id = intval($a->argv[3]); + + logger('API: api_statuses_destroy: '.$id); + + require_once('include/items.php'); + drop_item($id, false); + + if ($type == 'xml') + $ok = "true"; + else + $ok = "ok"; + + return api_apply_template('test', $type, array('$ok' => $ok)); + } + api_register_func('api/statuses/destroy','api_statuses_destroy', true); + + /** + * + * http://developer.twitter.com/doc/get/statuses/mentions + * + */ + function api_statuses_mentions(&$a, $type){ + if (local_user()===false) return false; + + $user_info = api_get_user($a); + // get last newtork messages + + + // params + $count = (x($_REQUEST,'count')?$_REQUEST['count']:20); + $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); + if ($page<0) $page=0; + $since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + $max_id = (x($_REQUEST,'max_id')?$_REQUEST['max_id']:0); + //$since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + + $start = $page*$count; + + //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false); + + $myurl = $a->get_baseurl() . '/profile/'. $a->user['nickname']; + $myurl = substr($myurl,strpos($myurl,'://')+3); + $myurl = str_replace(array('www.','.'),array('','\\.'),$myurl); + $diasp_url = str_replace('/profile/','/u/',$myurl); + $sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where ( `author-link` regexp '%s' or `tag` regexp '%s' or tag regexp '%s' )) ", + dbesc($myurl . '$'), + dbesc($myurl . '\\]'), + dbesc($diasp_url . '\\]') + ); + + if ($max_id > 0) + $sql_extra .= ' AND `item`.`id` <= '.intval($max_id); + + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, + `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid` + FROM `item`, `contact` + WHERE `item`.`uid` = %d + AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0 + AND `contact`.`id` = `item`.`contact-id` + AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 + $sql_extra + AND `item`.`id`>%d + ORDER BY `item`.`received` DESC LIMIT %d ,%d ", + intval($user_info['uid']), + intval($since_id), + intval($start), intval($count) + ); + + $ret = api_format_items($r,$user_info); + + + $data = array('$statuses' => $ret); + switch($type){ + case "atom": + case "rss": + $data = api_rss_extra($a, $data, $user_info); + break; + case "as": + $as = api_format_as($a, $ret, $user_info); + $as["title"] = $a->config['sitename']." Mentions"; + $as['link']['url'] = $a->get_baseurl()."/"; + return($as); + break; + } + + return api_apply_template("timeline", $type, $data); + } + api_register_func('api/statuses/mentions','api_statuses_mentions', true); + api_register_func('api/statuses/replies','api_statuses_mentions', true); function api_statuses_user_timeline(&$a, $type){ @@ -740,7 +1041,8 @@ $count = (x($_REQUEST,'count')?$_REQUEST['count']:20); $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); if ($page<0) $page=0; - $since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + $since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + //$since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); $start = $page*$count; @@ -833,6 +1135,70 @@ api_register_func('api/favorites','api_favorites', true); + function api_format_as($a, $ret, $user_info) { + + $as = array(); + $as['title'] = $a->config['sitename']." Public Timeline"; + $items = array(); + foreach ($ret as $item) { + $singleitem["actor"]["displayName"] = $item["user"]["name"]; + $singleitem["actor"]["id"] = $item["user"]["contact_url"]; + $avatar[0]["url"] = $item["user"]["profile_image_url"]; + $avatar[0]["rel"] = "avatar"; + $avatar[0]["type"] = ""; + $avatar[0]["width"] = 96; + $avatar[0]["height"] = 96; + $avatar[1]["url"] = $item["user"]["profile_image_url"]; + $avatar[1]["rel"] = "avatar"; + $avatar[1]["type"] = ""; + $avatar[1]["width"] = 48; + $avatar[1]["height"] = 48; + $avatar[2]["url"] = $item["user"]["profile_image_url"]; + $avatar[2]["rel"] = "avatar"; + $avatar[2]["type"] = ""; + $avatar[2]["width"] = 24; + $avatar[2]["height"] = 24; + $singleitem["actor"]["avatarLinks"] = $avatar; + + $singleitem["actor"]["image"]["url"] = $item["user"]["profile_image_url"]; + $singleitem["actor"]["image"]["rel"] = "avatar"; + $singleitem["actor"]["image"]["type"] = ""; + $singleitem["actor"]["image"]["width"] = 96; + $singleitem["actor"]["image"]["height"] = 96; + $singleitem["actor"]["type"] = "person"; + $singleitem["actor"]["url"] = $item["person"]["contact_url"]; + $singleitem["actor"]["statusnet:profile_info"]["local_id"] = $item["user"]["id"]; + $singleitem["actor"]["statusnet:profile_info"]["following"] = $item["user"]["following"] ? "true" : "false"; + $singleitem["actor"]["statusnet:profile_info"]["blocking"] = "false"; + $singleitem["actor"]["contact"]["preferredUsername"] = $item["user"]["screen_name"]; + $singleitem["actor"]["contact"]["displayName"] = $item["user"]["name"]; + $singleitem["actor"]["contact"]["addresses"] = ""; + + $singleitem["body"] = $item["text"]; + $singleitem["object"]["displayName"] = $item["text"]; + $singleitem["object"]["id"] = $item["url"]; + $singleitem["object"]["type"] = "note"; + $singleitem["object"]["url"] = $item["url"]; + //$singleitem["context"] =; + $singleitem["postedTime"] = date("c", strtotime($item["published"])); + $singleitem["provider"]["objectType"] = "service"; + $singleitem["provider"]["displayName"] = "Test"; + $singleitem["provider"]["url"] = "http://test.tld"; + $singleitem["title"] = $item["text"]; + $singleitem["verb"] = "post"; + $singleitem["statusnet:notice_info"]["local_id"] = $item["id"]; + $singleitem["statusnet:notice_info"]["source"] = $item["source"]; + $singleitem["statusnet:notice_info"]["favorite"] = "false"; + $singleitem["statusnet:notice_info"]["repeated"] = "false"; + //$singleitem["original"] = $item; + $items[] = $singleitem; + } + $as['items'] = $items; + $as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all"; + $as['link']['rel'] = "alternate"; + $as['link']['type'] = "text/html"; + return($as); + } function api_format_items($r,$user_info) { @@ -846,33 +1212,64 @@ foreach($r as $item) { localize_item($item); $status_user = (($item['cid']==$user_info['id'])?$user_info: api_item_get_user($a,$item)); + + if ($item['parent']!=$item['id']) { + $r = q("select id from item where parent=%s and id<%s order by id desc limit 1", + intval($item['parent']), intval($item['id'])); + if ($r) + $in_reply_to_status_id = $r[0]['id']; + else + $in_reply_to_status_id = $item['parent']; + + $r = q("select `item`.`contact-id`, `contact`.nick, `item`.`author-name` from item, contact + where `contact`.`id` = `item`.`contact-id` and `item`.id=%d", intval($in_reply_to_status_id)); + + $in_reply_to_screen_name = $r[0]['author-name']; + $in_reply_to_user_id = $r[0]['contact-id']; + + } else { + $in_reply_to_screen_name = ''; + $in_reply_to_user_id = 0; + $in_reply_to_status_id = 0; + } + $status = array( + 'text' => trim($item['title']." \n".html2plain(bbcode($item['body']), 0)), + 'truncated' => False, 'created_at'=> api_date($item['created']), - 'published' => api_date($item['created']), - 'updated' => api_date($item['edited']), - 'id' => intval($item['id']), - 'message_id' => $item['uri'], - 'text' => strip_tags(bbcode($item['body'])), - 'statusnet_html' => bbcode($item['body']), + 'in_reply_to_status_id' => $in_reply_to_status_id, 'source' => (($item['app']) ? $item['app'] : 'web'), - 'url' => ($item['plink']!=''?$item['plink']:$item['author-link']), - 'truncated' => False, - 'in_reply_to_status_id' => ($item['parent']!=$item['id']? intval($item['parent']):''), - 'in_reply_to_user_id' => '', - 'favorited' => $item['starred'] ? true : false, - 'in_reply_to_screen_name' => '', + 'id' => intval($item['id']), + 'in_reply_to_user_id' => $in_reply_to_user_id, + 'in_reply_to_screen_name' => $in_reply_to_screen_name, 'geo' => '', - 'coordinates' => $item['coord'], - 'place' => $item['location'], - 'contributors' => '', - 'annotations' => '', - 'entities' => '', + 'favorited' => $item['starred'] ? true : false, 'user' => $status_user , - 'objecttype' => (($item['object-type']) ? $item['object-type'] : ACTIVITY_OBJ_NOTE), - 'verb' => (($item['verb']) ? $item['verb'] : ACTIVITY_POST), - 'self' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type, - 'edit' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type, + 'statusnet_html' => bbcode($item['body']), + 'statusnet_conversation_id' => 0, ); + + // Seesmic doesn't like the following content + if ($_SERVER['HTTP_USER_AGENT'] != 'Seesmic') { + $status2 = array( + 'updated' => api_date($item['edited']), + 'published' => api_date($item['created']), + 'message_id' => $item['uri'], + 'url' => ($item['plink']!=''?$item['plink']:$item['author-link']), + 'coordinates' => $item['coord'], + 'place' => $item['location'], + 'contributors' => '', + 'annotations' => '', + 'entities' => '', + 'objecttype' => (($item['object-type']) ? $item['object-type'] : ACTIVITY_OBJ_NOTE), + 'verb' => (($item['verb']) ? $item['verb'] : ACTIVITY_POST), + 'self' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type, + 'edit' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type, + ); + + $status = array_merge($status, $status2); + } + $ret[]=$status; }; return $ret; @@ -882,17 +1279,31 @@ function api_account_rate_limit_status(&$a,$type) { $hash = array( + 'reset_time_in_seconds' => strtotime('now + 1 hour'), 'remaining_hits' => (string) 150, 'hourly_limit' => (string) 150, 'reset_time' => datetime_convert('UTC','UTC','now + 1 hour',ATOM_TIME), - 'reset_time_in_seconds' => strtotime('now + 1 hour') ); + if ($type == "xml") + $hash['resettime_in_seconds'] = $hash['reset_time_in_seconds']; return api_apply_template('ratelimit', $type, array('$hash' => $hash)); } api_register_func('api/account/rate_limit_status','api_account_rate_limit_status',true); + function api_help_test(&$a,$type) { + + if ($type == 'xml') + $ok = "true"; + else + $ok = "ok"; + + return api_apply_template('test', $type, array('$ok' => $ok)); + + } + api_register_func('api/help/test','api_help_test',true); + /** * https://dev.twitter.com/docs/api/1/get/statuses/friends * This function is deprecated by Twitter @@ -1075,7 +1486,7 @@ 'recipient_screen_name'=> $recipient['screen_name'], 'recipient'=> $recipient, - 'text'=> $item['title']."\n".strip_tags(bbcode($item['body'])) , + 'text'=> $item['title']."\n".html2plain(bbcode($item['body']), 0) , ); @@ -1144,7 +1555,7 @@ 'recipient_screen_name'=> $recipient['screen_name'], 'recipient'=> $recipient, - 'text'=> $item['title']."\n".strip_tags(bbcode($item['body'])) , + 'text'=> $item['title']."\n".html2plain(bbcode($item['body']), 0) , ); @@ -1197,4 +1608,31 @@ api_register_func('api/oauth/request_token', 'api_oauth_request_token', false); api_register_func('api/oauth/access_token', 'api_oauth_access_token', false); - +/* +Not implemented by now: +favorites +favorites/create +favorites/destroy +statuses/retweets_of_me +friendships/create +friendships/destroy +friendships/exists +friendships/show +account/update_location +account/update_profile_background_image +account/update_profile_image +blocks/create +blocks/destroy +oauth/authorize + +Not implemented in status.net: +statuses/retweeted_to_me +statuses/retweeted_by_me +direct_messages/destroy +account/end_session +account/update_delivery_device +notifications/follow +notifications/leave +blocks/exists +blocks/blocking +*/ diff --git a/include/attach.php b/include/attach.php index 6d611cec0..6d611cec0 100755..100644 --- a/include/attach.php +++ b/include/attach.php diff --git a/include/auth.php b/include/auth.php index fc52684e6..1341f3bb8 100755..100644 --- a/include/auth.php +++ b/include/auth.php @@ -24,7 +24,7 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p if(((x($_POST,'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) { // process logout request - + call_hooks("logging_out"); nuke_session(); info( t('Logged out.') . EOL); goaway(z_root()); @@ -77,7 +77,7 @@ else { $noid = get_config('system','no_openid'); - $openid_url = trim( (strlen($_POST['openid_url'])?$_POST['openid_url']:$_POST['username']) ); + $openid_url = trim((strlen($_POST['openid_url'])?$_POST['openid_url']:$_POST['username']) ); // validate_url alters the calling parameter @@ -94,37 +94,21 @@ else { // Otherwise it's probably an openid. + try { require_once('library/openid.php'); $openid = new LightOpenID; $openid->identity = $openid_url; $_SESSION['openid'] = $openid_url; $a = get_app(); - $openid->returnUrl = $a->get_baseurl() . '/openid'; - - $r = q("SELECT `uid` FROM `user` WHERE `openid` = '%s' LIMIT 1", - dbesc($openid_url) - ); - if(count($r)) { - // existing account - goaway($openid->authUrl()); - // NOTREACHED - } - else { - if($a->config['register_policy'] == REGISTER_CLOSED) { - $a = get_app(); - notice( t('Login failed.') . EOL); - goaway(z_root()); - // NOTREACHED - } - // new account - $_SESSION['register'] = 1; - $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson'); - $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default'); - goaway($openid->authUrl()); - // NOTREACHED - } + $openid->returnUrl = $a->get_baseurl(true) . '/openid'; + goaway($openid->authUrl()); + } catch (Exception $e) { + notice( t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'. t('The error message was:').' '.$e->getMessage()); + } + // NOTREACHED } } + if((x($_POST,'auth-params')) && $_POST['auth-params'] === 'login') { $record = null; @@ -165,7 +149,7 @@ else { } if((! $record) || (! count($record))) { - logger('authenticate: failed login attempt: ' . notags(trim($_POST['username']))); + logger('authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR']); notice( t('Login failed.') . EOL ); goaway(z_root()); } diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index 8487f845a..8487f845a 100755..100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php diff --git a/include/bbcode.php b/include/bbcode.php index cff26f5c8..3697f1fc5 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -189,8 +189,29 @@ function bbcode($Text,$preserve_nl = false) { // Check for [code] text $Text = preg_replace("/\[code\](.*?)\[\/code\]/ism","$CodeLayout", $Text); + // Declare the format for [spoiler] layout + $SpoilerLayout = '<blockquote class="spoiler">$1</blockquote>'; + + // Check for [spoiler] text + // handle nested quotes + $endlessloop = 0; + while ((strpos($Text, "[/spoiler]") !== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20)) + $Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism","$SpoilerLayout", $Text); + + // Check for [spoiler=Author] text + + $t_wrote = t('$1 wrote:'); + + // handle nested quotes + $endlessloop = 0; + while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler=") !== false) and (++$endlessloop < 20)) + $Text = preg_replace("/\[spoiler=[\"\']*(.*?)[\"\']*\](.*?)\[\/spoiler\]/ism", + "<br /><strong class=".'"spoiler"'.">" . $t_wrote . "</strong><blockquote class=".'"spoiler"'.">$2</blockquote>", + $Text); + // Declare the format for [quote] layout $QuoteLayout = '<blockquote>$1</blockquote>'; + // Check for [quote] text // handle nested quotes $endlessloop = 0; @@ -205,17 +226,21 @@ function bbcode($Text,$preserve_nl = false) { $endlessloop = 0; while ((strpos($Text, "[/quote]")!== false) and (strpos($Text, "[quote=") !== false) and (++$endlessloop < 20)) $Text = preg_replace("/\[quote=[\"\']*(.*?)[\"\']*\](.*?)\[\/quote\]/ism", - "<blockquote><strong>" . $t_wrote . "</strong> $2</blockquote>", + "<br /><strong class=".'"author"'.">" . $t_wrote . "</strong><blockquote class=".'"author"'.">$2</blockquote>", $Text); // [img=widthxheight]image source[/img] - $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="height: $2px; width: $1px;" >', $Text); + //$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="height: $2px; width: $1px;" >', $Text); + $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" >', $Text); // Images // [img]pathtoimage[/img] $Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img src="$1" alt="' . t('Image/photo') . '" />', $Text); + $Text = preg_replace("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4))\[\/video\]/ism", '<video src="$1" controls="controls" width="425" height="350"><a href="$1">$1</a></video>', $Text); + + $Text = preg_replace("/\[audio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3))\[\/audio\]/ism", '<audio src="$1" controls="controls"><a href="$1">$1</a></audio>', $Text); // Try to Oembed $Text = preg_replace_callback("/\[video\](.*?)\[\/video\]/ism", 'tryoembed', $Text); @@ -224,9 +249,6 @@ function bbcode($Text,$preserve_nl = false) { // html5 video and audio - $Text = preg_replace("/\[video\](.*?)\[\/video\]/ism", '<video src="$1" controls="controls" width="425" height="350"><a href="$1">$1</a></video>', $Text); - - $Text = preg_replace("/\[audio\](.*?)\[\/audio\]/ism", '<audio src="$1" controls="controls"><a href="$1">$1</a></audio>', $Text); $Text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<iframe src="$1" width="425" height="350"><a href="$1">$1</a></iframe>', $Text); diff --git a/include/cache.php b/include/cache.php index 3c8a3f713..3c8a3f713 100755..100644 --- a/include/cache.php +++ b/include/cache.php diff --git a/include/config.php b/include/config.php index 2cddda0b8..4cff38090 100755 --- a/include/config.php +++ b/include/config.php @@ -80,6 +80,7 @@ function set_config($family,$key,$value) { // manage array value $dbvalue = (is_array($value)?serialize($value):$value); + $dbvalue = (is_bool($value) ? intval($value) : $value); if(get_config($family,$key,true) === false) { $a->config[$family][$key] = $value; diff --git a/include/contact_selectors.php b/include/contact_selectors.php index 4b3ca987a..4b3ca987a 100755..100644 --- a/include/contact_selectors.php +++ b/include/contact_selectors.php diff --git a/include/contact_widgets.php b/include/contact_widgets.php index caa0572d2..e0f37f078 100755..100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -15,8 +15,6 @@ function findpeople_widget() { $a = get_app(); - $inv = (($a->config['register_policy'] != REGISTER_CLOSED) ? t('Invite Friends') : ''); - if(get_config('system','invitation_only')) { $x = get_pconfig(local_user(),'system','invites_remaining'); if($x || is_site_admin()) { @@ -34,7 +32,7 @@ function findpeople_widget() { '$findthem' => t('Find'), '$suggest' => t('Friend Suggestions'), '$similar' => t('Similar Interests'), - '$inv' => $inv + '$inv' => t('Invite Friends') )); } @@ -48,7 +46,7 @@ function networks_widget($baseurl,$selected = '') { return ''; - $r = q("select distinct(network) from contact where uid = %d", + $r = q("select distinct(network) from contact where uid = %d and self = 0", intval(local_user()) ); @@ -75,4 +73,61 @@ function networks_widget($baseurl,$selected = '') { )); } +function fileas_widget($baseurl,$selected = '') { + $a = get_app(); + if(! local_user()) + return ''; + + $saved = get_pconfig(local_user(),'system','filetags'); + if(! strlen($saved)) + return; + + $matches = false; + $terms = array(); + $cnt = preg_match_all('/\[(.*?)\]/',$saved,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $unescaped = xmlify(file_tag_decode($mtch[1])); + $terms[] = array('name' => $unescaped,'selected' => (($selected == $unescaped) ? 'selected' : '')); + } + } + + return replace_macros(get_markup_template('fileas_widget.tpl'),array( + '$title' => t('Saved Folders'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $baseurl, + + )); +} + +function categories_widget($baseurl,$selected = '') { + $a = get_app(); + + $saved = get_pconfig($a->profile['profile_uid'],'system','filetags'); + if(! strlen($saved)) + return; + + $matches = false; + $terms = array(); + $cnt = preg_match_all('/<(.*?)>/',$saved,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $unescaped = xmlify(file_tag_decode($mtch[1])); + $terms[] = array('name' => $unescaped,'selected' => (($selected == $unescaped) ? 'selected' : '')); + } + } + + return replace_macros(get_markup_template('categories_widget.tpl'),array( + '$title' => t('Categories'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $baseurl, + + )); +} diff --git a/include/conversation.php b/include/conversation.php index f4740688c..df92a40ed 100755..100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -94,9 +94,9 @@ function localize_item(&$item){ } - $A = '[url=' . $Alink . ']' . $Aname . '[/url]'; - $B = '[url=' . $Blink . ']' . $Bname . '[/url]'; - if ($Bphoto!="") $Bphoto = '[url=' . $Blink . '][img]' . $Bphoto . '[/img][/url]'; + $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]'; + $B = '[url=' . zrl($Blink) . ']' . $Bname . '[/url]'; + if ($Bphoto!="") $Bphoto = '[url=' . zrl($Blink) . '][img]' . $Bphoto . '[/img][/url]'; $item['body'] = sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto; @@ -108,8 +108,8 @@ function localize_item(&$item){ if(count($r)==0) return; $obj=$r[0]; - $author = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]'; - $objauthor = '[url=' . $obj['author-link'] . ']' . $obj['author-name'] . '[/url]'; + $author = '[url=' . zrl($item['author-link']) . ']' . $item['author-name'] . '[/url]'; + $objauthor = '[url=' . zrl($obj['author-link']) . ']' . $obj['author-name'] . '[/url]'; switch($obj['verb']){ case ACTIVITY_POST: @@ -158,14 +158,21 @@ function localize_item(&$item){ $target = $r[0]; $Bname = $target['author-name']; $Blink = $target['author-link']; - $A = '[url=' . $Alink . ']' . $Aname . '[/url]'; - $B = '[url=' . $Blink . ']' . $Bname . '[/url]'; + $A = '[url=' . zrl($Alink) . ']' . $Aname . '[/url]'; + $B = '[url=' . zrl($Blink) . ']' . $Bname . '[/url]'; $P = '[url=' . $target['plink'] . ']' . t('post/item') . '[/url]'; $item['body'] = sprintf( t('%1$s marked %2$s\'s %3$s as favorite'), $A, $B, $P)."\n"; } } } + $matches = null; + if(preg_match_all('/@\[url=(.*?)\]/is',$item['body'],$matches,PREG_SET_ORDER)) { + foreach($matches as $mtch) { + if(! strpos($mtch[1],'zrl=')) + $item['body'] = str_replace($mtch[0],'@[url=' . zrl($mtch[1]). ']',$item['body']); + } + } } @@ -179,11 +186,15 @@ function localize_item(&$item){ * that are based on unique features of the calling module. * */ - if(!function_exists('conversation')){ + +if(!function_exists('conversation')) { function conversation(&$a, $items, $mode, $update, $preview = false) { + require_once('bbcode.php'); + $ssl_state = ((local_user()) ? true : false); + $profile_owner = 0; $page_writeable = false; @@ -217,7 +228,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { if($update) $return_url = $_SESSION['return_url']; else - $return_url = $_SESSION['return_url'] = $a->cmd; + $return_url = $_SESSION['return_url'] = $a->query_string; load_contact_links(local_user()); @@ -239,7 +250,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $threads = array(); $threadsid = -1; - if(count($items)) { + if($items && count($items)) { if($mode === 'network-new' || $mode === 'search' || $mode === 'community') { @@ -272,13 +283,16 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { if($item['author-link'] && (! $item['author-name'])) $profile_name = $item['author-link']; + + $sp = false; $profile_link = best_link_url($item,$sp); - if($sp) - $sparkle = ' sparkle'; if($profile_link === 'mailbox') $profile_link = ''; - + if($sp) + $sparkle = ' sparkle'; + else + $profile_link = zrl($profile_link); $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']); if(($normalised != 'mailbox') && (x($a->contacts[$normalised]))) @@ -343,7 +357,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { 'like' => '', 'dislike' => '', 'comment' => '', - 'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl() . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))), + 'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state) . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))), 'previewing' => $previewing, 'wait' => t('Please wait'), ); @@ -373,7 +387,8 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $comments[$item['parent']] = 1; else $comments[$item['parent']] += 1; - } + } elseif(! x($comments,$item['parent'])) + $comments[$item['parent']] = 0; // avoid notices later on } // map all the like/dislike activities for each parent item @@ -418,26 +433,6 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $toplevelprivate = (($toplevelpost && $item['private']) ? true : false); $item_writeable = (($item['writable'] || $item['self']) ? true : false); - // DISABLED - /* - if($blowhard == $item['cid'] && (! $item['self']) && ($mode != 'profile') && ($mode != 'notes')) { - $blowhard_count ++; - if($blowhard_count == 3) { - $o .= '<div class="icollapse-wrapper fakelink" id="icollapse-wrapper-' . $item['parent'] - . '" onclick="openClose(' . '\'icollapse-' . $item['parent'] . '\'); $(\'#icollapse-wrapper-' . $item['parent'] . '\').hide();" >' - . t('See more posts like this') . '</div>' . '<div class="icollapse" id="icollapse-' - . $item['parent'] . '" style="display: none;" >'; - } - } - else { - $blowhard = $item['cid']; - if($blowhard_count >= 3) - $o .= '</div>'; - $blowhard_count = 0; - } - // END DISABLED - */ - $comments_seen = 0; $comments_collapsed = false; $comment_lastcollapsed = false; @@ -445,13 +440,16 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $threadsid++; $threads[$threadsid]['id'] = $item['item_id']; + $threads[$threadsid]['private'] = $item['private']; $threads[$threadsid]['items'] = array(); } else { - // prevent private email from leaking into public conversation - if((! $toplevelpost) && (! $toplevelprivate) && ($item['private']) && ($profile_owner != local_user())) + + // prevent private email reply to public conversation from leaking. + if($item['private'] && ! $threads[$threadsid]['private']) continue; + $comments_seen ++; $comment_lastcollapsed = false; $comment_firstcollapsed = false; @@ -475,7 +473,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $comment_lastcollapsed = true; } - $redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ; + $redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ; $lock = ((($item['private']) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])))) @@ -496,13 +494,13 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { // This will have been stored in $a->page_contact by our calling page. // Put this person on the left of the wall-to-wall notice. - $owner_url = $a->page_contact['url']; + $owner_url = zrl($a->page_contact['url']); $owner_photo = $a->page_contact['thumb']; $owner_name = $a->page_contact['name']; $template = $wallwall; $commentww = 'ww'; } - if((! $item['wall']) && (strlen($item['owner-link'])) && ($item['owner-link'] != $item['author-link'])) { + if((! $item['wall']) && (strlen($item['owner-link'])) && (! link_compare($item['owner-link'],$item['author-link']))) { // Could be anybody. @@ -513,10 +511,12 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $commentww = 'ww'; // If it is our contact, use a friendly redirect link if((link_compare($item['owner-link'],$item['url'])) - && ($item['network'] === 'dfrn')) { + && ($item['network'] === NETWORK_DFRN)) { $owner_url = $redirect_url; $osparkle = ' sparkle'; } + else + $owner_url = zrl($owner_url); } } @@ -532,9 +532,12 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { if ($shareable) $likebuttons['share'] = array( t('Share this'), t('share')); } + $qc = $qcomment = null; - $qc = ((local_user()) ? get_pconfig(local_user(),'qcomment','words') : null); - $qcomment = (($qc) ? explode("\n",$qc) : null); + if(in_array('qcomment',$a->plugins)) { + $qc = ((local_user()) ? get_pconfig(local_user(),'qcomment','words') : null); + $qcomment = (($qc) ? explode("\n",$qc) : null); + } if(($show_comment_box) || (($show_comment_box == false) && ($override_comment_box == false) && ($item['last-child']))) { $comment = replace_macros($cmnt_tpl,array( @@ -557,7 +560,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { } $edpost = (((($profile_owner == local_user()) && ($toplevelpost) && (intval($item['wall']) == 1)) || ($mode === 'notes')) - ? array($a->get_baseurl()."/editpost/".$item['id'], t("Edit")) + ? array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit")) : False); @@ -574,24 +577,28 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { ); $star = false; + $filer = false; + $isstarred = "unstarred"; - if ($profile_owner == local_user() && $toplevelpost) { - $isstarred = (($item['starred']) ? "starred" : "unstarred"); - - $star = array( - 'do' => t("add star"), - 'undo' => t("remove star"), - 'toggle' => t("toggle star status"), - 'classdo' => (($item['starred']) ? "hidden" : ""), - 'classundo' => (($item['starred']) ? "" : "hidden"), - 'starred' => t('starred'), - 'tagger' => t("add tag"), - 'classtagger' => "", - ); + if ($profile_owner == local_user()) { + if($toplevelpost) { + $isstarred = (($item['starred']) ? "starred" : "unstarred"); + + $star = array( + 'do' => t("add star"), + 'undo' => t("remove star"), + 'toggle' => t("toggle star status"), + 'classdo' => (($item['starred']) ? "hidden" : ""), + 'classundo' => (($item['starred']) ? "" : "hidden"), + 'starred' => t('starred'), + 'tagger' => t("add tag"), + 'classtagger' => "", + ); + } + $filer = t("save to folder"); } - $photo = $item['photo']; $thumb = $item['thumb']; @@ -604,14 +611,14 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { if($item['author-link'] && (! $item['author-name'])) $profile_name = $item['author-link']; - $sp = false; $profile_link = best_link_url($item,$sp); - if($sp) - $sparkle = ' sparkle'; - if($profile_link === 'mailbox') $profile_link = ''; + if($sp) + $sparkle = ' sparkle'; + else + $profile_link = zrl($profile_link); $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']); if(($normalised != 'mailbox') && (x($a->contacts,$normalised))) @@ -657,7 +664,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { // template to use to render item (wall, walltowall, search) 'template' => $template, - 'type' => implode("",array_slice(split("/",$item['verb']),-1)), + 'type' => implode("",array_slice(explode("/",$item['verb']),-1)), 'tags' => $tags, 'body' => template_escape($body), 'text' => strip_tags(template_escape($body)), @@ -685,6 +692,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { 'edpost' => $edpost, 'isstarred' => $isstarred, 'star' => $star, + 'filer' => $filer, 'drop' => $drop, 'vote' => $likebuttons, 'like' => $like, @@ -706,7 +714,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $page_template = get_markup_template("conversation.tpl"); $o .= replace_macros($page_template, array( - '$baseurl' => $a->get_baseurl(), + '$baseurl' => $a->get_baseurl($ssl_state), '$mode' => $mode, '$user' => $a->user, '$threads' => $threads, @@ -716,7 +724,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { return $o; }} -function best_link_url($item,&$sparkle) { +function best_link_url($item,&$sparkle,$ssl_state = false) { $a = get_app(); @@ -728,7 +736,7 @@ function best_link_url($item,&$sparkle) { if((local_user()) && (local_user() == $item['uid'])) { if(isset($a->contacts) && x($a->contacts,$clean_url)) { if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) { - $best_url = $a->get_baseurl() . '/redir/' . $a->contacts[$clean_url]['id']; + $best_url = $a->get_baseurl($ssl_state) . '/redir/' . $a->contacts[$clean_url]['id']; $sparkle = true; } else @@ -749,10 +757,14 @@ function best_link_url($item,&$sparkle) { if(! function_exists('item_photo_menu')){ function item_photo_menu($item){ $a = get_app(); - - if (local_user() && (! count($a->contacts))) - load_contact_links(local_user()); + $ssl_state = false; + + if(local_user()) { + $ssl_state = true; + if(! count($a->contacts)) + load_contact_links(local_user()); + } $contact_url=""; $pm_url=""; $status_link=""; @@ -760,7 +772,7 @@ function item_photo_menu($item){ $posts_link=""; $sparkle = false; - $profile_link = best_link_url($item,$sparkle); + $profile_link = best_link_url($item,$sparkle,$ssl_state); if($profile_link === 'mailbox') $profile_link = ''; @@ -769,9 +781,11 @@ function item_photo_menu($item){ $status_link = $profile_link . "?url=status"; $photos_link = $profile_link . "?url=photos"; $profile_link = $profile_link . "?url=profile"; - $pm_url = $a->get_baseurl() . '/message/new/' . $cid; + $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid; + $zurl = ''; } else { + $profile_link = zrl($profile_link); if(local_user() && local_user() == $item['uid'] && link_compare($item['url'],$item['author-link'])) { $cid = $item['contact-id']; } @@ -780,14 +794,25 @@ function item_photo_menu($item){ } } if(($cid) && (! $item['self'])) { - $contact_url = $a->get_baseurl() . '/contacts/' . $cid; - $posts_link = $a->get_baseurl() . '/network/?cid=' . $cid; + $contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid; + $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $cid; + + $clean_url = normalise_link($item['author-link']); + + if((local_user()) && (local_user() == $item['uid'])) { + if(isset($a->contacts) && x($a->contacts,$clean_url)) { + if($a->contacts[$clean_url]['network'] === NETWORK_DIASPORA) { + $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid; + } + } + } + } $menu = Array( t("View status") => $status_link, t("View profile") => $profile_link, - t("View photos") => $photos_link, + t("View photos") => $photos_link, t("View recent") => $posts_link, t("Edit contact") => $contact_url, t("Send PM") => $pm_url, @@ -817,9 +842,11 @@ function like_puller($a,$item,&$arr,$mode) { if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) { $url = $item['author-link']; if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === 'dfrn') && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) { - $url = $a->get_baseurl() . '/redir/' . $item['contact-id']; + $url = $a->get_baseurl(true) . '/redir/' . $item['contact-id']; $sparkle = ' class="sparkle" '; } + else + $url = zrl($url); if(! ((isset($arr[$item['parent'] . '-l'])) && (is_array($arr[$item['parent'] . '-l'])))) $arr[$item['parent'] . '-l'] = array(); if(! isset($arr[$item['parent']])) @@ -879,7 +906,7 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { $a->page['htmlhead'] .= replace_macros($tpl, array( '$newpost' => 'true', - '$baseurl' => $a->get_baseurl(), + '$baseurl' => $a->get_baseurl(true), '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), '$geotag' => $geotag, '$nickname' => $x['nickname'], @@ -888,8 +915,8 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { '$vidurl' => t("Please enter a video link/URL:"), '$audurl' => t("Please enter an audio link/URL:"), '$term' => t('Tag term:'), - '$whereareu' => t('Where are you right now?'), - '$title' => t('Enter a title for this item') + '$fileas' => t('Save to Folder:'), + '$whereareu' => t('Where are you right now?') )); @@ -929,8 +956,8 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { $o .= replace_macros($tpl,array( '$return_path' => $a->cmd, - '$action' => $a->get_baseurl().'/item', - '$share' => (($x['button']) ? $x['button'] : t('Share')), + '$action' => $a->get_baseurl(true) . '/item', + '$share' => (x($x,'button') ? $x['button'] : t('Share')), '$upload' => t('Upload photo'), '$shortupload' => t('upload photo'), '$attach' => t('Attach file'), @@ -947,13 +974,15 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { '$shortnoloc' => t('clear location'), '$title' => "", '$placeholdertitle' => t('Set title'), + '$category' => "", + '$placeholdercategory' => t('Categories (comma-separated list)'), '$wait' => t('Please wait'), '$permset' => t('Permission settings'), '$shortpermset' => t('permissions'), '$ptyp' => (($notes_cid) ? 'note' : 'wall'), '$content' => '', '$post_id' => '', - '$baseurl' => $a->get_baseurl(), + '$baseurl' => $a->get_baseurl(true), '$defloc' => $x['default_location'], '$visitor' => $x['visitor'], '$pvisit' => (($notes_cid) ? 'none' : $x['visitor']), @@ -995,8 +1024,8 @@ function conv_sort($arr,$order) { usort($parents,'sort_thr_commented'); if(count($parents)) - foreach($parents as $x) - $x['children'] = array(); + foreach($parents as $i=>$_x) + $parents[$i]['children'] = array(); foreach($arr as $x) { if($x['id'] != $x['parent']) { diff --git a/include/cronhooks.php b/include/cronhooks.php index 37541f013..37541f013 100755..100644 --- a/include/cronhooks.php +++ b/include/cronhooks.php diff --git a/include/crypto.php b/include/crypto.php index 0feb45c24..0feb45c24 100755..100644 --- a/include/crypto.php +++ b/include/crypto.php diff --git a/include/datetime.php b/include/datetime.php index 6d395fe3f..6d395fe3f 100755..100644 --- a/include/datetime.php +++ b/include/datetime.php diff --git a/include/dba.php b/include/dba.php index 7455b6b3e..76cc0bc7b 100755..100644 --- a/include/dba.php +++ b/include/dba.php @@ -1,5 +1,7 @@ <?php +require_once('include/datetime.php'); + /** * * MySQL database class @@ -104,19 +106,17 @@ class dba { logger('dba: ' . $str ); } - else { - /** - * If dbfail.out exists, we will write any failed calls directly to it, - * regardless of any logging that may or may nor be in effect. - * These usually indicate SQL syntax errors that need to be resolved. - */ + /** + * If dbfail.out exists, we will write any failed calls directly to it, + * regardless of any logging that may or may nor be in effect. + * These usually indicate SQL syntax errors that need to be resolved. + */ - if($result === false) { - logger('dba: ' . printable($sql) . ' returned false.'); - if(file_exists('dbfail.out')) - file_put_contents('dbfail.out', printable($sql) . ' returned false' . "\n", FILE_APPEND); - } + if($result === false) { + logger('dba: ' . printable($sql) . ' returned false.'); + if(file_exists('dbfail.out')) + file_put_contents('dbfail.out', datetime_convert() . "\n" . printable($sql) . ' returned false' . "\n", FILE_APPEND); } if(($result === true) || ($result === false)) @@ -140,7 +140,7 @@ class dba { if($this->debug) - logger('dba: ' . printable(print_r($r, true)), LOGGER_DATA); + logger('dba: ' . printable(print_r($r, true))); return($r); } @@ -207,8 +207,10 @@ function q($sql) { unset($args[0]); if($db && $db->connected) { - $ret = $db->q(vsprintf($sql,$args)); - return $ret; + $stmt = vsprintf($sql,$args); + if($stmt === false) + logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true)); + return $db->q($stmt); } /** diff --git a/include/delivery.php b/include/delivery.php index c1ff07bd5..794b8f27a 100755..100644 --- a/include/delivery.php +++ b/include/delivery.php @@ -256,7 +256,8 @@ function delivery_run($argv, $argc){ '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) , '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) , '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) , - '$birthday' => $birthday + '$birthday' => $birthday, + '$community' => (($owner['page-flags'] == PAGE_COMMUNITY) ? '<dfrn:community>1</dfrn:community>' : '') )); foreach($items as $item) { @@ -320,6 +321,14 @@ function delivery_run($argv, $argc){ $x[0]['writable'] = 1; } + $ssl_policy = get_config('system','ssl_policy'); + fix_contact_ssl_policy($x[0],$ssl_policy); + + // If we are setup as a soapbox we aren't accepting input from this person + + if($x[0]['page-flags'] == PAGE_SOAPBOX) + break; + require_once('library/simplepie/simplepie.inc'); logger('mod-delivery: local delivery'); local_delivery($x[0],$atom); @@ -435,8 +444,8 @@ function delivery_run($argv, $argc){ $headers .= 'Reply-to: ' . $reply_to . "\n"; // for testing purposes: Collect exported mails - $file = tempnam("/tmp/friendica/", "mail-out-"); - file_put_contents($file, json_encode($it)); + // $file = tempnam("/tmp/friendica/", "mail-out-"); + // file_put_contents($file, json_encode($it)); $headers .= 'Message-Id: <' . iri2msgid($it['uri']). '>' . "\n"; @@ -446,30 +455,16 @@ function delivery_run($argv, $argc){ if($it['uri'] !== $it['parent-uri']) { $headers .= 'References: <' . iri2msgid($it['parent-uri']) . '>' . "\n"; - if(! strlen($it['title'])) { + if(!strlen($it['title'])) { $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' LIMIT 1", - dbesc($it['parent-uri']) - ); - if(count($r)) { - $subtitle = $r[0]['title']; - if($subtitle) { - if(strncasecmp($subtitle,'RE:',3)) - $subject = $subtitle; - else - $subject = 'Re: ' . $subtitle; - } - } + dbesc($it['parent-uri'])); + + if(count($r) AND ($r[0]['title'] != '')) + $subject = $r[0]['title']; } + if(strncasecmp($subject,'RE:',3)) + $subject = 'Re: '.$subject; } - /*$headers .= 'MIME-Version: 1.0' . "\n"; - //$headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; - $headers .= 'Content-Type: text/plain; charset=UTF-8' . "\n"; - $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; - $html = prepare_body($it); - //$message = '<html><body>' . $html . '</body></html>'; - $message = html2plain($html); - logger('notifier: email delivery to ' . $addr); - mail($addr, $subject, $message, $headers);*/ email_send($addr, $subject, $headers, $it); } break; diff --git a/include/diaspora.php b/include/diaspora.php index dca857a19..06df9c24a 100755..100644 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -9,6 +9,12 @@ require_once('include/queue_fn.php'); function diaspora_dispatch_public($msg) { + $enabled = intval(get_config('system','diaspora_enabled')); + if(! $enabled) { + logger('mod-diaspora: disabled'); + return; + } + $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN ( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' ) AND `account_expired` = 0 ", dbesc(NETWORK_DIASPORA), dbesc($msg['author']) @@ -29,6 +35,12 @@ function diaspora_dispatch($importer,$msg) { $ret = 0; + $enabled = intval(get_config('system','diaspora_enabled')); + if(! $enabled) { + logger('mod-diaspora: disabled'); + return; + } + // php doesn't like dashes in variable names $msg['message'] = str_replace( @@ -688,9 +700,9 @@ function diaspora_post($importer,$xml) { // don't link tags that are already embedded in links - if(preg_match('/\[(.*?)' . preg_quote($tag) . '(.*?)\]/',$body)) + if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body)) continue; - if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag) . '(.*?)\)/',$body)) + if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body)) continue; $basetag = str_replace('_',' ',substr($tag,1)); @@ -853,9 +865,9 @@ function diaspora_reshare($importer,$xml) { // don't link tags that are already embedded in links - if(preg_match('/\[(.*?)' . preg_quote($tag) . '(.*?)\]/',$body)) + if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body)) continue; - if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag) . '(.*?)\)/',$body)) + if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body)) continue; @@ -1094,9 +1106,9 @@ function diaspora_comment($importer,$xml,$msg) { // don't link tags that are already embedded in links - if(preg_match('/\[(.*?)' . preg_quote($tag) . '(.*?)\]/',$body)) + if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body)) continue; - if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag) . '(.*?)\)/',$body)) + if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body)) continue; @@ -1159,6 +1171,48 @@ function diaspora_comment($importer,$xml,$msg) { proc_run('php','include/notifier.php','comment',$message_id); } + + $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ", + dbesc($parent_item['uri']), + intval($importer['uid']) + ); + + if(count($myconv)) { + $importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname']; + + foreach($myconv as $conv) { + + // now if we find a match, it means we're in this conversation + + if(! link_compare($conv['author-link'],$importer_url)) + continue; + + require_once('include/enotify.php'); + + $conv_parent = $conv['parent']; + + notification(array( + 'type' => NOTIFY_COMMENT, + 'notify_flags' => $importer['notify-flags'], + 'language' => $importer['language'], + 'to_name' => $importer['username'], + 'to_email' => $importer['email'], + 'uid' => $importer['uid'], + 'item' => $datarray, + 'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id, + 'source_name' => $datarray['author-name'], + 'source_link' => $datarray['author-link'], + 'source_photo' => $datarray['author-avatar'], + 'verb' => ACTIVITY_POST, + 'otype' => 'item', + 'parent' => $conv_parent, + + )); + + // only send one notification + break; + } + } return; } @@ -1695,7 +1749,7 @@ function diaspora_retraction($importer,$xml) { contact_remove($contact['id']); } elseif($type === 'Post') { - $r = q("select * from item where guid = '%s' and uid = %d limit 1", + $r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1", dbesc('guid'), intval($importer['uid']) ); @@ -1743,7 +1797,7 @@ function diaspora_signed_retraction($importer,$xml,$msg) { } if($type === 'StatusMessage') { - $r = q("select * from item where guid = '%s' and uid = %d limit 1", + $r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1", dbesc($guid), intval($importer['uid']) ); @@ -1878,6 +1932,7 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { $images = array(); + $title = $item['title']; $body = $item['body']; /* @@ -1902,9 +1957,12 @@ function diaspora_send_status($item,$owner,$contact,$public_batch = false) { } } */ - $body = xmlify(html_entity_decode(bb2diaspora($body))); + if(strlen($title)) + $body = xmlify('**' . html_entity_decode($title) . '**' . "\n") . $body; + + if($item['attach']) { $cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism',$item['attach'],$matches,PREG_SET_ORDER); if(cnt) { @@ -2225,6 +2283,11 @@ function diaspora_send_mail($item,$owner,$contact) { function diaspora_transmit($owner,$contact,$slap,$public_batch) { + $enabled = intval(get_config('system','diaspora_enabled')); + if(! $enabled) { + return 200; + } + $a = get_app(); $logid = random_string(4); $dest_url = (($public_batch) ? $contact['batch'] : $contact['notify']); diff --git a/include/directory.php b/include/directory.php index cae78adb4..cae78adb4 100755..100644 --- a/include/directory.php +++ b/include/directory.php diff --git a/include/email.php b/include/email.php index 659978b6e..b43ae0dc1 100755..100644 --- a/include/email.php +++ b/include/email.php @@ -1,5 +1,7 @@ <?php require_once('include/html2plain.php'); +require_once('include/msgclean.php'); +require_once('include/quoteconvert.php'); function email_connect($mailbox,$username,$password) { if(! function_exists('imap_open')) @@ -54,7 +56,7 @@ function email_msg_headers($mbox,$uid) { $raw_header = (($mbox && $uid) ? @imap_fetchheader($mbox,$uid,FT_UID) : ''); $raw_header = str_replace("\r",'',$raw_header); $ret = array(); - $h = split("\n",$raw_header); + $h = explode("\n",$raw_header); if(count($h)) foreach($h as $line ) { if (preg_match("/^[a-zA-Z]/", $line)) { @@ -72,7 +74,7 @@ function email_msg_headers($mbox,$uid) { } -function email_get_msg($mbox,$uid) { +function email_get_msg($mbox,$uid, $reply) { $ret = array(); $struc = (($mbox && $uid) ? @imap_fetchstructure($mbox,$uid,FT_UID) : null); @@ -86,6 +88,7 @@ function email_get_msg($mbox,$uid) { if(! $struc->parts) { $ret['body'] = email_get_part($mbox,$uid,$struc,0, 'html'); + $html = $ret['body']; if (trim($ret['body']) == '') $ret['body'] = email_get_part($mbox,$uid,$struc,0, 'plain'); @@ -107,6 +110,17 @@ function email_get_msg($mbox,$uid) { else $ret['body'] = $text; } + + $ret['body'] = removegpg($ret['body']); + $msg = removesig($ret['body']); + $ret['body'] = $msg['body']; + $ret['body'] = convertquote($ret['body'], $reply); + + if (trim($html) != '') + $ret['body'] = removelinebreak($ret['body']); + + $ret['body'] = unifyattributionline($ret['body']); + return $ret; } @@ -236,7 +250,7 @@ function email_header_encode($in_str, $charset) { // remove trailing spacer and // add start and end delimiters - $spacer = preg_quote($spacer); + $spacer = preg_quote($spacer,'/'); $out_str = preg_replace("/" . $spacer . "$/", "", $out_str); $out_str = $start . $out_str . $end; } diff --git a/include/enotify.php b/include/enotify.php index a505f1f04..8385bdec5 100755..100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -5,6 +5,12 @@ function notification($params) { logger('notification: entry', LOGGER_DEBUG); $a = get_app(); + + // from here on everything is in the recipients language + + push_lang($params['language']); + + $banner = t('Friendica Notification'); $product = FRIENDICA_PLATFORM; $siteurl = z_path(); @@ -153,9 +159,33 @@ function notification($params) { } - // from here on everything is in the recipients language + if($params['type'] == NOTIFY_SYSTEM) { + + } + + $h = array( + 'params' => $params, + 'subject' => $subject, + 'preamble' => $preamble, + 'epreamble' => $epreamble, + 'body' => $body, + 'sitelink' => $sitelink, + 'tsitelink' => $tsitelink, + 'hsitelink' => $hsitelink, + 'itemlink' => $itemlink + ); + + call_hooks('enotify',$h); + + $subject = $h['subject']; + $preamble = $h['preamble']; + $epreamble = $h['epreamble']; + $body = $h['body']; + $sitelink = $h['sitelink']; + $tsitelink = $h['tsitelink']; + $hsitelink = $h['hsitelink']; + $itemlink = $h['itemlink']; - push_lang($params['language']); require_once('include/html2bbcode.php'); @@ -207,8 +237,10 @@ function notification($params) { ); if($r) $notify_id = $r[0]['id']; - else + else { + pop_lang(); return; + } $itemlink = $a->get_baseurl() . '/notify/view/' . $notify_id; $msg = replace_macros($epreamble,array('$itemlink' => $itemlink)); @@ -219,11 +251,10 @@ function notification($params) { ); - // send email notification if notification preferences permit require_once('bbcode.php'); - if(intval($params['notify_flags']) & intval($params['type'])) { + if((intval($params['notify_flags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) { logger('notification: sending notification email'); diff --git a/include/event.php b/include/event.php index 4a9a9a004..29202badd 100755..100644 --- a/include/event.php +++ b/include/event.php @@ -163,7 +163,7 @@ function bbtoevent($s) { if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match)) $ev['adjust'] = $match[1]; $match = ''; - $ev['nofinish'] = (($ev['start'] && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); + $ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); return $ev; } diff --git a/include/expire.php b/include/expire.php index 5fa0ec758..5fa0ec758 100755..100644 --- a/include/expire.php +++ b/include/expire.php diff --git a/include/fcontact.php b/include/fcontact.php index 8821a985f..8821a985f 100755..100644 --- a/include/fcontact.php +++ b/include/fcontact.php diff --git a/include/group.php b/include/group.php index 4a35912e5..4a35912e5 100755..100644 --- a/include/group.php +++ b/include/group.php diff --git a/include/html2bbcode.php b/include/html2bbcode.php index 442e38691..69ccf41b7 100755..100644 --- a/include/html2bbcode.php +++ b/include/html2bbcode.php @@ -142,14 +142,14 @@ function html2bbcode($message) node2bbcode($doc, 'span', array('style'=>'font-style: italic;'), '[i]', '[/i]'); node2bbcode($doc, 'span', array('style'=>'font-weight: bold;'), '[b]', '[/b]'); - node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[font=$1][size=$2][color=$3]', '[/color][/size][/font]'); + /*node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[font=$1][size=$2][color=$3]', '[/color][/size][/font]'); node2bbcode($doc, 'font', array('size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[size=$1][color=$2]', '[/color][/size]'); node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(.+)/'), '[font=$1][size=$2]', '[/size][/font]'); node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'color'=>'/(.+)/'), '[font=$1][color=$3]', '[/color][/font]'); node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/'), '[font=$1]', '[/font]'); node2bbcode($doc, 'font', array('size'=>'/(\d+)/'), '[size=$1]', '[/size]'); node2bbcode($doc, 'font', array('color'=>'/(.+)/'), '[color=$1]', '[/color]'); - +*/ // Untested //node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*font-family:\s*(.+?)[,;].*color:\s*(.+?)[,;].*/'), '[size=$1][font=$2][color=$3]', '[/color][/font][/size]'); //node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(\d+)[,;].*/'), '[size=$1]', '[/size]'); @@ -191,13 +191,13 @@ function html2bbcode($message) node2bbcode($doc, 'hr', array(), "[hr]", ""); - //node2bbcode($doc, 'table', array(), "", ""); - //node2bbcode($doc, 'tr', array(), "\n", ""); - //node2bbcode($doc, 'td', array(), "\t", ""); - node2bbcode($doc, 'table', array(), "[table]", "[/table]"); - node2bbcode($doc, 'th', array(), "[th]", "[/th]"); - node2bbcode($doc, 'tr', array(), "[tr]", "[/tr]"); - node2bbcode($doc, 'td', array(), "[td]", "[/td]"); + node2bbcode($doc, 'table', array(), "", ""); + node2bbcode($doc, 'tr', array(), "\n", ""); + node2bbcode($doc, 'td', array(), "\t", ""); + //node2bbcode($doc, 'table', array(), "[table]", "[/table]"); + //node2bbcode($doc, 'th', array(), "[th]", "[/th]"); + //node2bbcode($doc, 'tr', array(), "[tr]", "[/tr]"); + //node2bbcode($doc, 'td', array(), "[td]", "[/td]"); node2bbcode($doc, 'h1', array(), "\n\n[size=xx-large][b]", "[/b][/size]\n"); node2bbcode($doc, 'h2', array(), "\n\n[size=x-large][b]", "[/b][/size]\n"); @@ -216,7 +216,7 @@ function html2bbcode($message) node2bbcode($doc, 'audio', array('src'=>'/(.+)/'), '[audio]$1', '[/audio]'); node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), '[iframe]$1', '[/iframe]'); - node2bbcode($doc, 'code', array(), '[code]$1', '[/code]'); + node2bbcode($doc, 'code', array(), '[code]', '[/code]'); $message = $doc->saveHTML(); diff --git a/include/html2plain.php b/include/html2plain.php index 2a4cf6639..21261327d 100644 --- a/include/html2plain.php +++ b/include/html2plain.php @@ -1,9 +1,15 @@ <?php require_once "html2bbcode.php"; -function breaklines($line, $level) +function breaklines($line, $level, $wraplength = 75) { - $wraplen = 75-$level; + + if ($wraplength == 0) + $wraplength = 2000000; + + // return($line); + + $wraplen = $wraplength-$level; $newlines = array(); @@ -37,7 +43,7 @@ function breaklines($line, $level) return(implode($newlines, "\n")); } -function quotelevel($message) +function quotelevel($message, $wraplength = 75) { $lines = explode("\n", $message); @@ -65,12 +71,34 @@ function quotelevel($message) } if (!$startquote or ($line != '')) - $newlines[] = breaklines($line, $currlevel); + $newlines[] = breaklines($line, $currlevel, $wraplength); } return(implode($newlines, "\n")); } -function html2plain($html) +function collecturls($message) { + $pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is'; + preg_match_all($pattern, $message, $result, PREG_SET_ORDER); + + $urls = array(); + foreach ($result as $treffer) { + // A list of some links that should be ignored + $list = array("/user/", "/tag/", "/group/", "/profile/", "/search?search=", "mailto:", "/u/", "/node/", + "//facebook.com/profile.php?id=", "//plus.google.com/"); + foreach ($list as $listitem) + if (strpos($treffer[1], $listitem) !== false) + $ignore = true; + + if ((strpos($treffer[1], "//plus.google.com/") !== false) and (strpos($treffer[1], "/posts") !== false)) + $ignore = false; + + if (!$ignore) + $urls[$treffer[1]] = $treffer[1]; + } + return($urls); +} + +function html2plain($html, $wraplength = 75, $compact = false) { global $lang; @@ -93,22 +121,16 @@ function html2plain($html) $message = str_replace(array("\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"), array("<", ">", "<br>", " ", ""), $message); $message = preg_replace('= [\s]*=i', " ", $message); - // nach <a href="...">...</a> suchen, die ... miteinander vergleichen und bei Gleichheit durch ein einzelnes ... ersetzen. - $pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is'; - preg_match_all($pattern, $message, $result, PREG_SET_ORDER); + // Collecting all links + $urls = collecturls($message); - foreach ($result as $treffer) { - if ($treffer[1] == $treffer[2]) { - $search = '<a href="'.$treffer[1].'" target="_blank">'.$treffer[1].'</a>'; - $message = str_replace($search, $treffer[1], $message); - } - } @$doc->loadHTML($message); node2bbcode($doc, 'html', array(), '', ''); node2bbcode($doc, 'body', array(), '', ''); // MyBB-Auszeichnungen + /* node2bbcode($doc, 'span', array('style'=>'text-decoration: underline;'), '_', '_'); node2bbcode($doc, 'span', array('style'=>'font-style: italic;'), '/', '/'); node2bbcode($doc, 'span', array('style'=>'font-weight: bold;'), '*', '*'); @@ -117,8 +139,12 @@ function html2plain($html) node2bbcode($doc, 'b', array(), '*', '*'); node2bbcode($doc, 'i', array(), '/', '/'); node2bbcode($doc, 'u', array(), '_', '_'); + */ - node2bbcode($doc, 'blockquote', array(), '[quote]', "[/quote]\n"); + if ($compact) + node2bbcode($doc, 'blockquote', array(), "»", "«"); + else + node2bbcode($doc, 'blockquote', array(), '[quote]', "[/quote]\n"); node2bbcode($doc, 'br', array(), "\n", ''); @@ -131,7 +157,7 @@ function html2plain($html) //node2bbcode($doc, 'ol', array(), "\n[list=1]", "[/list]\n"); node2bbcode($doc, 'li', array(), "\n* ", "\n"); - node2bbcode($doc, 'hr', array(), str_repeat("-", 70), ""); + node2bbcode($doc, 'hr', array(), "\n".str_repeat("-", 70)."\n", ""); node2bbcode($doc, 'tr', array(), "\n", ""); node2bbcode($doc, 'td', array(), "\t", ""); @@ -143,16 +169,25 @@ function html2plain($html) node2bbcode($doc, 'h5', array(), "\n\n*", "*\n"); node2bbcode($doc, 'h6', array(), "\n\n*", "*\n"); - node2bbcode($doc, 'a', array('href'=>'/(.+)/'), ' $1', '', true); - node2bbcode($doc, 'img', array('alt'=>'/(.+)/'), '$1', ''); - node2bbcode($doc, 'img', array('title'=>'/(.+)/'), '$1', ''); - node2bbcode($doc, 'img', array(), '', ''); - node2bbcode($doc, 'img', array('src'=>'/(.+)/'), '[img]$1', '[/img]'); + // Problem: there is no reliable way to detect if it is a link to a tag or profile + //node2bbcode($doc, 'a', array('href'=>'/(.+)/'), ' $1 ', '', true); + node2bbcode($doc, 'a', array('href'=>'/(.+)/', 'rel'=>'oembed'), ' $1 ', '', true); + //node2bbcode($doc, 'img', array('alt'=>'/(.+)/'), '$1', ''); + //node2bbcode($doc, 'img', array('title'=>'/(.+)/'), '$1', ''); + //node2bbcode($doc, 'img', array(), '', ''); + if (!$compact) + node2bbcode($doc, 'img', array('src'=>'/(.+)/'), '[img]$1', '[/img]'); + else + node2bbcode($doc, 'img', array('src'=>'/(.+)/'), '', ''); + + node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), ' $1 ', '', true); $message = $doc->saveHTML(); - $message = str_replace("[img]", "", $message); - $message = str_replace("[/img]", "", $message); + if (!$compact) { + $message = str_replace("[img]", "", $message); + $message = str_replace("[/img]", "", $message); + } // was ersetze ich da? // Irgendein stoerrisches UTF-Zeug @@ -168,12 +203,20 @@ function html2plain($html) $message = html_entity_decode($message, ENT_QUOTES, 'UTF-8'); + if (!$compact) { + $counter = 1; + foreach ($urls as $id=>$url) + if (strpos($message, $url) == false) + $message .= "\n".$url." "; + //$message .= "\n[".($counter++)."] ".$url; + } + do { $oldmessage = $message; $message = str_replace("\n\n\n", "\n\n", $message); } while ($oldmessage != $message); - $message = quotelevel(trim($message)); + $message = quotelevel(trim($message), $wraplength); return(trim($message)); } diff --git a/include/items.php b/include/items.php index a1254e165..ee6960534 100755..100644 --- a/include/items.php +++ b/include/items.php @@ -7,14 +7,11 @@ require_once('include/crypto.php'); function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) { - // default permissions - anonymous user - - if(! strlen($owner_nick)) - killme(); + $sitefeed = ((strlen($owner_nick)) ? false : true); // not yet implemented, need to rewrite huge chunks of following logic $public_feed = (($dfrn_id) ? false : true); - $starred = false; - $converse = false; + $starred = false; // not yet implemented, possible security issues + $converse = false; if($public_feed && $a->argc > 2) { for($x = 2; $x < $a->argc; $x++) { @@ -25,10 +22,11 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) } } + // default permissions - anonymous user $sql_extra = " AND `allow_cid` = '' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = '' "; - $r = q("SELECT `contact`.*, `user`.`uid` AS `user_uid`, `user`.`nickname`, `user`.`timezone` + $r = q("SELECT `contact`.*, `user`.`uid` AS `user_uid`, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid` WHERE `contact`.`self` = 1 AND `user`.`nickname` = '%s' LIMIT 1", dbesc($owner_nick) @@ -156,7 +154,8 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) , '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) , '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) , - '$birthday' => ((strlen($birthday)) ? '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>' : '') + '$birthday' => ((strlen($birthday)) ? '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>' : ''), + '$community' => (($owner['page-flags'] == PAGE_COMMUNITY) ? '<dfrn:community>1</dfrn:community>' : '') )); call_hooks('atom_feed', $atom); @@ -417,7 +416,7 @@ function get_atom_elements($feed,$item) { // the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining // html. - if((strpos($res['body'],'<') !== false) || (strpos($res['body'],'>') !== false)) { + if((strpos($res['body'],'<') !== false) && (strpos($res['body'],'>') !== false)) { $res['body'] = reltoabs($res['body'],$base_url); @@ -430,14 +429,22 @@ function get_atom_elements($feed,$item) { // we shouldn't need a whitelist, because the bbcode converter // will strip out any unsupported tags. - // $config->set('HTML.Allowed', 'p,b,a[href],i'); $purifier = new HTMLPurifier($config); $res['body'] = $purifier->purify($res['body']); - $res['body'] = html2bbcode($res['body']); + $res['body'] = @html2bbcode($res['body']); + } + elseif(! $have_real_body) { + + // it's not one of our messages and it has no tags + // so it's probably just text. We'll escape it just to be safe. + + $res['body'] = escape_tags($res['body']); } + // this tag is obsolete but we keep it for really old sites + $allow = $item->get_item_tags(NAMESPACE_DFRN,'comment-allow'); if($allow && $allow[0]['data'] == 1) $res['last-child'] = 1; @@ -682,7 +689,7 @@ function item_store($arr,$force_parent = false) { unset($arr['dsprsig']); } - if($arr['gravity']) + if(x($arr, 'gravity')) $arr['gravity'] = intval($arr['gravity']); elseif($arr['parent-uri'] === $arr['uri']) $arr['gravity'] = 0; @@ -742,6 +749,7 @@ function item_store($arr,$force_parent = false) { if($arr['parent-uri'] === $arr['uri']) { $parent_id = 0; + $parent_deleted = 0; $allow_cid = $arr['allow_cid']; $allow_gid = $arr['allow_gid']; $deny_cid = $arr['deny_cid']; @@ -800,6 +808,8 @@ function item_store($arr,$force_parent = false) { logger('item_store: item parent was not found - ignoring item'); return 0; } + + $parent_deleted = 0; } } @@ -1043,6 +1053,22 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { if(! $rino_enable) $rino = 0; + $ssl_val = intval(get_config('system','ssl_policy')); + $ssl_policy = ''; + + switch($ssl_val){ + case SSL_POLICY_FULL: + $ssl_policy = 'full'; + break; + case SSL_POLICY_SELFSIGN: + $ssl_policy = 'self'; + break; + case SSL_POLICY_NONE: + default: + $ssl_policy = 'none'; + break; + } + $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino=1' : ''); logger('dfrn_deliver: ' . $url); @@ -1072,11 +1098,23 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $postvars = array(); $sent_dfrn_id = hex2bin((string) $res->dfrn_id); $challenge = hex2bin((string) $res->challenge); + $perm = (($res->perm) ? $res->perm : null); $dfrn_version = (float) (($res->dfrn_version) ? $res->dfrn_version : 2.0); $rino_allowed = ((intval($res->rino) === 1) ? 1 : 0); + $page = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0); $final_dfrn_id = ''; + if($perm) { + if((($perm == 'rw') && (! intval($contact['writable']))) + || (($perm == 'r') && (intval($contact['writable'])))) { + q("update contact set writable = %d where id = %d limit 1", + intval(($perm == 'rw') ? 1 : 0), + intval($contact['id']) + ); + $contact['writable'] = (string) 1 - intval($contact['writable']); + } + } if(($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) @@ -1115,6 +1153,11 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $postvars['perm'] = 'r'; } + $postvars['ssl_policy'] = $ssl_policy; + + if($page) + $postvars['page'] = '1'; + if($rino && $rino_allowed && (! $dissolve)) { $key = substr(random_string(),0,16); $data = bin2hex(aes_encrypt($postvars['data'],$key)); @@ -1379,6 +1422,19 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } + $community_page = 0; + $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'community'); + if($rawtags) { + $community_page = intval($rawtags[0]['data']); + } + if(is_array($contact) && intval($contact['forum']) != $community_page) { + q("update contact set forum = %d where id = %d limit 1", + intval($community_page), + intval($contact['id']) + ); + $contact['forum'] = (string) $community_page; + } + // process any deleted entries @@ -1398,7 +1454,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } if($deleted && is_array($contact)) { $r = q("SELECT `item`.*, `contact`.`self` FROM `item` left join `contact` on `item`.`contact-id` = `contact`.`id` - WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d LIMIT 1", + WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), intval($importer['uid']), intval($contact['id']) @@ -1543,9 +1599,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['uid']) @@ -1595,6 +1652,14 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; + // only one like or dislike per person + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1", + intval($datarray['uid']), + intval($datarray['contact-id']), + dbesc($datarray['verb']) + ); + if($r && count($r)) + continue; } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { @@ -1680,9 +1745,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['uid']) @@ -1747,6 +1813,18 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; + + if(! link_compare($datarray['owner-link'],$contact['url'])) { + // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, + // but otherwise there's a possible data mixup on the sender's system. + // the tgroup delivery code called from item_store will correct it if it's a forum, + // but we're going to unconditionally correct it here so that the post will always be owned by our contact. + logger('consume_feed: Correcting item owner.', LOGGER_DEBUG); + $datarray['owner-name'] = $contact['name']; + $datarray['owner-link'] = $contact['url']; + $datarray['owner-avatar'] = $contact['thumb']; + } + $r = item_store($datarray); continue; @@ -1837,6 +1915,14 @@ function local_delivery($importer,$data) { ); if(count($r)) { $fid = $r[0]['id']; + + // OK, we do. Do we already have an introduction for this person ? + $r = q("select id from intro where uid = %d and fid = %d limit 1", + intval($fsugg['uid']), + intval($fid) + ); + if(count($r)) + return 0; } if(! $fid) $r = q("INSERT INTO `fcontact` ( `name`,`url`,`photo`,`request` ) VALUES ( '%s', '%s', '%s', '%s' ) ", @@ -1857,6 +1943,7 @@ function local_delivery($importer,$data) { else return 0; + $hash = random_string(); $r = q("INSERT INTO `intro` ( `uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked` ) @@ -1942,6 +2029,19 @@ function local_delivery($importer,$data) { // NOTREACHED } + + $community_page = 0; + $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'community'); + if($rawtags) { + $community_page = intval($rawtags[0]['data']); + } + if(intval($importer['forum']) != $community_page) { + q("update contact set forum = %d where id = %d limit 1", + intval($community_page), + intval($importer['id']) + ); + $importer['forum'] = (string) $community_page; + } logger('local_delivery: feed item count = ' . $feed->get_item_quantity()); @@ -1964,7 +2064,7 @@ function local_delivery($importer,$data) { if($deleted) { $r = q("SELECT `item`.*, `contact`.`self` FROM `item` left join contact on `item`.`contact-id` = `contact`.`id` - WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d LIMIT 1", + WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), intval($importer['importer_uid']), intval($importer['id']) @@ -1981,6 +2081,7 @@ function local_delivery($importer,$data) { if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTVITY_OBJ_TAGTERM)) { $xo = parse_xml_string($item['object'],false); $xt = parse_xml_string($item['target'],false); + if($xt->type === ACTIVITY_OBJ_NOTE) { $i = q("select * from `item` where uri = '%s' and uid = %d limit 1", dbesc($xt->id), @@ -2136,6 +2237,14 @@ function local_delivery($importer,$data) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; $datarray['last-child'] = 0; + // only one like or dislike per person + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1", + intval($datarray['uid']), + intval($datarray['contact-id']), + dbesc($datarray['verb']) + ); + if($r && count($r)) + continue; } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { @@ -2251,9 +2360,10 @@ function local_delivery($importer,$data) { if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['importer_uid']) @@ -2285,6 +2395,15 @@ function local_delivery($importer,$data) { if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; + // only one like or dislike per person + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1", + intval($datarray['uid']), + intval($datarray['contact-id']), + dbesc($datarray['verb']) + ); + if($r && count($r)) + continue; + } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { @@ -2407,9 +2526,10 @@ function local_delivery($importer,$data) { if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['importer_uid']) @@ -2439,6 +2559,18 @@ function local_delivery($importer,$data) { $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; + + if(! link_compare($datarray['owner-link'],$contact['url'])) { + // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, + // but otherwise there's a possible data mixup on the sender's system. + // the tgroup delivery code called from item_store will correct it if it's a forum, + // but we're going to unconditionally correct it here so that the post will always be owned by our contact. + logger('local_delivery: Correcting item owner.', LOGGER_DEBUG); + $datarray['owner-name'] = $importer['senderName']; + $datarray['owner-link'] = $importer['url']; + $datarray['owner-avatar'] = $importer['thumb']; + } + $r = item_store($datarray); continue; } @@ -2823,6 +2955,11 @@ function item_expire($uid,$days) { foreach($r as $item) { + // don't expire filed items + + if(strpos($item['file'],'[') !== false) + continue; + // Only expire posts, not photos and photo comments if($expire_photos==0 && strlen($item['resource-id'])) diff --git a/include/message.php b/include/message.php index 7ad80ae9c..377d7c715 100755..100644 --- a/include/message.php +++ b/include/message.php @@ -1,4 +1,5 @@ <?php + // send a private message @@ -155,3 +156,87 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){ } } + + + + + +function send_wallmessage($recipient='', $body='', $subject='', $replyto=''){ + + $a = get_app(); + + if(! $recipient) return -1; + + if(! strlen($subject)) + $subject = t('[no subject]'); + + $hash = random_string(); + $uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $hash ; + + $convid = 0; + $reply = false; + + require_once('include/Scrape.php'); + + $me = probe_url($replyto); + + if(! $me['name']) + return -2; + + $conv_guid = get_guid(); + + $recip_handle = $recipient['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + + $sender_nick = basename($replyto); + $sender_host = substr($replyto,strpos($replyto,'://')+3); + $sender_host = substr($sender_host,0,strpos($sender_host,'/')); + $sender_handle = $sender_nick . '@' . $sender_host; + + $handles = $recip_handle . ';' . $sender_handle; + + $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ", + intval(local_user()), + dbesc($conv_guid), + dbesc($sender_handle), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($subject), + dbesc($handles) + ); + + $r = q("select * from conv where guid = '%s' and uid = %d limit 1", + dbesc($conv_guid), + intval($recipient['uid']) + ); + if(count($r)) + $convid = $r[0]['id']; + + if(! $convid) { + logger('send message: conversation not found.'); + return -4; + } + + $r = q("INSERT INTO `mail` ( `uid`, `guid`, `convid`, `from-name`, `from-photo`, `from-url`, + `contact-id`, `title`, `body`, `seen`, `reply`, `replied`, `uri`, `parent-uri`, `created`, `unknown`) + VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, %d, '%s', '%s', '%s', %d )", + intval($recipient['uid']), + dbesc(get_guid()), + intval($convid), + dbesc($me['name']), + dbesc($me['photo']), + dbesc($me['url']), + 0, + dbesc($subject), + dbesc($body), + 0, + 0, + 0, + dbesc($uri), + dbesc($replyto), + datetime_convert(), + 1 + ); + + return 0; + +} diff --git a/include/msgclean.php b/include/msgclean.php new file mode 100644 index 000000000..eabb47788 --- /dev/null +++ b/include/msgclean.php @@ -0,0 +1,225 @@ +<?php + +function savereplace($pattern, $replace, $text) +{ + $save = $text; + + $text = preg_replace($pattern, $replace, $text); + + if ($text == '') + $text = $save; + return($text); +} + +function unifyattributionline($message) +{ + $quotestr = array('quote', 'spoiler'); + foreach ($quotestr as $quote) { + + $message = savereplace('/----- Original Message -----\s.*?From: "([^<"].*?)" <(.*?)>\s.*?To: (.*?)\s*?Cc: (.*?)\s*?Sent: (.*?)\s.*?Subject: ([^\n].*)\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/----- Original Message -----\s.*?From: "([^<"].*?)" <(.*?)>\s.*?To: (.*?)\s*?Sent: (.*?)\s.*?Subject: ([^\n].*)\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/-------- Original-Nachricht --------\s*\['.$quote.'\]\nDatum: (.*?)\nVon: (.*?) <(.*?)>\nAn: (.*?)\nBetreff: (.*?)\n/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/-------- Original-Nachricht --------\s*\['.$quote.'\]\sDatum: (.*?)\s.*Von: "([^<"].*?)" <(.*?)>\s.*An: (.*?)\n.*/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/-------- Original-Nachricht --------\s*\['.$quote.'\]\nDatum: (.*?)\nVon: (.*?)\nAn: (.*?)\nBetreff: (.*?)\n/i', "[".$quote."='$2']\n", $message); + + $message = savereplace('/-----Urspr.*?ngliche Nachricht-----\sVon: "([^<"].*?)" <(.*?)>\s.*Gesendet: (.*?)\s.*An: (.*?)\s.*Betreff: ([^\n].*?).*:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/-----Urspr.*?ngliche Nachricht-----\sVon: "([^<"].*?)" <(.*?)>\s.*Gesendet: (.*?)\s.*An: (.*?)\s.*Betreff: ([^\n].*?)\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/Am (.*?), schrieb (.*?):\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + + $message = savereplace('/Am .*?, \d+ .*? \d+ \d+:\d+:\d+ \+\d+\sschrieb\s(.*?)\s<(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/Am (.*?) schrieb (.*?) <(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/Am (.*?) schrieb <(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/Am (.*?) schrieb (.*?):\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/Am (.*?) schrieb (.*?)\n(.*?):\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + + $message = savereplace('/(\d+)\/(\d+)\/(\d+) ([^<"].*?) <(.*?)>\s*\['.$quote.'\]/i', "[".$quote."='$4']\n", $message); + + $message = savereplace('/On .*?, \d+ .*? \d+ \d+:\d+:\d+ \+\d+\s(.*?)\s<(.*?)>\swrote:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/On (.*?) at (.*?), (.*?)\s<(.*?)>\swrote:\s*\['.$quote.'\]/i', "[".$quote."='$3']\n", $message); + $message = savereplace('/On (.*?)\n([^<].*?)\s<(.*?)>\swrote:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/On (.*?), (.*?), (.*?)\s<(.*?)>\swrote:\s*\['.$quote.'\]/i', "[".$quote."='$3']\n", $message); + $message = savereplace('/On ([^,].*?), (.*?)\swrote:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/On (.*?), (.*?)\swrote\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + + // Der loescht manchmal den Body - was eigentlich unmoeglich ist + $message = savereplace('/On (.*?),(.*?),(.*?),(.*?), (.*?) wrote:\s*\['.$quote.'\]/i', "[".$quote."='$5']\n", $message); + + $message = savereplace('/Zitat von ([^<].*?) <(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/Quoting ([^<].*?) <(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/From: "([^<"].*?)" <(.*?)>\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/From: <(.*?)>\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/Du \(([^)].*?)\) schreibst:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/--- (.*?) <.*?> schrieb am (.*?):\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/--- (.*?) schrieb am (.*?):\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/\* (.*?) <(.*?)> hat geschrieben:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/(.*?) <(.*?)> schrieb (.*?)\):\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) <(.*?)> schrieb am (.*?) um (.*):\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) schrieb am (.*?) um (.*):\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) \((.*?)\) schrieb:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/(.*?) schrieb:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/(.*?) <(.*?)> writes:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) \((.*?)\) writes:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + $message = savereplace('/(.*?) writes:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/\* (.*?) wrote:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) wrote \(.*?\):\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) wrote:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/([^<].*?) <.*?> hat am (.*?)\sum\s(.*)\sgeschrieben:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + + $message = savereplace('/(\d+)\/(\d+)\/(\d+) ([^<"].*?) <(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$4']\n", $message); + $message = savereplace('/(\d+)\/(\d+)\/(\d+) (.*?) <(.*?)>\s*\['.$quote.'\]/i', "[".$quote."='$4']\n", $message); + $message = savereplace('/(\d+)\/(\d+)\/(\d+) <(.*?)>:\s*\['.$quote.'\]/i', "[".$quote."='$4']\n", $message); + $message = savereplace('/(\d+)\/(\d+)\/(\d+) <(.*?)>\s*\['.$quote.'\]/i', "[".$quote."='$4']\n", $message); + + $message = savereplace('/(.*?) <(.*?)> schrubselte:\s*\['.$quote.'\]/i', "[".$quote."='$1']\n", $message); + $message = savereplace('/(.*?) \((.*?)\) schrubselte:\s*\['.$quote.'\]/i', "[".$quote."='$2']\n", $message); + + } + return($message); +} + +function removegpg($message) +{ + + $pattern = '/(.*)\s*-----BEGIN PGP SIGNED MESSAGE-----\s*[\r\n].*Hash:.*?[\r\n](.*)'. + '[\r\n]\s*-----BEGIN PGP SIGNATURE-----\s*[\r\n].*'. + '[\r\n]\s*-----END PGP SIGNATURE-----(.*)/is'; + + preg_match($pattern, $message, $result); + + $cleaned = trim($result[1].$result[2].$result[3]); + + $cleaned = str_replace(array("\n- --\n", "\n- -"), array("\n-- \n", "\n-"), $cleaned); + + + if ($cleaned == '') + $cleaned = $message; + + return($cleaned); +} + +function removesig($message) +{ + $sigpos = strrpos($message, "\n-- \n"); + $quotepos = strrpos($message, "[/quote]"); + + if ($sigpos == 0) { + // Speziell fuer web.de, die das als Trenner verwenden + $message = str_replace("\n___________________________________________________________\n", "\n-- \n", $message); + $sigpos = strrpos($message, "\n-- \n"); + $quotepos = strrpos($message, "[/quote]"); + } + + // Sollte sich der Signaturtrenner innerhalb eines Quotes befinden + // wird keine Signaturtrennung ausgefuehrt + if (($sigpos < $quotepos) and ($sigpos != 0)) + return(array('body' => $message, 'sig' => '')); + + // To-Do: Regexp umstellen, so dass auf 1 oder kein Leerzeichen + // geprueft wird + //$message = str_replace("\n--\n", "\n-- \n", $message); + + $pattern = '/(.*)[\r\n]-- [\r\n](.*)/is'; + + preg_match($pattern, $message, $result); + + if (($result[1] != '') and ($result[2] != '')) { + $cleaned = trim($result[1])."\n"; + $sig = trim($result[2]); + // '[hr][size=x-small][color=darkblue]'.trim($result[2]).'[/color][/size]'; + } else { + $cleaned = $message; + $sig = ''; + } + + return(array('body' => $cleaned, 'sig' => $sig)); +} + +function removelinebreak($message) +{ + $arrbody = explode("\n", trim($message)); + + $lines = array(); + $lineno = 0; + + foreach($arrbody as $i => $line) { + $currquotelevel = 0; + $currline = $line; + while ((strlen($currline)>0) and ((substr($currline, 0, 1) == '>') + or (substr($currline, 0, 1) == ' '))) { + if (substr($currline, 0, 1) == '>') + $currquotelevel++; + + $currline = ltrim(substr($currline, 1)); + } + + $quotelevel = 0; + $nextline = trim($arrbody[$i+1]); + while ((strlen($nextline)>0) and ((substr($nextline, 0, 1) == '>') + or (substr($nextline, 0, 1) == ' '))) { + if (substr($nextline, 0, 1) == '>') + $quotelevel++; + + $nextline = ltrim(substr($nextline, 1)); + } + + $len = strlen($line); + $firstword = strpos($nextline.' ', ' '); + + $specialchars = ((substr(trim($nextline), 0, 1) == '-') or + (substr(trim($nextline), 0, 1) == '=') or + (substr(trim($nextline), 0, 1) == '*') or + (substr(trim($nextline), 0, 1) == '·') or + (substr(trim($nextline), 0, 4) == '[url') or + (substr(trim($nextline), 0, 5) == '[size') or + (substr(trim($nextline), 0, 7) == 'http://') or + (substr(trim($nextline), 0, 8) == 'https://')); + + if (!$specialchars) + $specialchars = ((substr(rtrim($line), -1) == '-') or + (substr(rtrim($line), -1) == '=') or + (substr(rtrim($line), -1) == '*') or + (substr(rtrim($line), -1) == '·') or + (substr(rtrim($line), -6) == '[/url]') or + (substr(rtrim($line), -7) == '[/size]')); + + //if ($specialchars) + // echo ("Special\n"); + + if ($lines[$lineno] != '') { + if (substr($lines[$lineno], -1) != ' ') + $lines[$lineno] .= ' '; + + while ((strlen($line)>0) and ((substr($line, 0, 1) == '>') + or (substr($line, 0, 1) == ' '))) { + + $line = ltrim(substr($line, 1)); + } + + } + //else + // $lines[$lineno] = $quotelevel.'-'.$len.'-'.$firstword.'-'; + + $lines[$lineno] .= $line; + //if ((($len + $firstword < 68) and (substr($line, -1, 1) != ' ')) + // or ($quotelevel != $currquotelevel) or $specialchars) + if (((substr($line, -1, 1) != ' ')) + or ($quotelevel != $currquotelevel)) + $lineno++; + } + return(implode("\n", $lines)); + +} +?> diff --git a/include/nav.php b/include/nav.php index 511ca07fc..2c9c643a9 100755..100644 --- a/include/nav.php +++ b/include/nav.php @@ -8,6 +8,8 @@ function nav(&$a) { * */ + $ssl_state = ((local_user()) ? true : false); + if(!(x($a->page,'nav'))) $a->page['nav'] = ''; @@ -27,7 +29,7 @@ function nav(&$a) { $myident = ((is_array($a->user) && isset($a->user['nickname'])) ? $a->user['nickname'] . '@' : ''); - $sitelocation = $myident . substr($a->get_baseurl(),strpos($a->get_baseurl(),'//') + 2 ); + $sitelocation = $myident . substr($a->get_baseurl($ssl_state),strpos($a->get_baseurl($ssl_state),'//') + 2 ); // nav links: array of array('href', 'text', 'extra css classes', 'title') @@ -53,7 +55,7 @@ function nav(&$a) { // user info $r = q("SELECT micro FROM contact WHERE uid=%d AND self=1", intval($a->user['uid'])); $userinfo = array( - 'icon' => (count($r) ? $r[0]['micro']: $a->get_baseurl()."/images/default-profile-mm.jpg"), + 'icon' => (count($r) ? $r[0]['micro']: $a->get_baseurl($ssl_state)."/images/person-48.jpg"), 'name' => $a->user['username'], ); @@ -67,7 +69,9 @@ function nav(&$a) { * "Home" should also take you home from an authenticated remote profile connection */ - $homelink = ((x($_SESSION,'visitor_home')) ? $_SESSION['visitor_home'] : ''); + $homelink = get_my_url(); + if(! $homelink) + $homelink = ((x($_SESSION,'visitor_home')) ? $_SESSION['visitor_home'] : ''); if(($a->module != 'home') && (! (local_user()))) $nav['home'] = array($homelink, t('Home'), "", t('Home Page')); @@ -76,7 +80,7 @@ function nav(&$a) { if(($a->config['register_policy'] == REGISTER_OPEN) && (! local_user()) && (! remote_user())) $nav['register'] = array('register',t('Register'), "", t('Create an account')); - $help_url = $a->get_baseurl() . '/help'; + $help_url = $a->get_baseurl($ssl_state) . '/help'; if(! get_config('system','hide_help')) $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation')); @@ -122,6 +126,9 @@ function nav(&$a) { } $nav['messages'] = array('message', t('Messages'), "", t('Private mail')); + $nav['messages']['inbox'] = array('message', t('Inbox'), "", t('Inbox')); + $nav['messages']['outbox']= array('message/sent', t('Outbox'), "", t('Outbox')); + $nav['messages']['new'] = array('message/new', t('New Message'), "", t('New Message')); if(is_array($a->identities) && count($a->identities) > 1) { $nav['manage'] = array('manage', t('Manage'), "", t('Manage other pages')); diff --git a/include/network.php b/include/network.php index c72919dd8..38d0980d5 100755..100644 --- a/include/network.php +++ b/include/network.php @@ -303,7 +303,7 @@ function webfinger_dfrn($s,&$hcard) { if(! function_exists('webfinger')) { -function webfinger($s) { +function webfinger($s, $debug = false) { $host = ''; if(strstr($s,'@')) { $host = substr($s,strpos($s,'@') + 1); @@ -328,7 +328,7 @@ function webfinger($s) { }} if(! function_exists('lrdd')) { -function lrdd($uri) { +function lrdd($uri, $debug = false) { $a = get_app(); @@ -364,6 +364,9 @@ function lrdd($uri) { logger('lrdd: host_meta: ' . $xml, LOGGER_DATA); + if(! stristr($xml,'<xrd')) + return array(); + $h = parse_xml_string($xml); if(! $h) return array(); @@ -821,3 +824,48 @@ function scale_external_images($s,$include_link = true) { } return $s; } + + +function fix_contact_ssl_policy(&$contact,$new_policy) { + + $ssl_changed = false; + if((intval($new_policy) == SSL_POLICY_SELFSIGN || $new_policy === 'self') && strstr($contact['url'],'https:')) { + $ssl_changed = true; + $contact['url'] = str_replace('https:','http:',$contact['url']); + $contact['request'] = str_replace('https:','http:',$contact['request']); + $contact['notify'] = str_replace('https:','http:',$contact['notify']); + $contact['poll'] = str_replace('https:','http:',$contact['poll']); + $contact['confirm'] = str_replace('https:','http:',$contact['confirm']); + $contact['poco'] = str_replace('https:','http:',$contact['poco']); + } + + if((intval($new_policy) == SSL_POLICY_FULL || $new_policy === 'full') && strstr($contact['url'],'http:')) { + $ssl_changed = true; + $contact['url'] = str_replace('http:','https:',$contact['url']); + $contact['request'] = str_replace('http:','https:',$contact['request']); + $contact['notify'] = str_replace('http:','https:',$contact['notify']); + $contact['poll'] = str_replace('http:','https:',$contact['poll']); + $contact['confirm'] = str_replace('http:','https:',$contact['confirm']); + $contact['poco'] = str_replace('http:','https:',$contact['poco']); + } + + if($ssl_changed) { + q("update contact set + url = '%s', + request = '%s', + notify = '%s', + poll = '%s', + confirm = '%s', + poco = '%s' + where id = %d limit 1", + dbesc($contact['url']), + dbesc($contact['request']), + dbesc($contact['notify']), + dbesc($contact['poll']), + dbesc($contact['confirm']), + dbesc($contact['poco']), + intval($contact['id']) + ); + } +} + diff --git a/include/notifier.php b/include/notifier.php index 4765cca06..ca7c7b92e 100755..100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -201,7 +201,7 @@ function notifier_run($argv, $argc){ // by stringing togther an array of retractions and sending them onward. - $localhost = $a->get_hostname(); + $localhost = str_replace('www.','',$a->get_hostname()); if(strpos($localhost,':')) $localhost = substr($localhost,0,strpos($localhost,':')); @@ -337,7 +337,9 @@ function notifier_run($argv, $argc){ '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) , '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) , '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) , - '$birthday' => $birthday + '$birthday' => $birthday, + '$community' => (($owner['page-flags'] == PAGE_COMMUNITY) ? '<dfrn:community>1</dfrn:community>' : '') + )); if($mail) { @@ -535,6 +537,17 @@ function notifier_run($argv, $argc){ $x[0]['writable'] = 1; } + // if contact's ssl policy changed, which we just determined + // is on our own server, update our contact links + + $ssl_policy = get_config('system','ssl_policy'); + fix_contact_ssl_policy($x[0],$ssl_policy); + + // If we are setup as a soapbox we aren't accepting input from this person + + if($x[0]['page-flags'] == PAGE_SOAPBOX) + break; + require_once('library/simplepie/simplepie.inc'); logger('mod-delivery: local delivery'); local_delivery($x[0],$atom); @@ -648,38 +661,23 @@ function notifier_run($argv, $argc){ $headers .= 'Reply-to: ' . $reply_to . "\n"; // for testing purposes: Collect exported mails - $file = tempnam("/tmp/friendica/", "mail-out2-"); - file_put_contents($file, json_encode($it)); + //$file = tempnam("/tmp/friendica/", "mail-out2-"); + //file_put_contents($file, json_encode($it)); $headers .= 'Message-Id: <' . iri2msgid($it['uri']) . '>' . "\n"; if($it['uri'] !== $it['parent-uri']) { $headers .= 'References: <' . iri2msgid($it['parent-uri']) . '>' . "\n"; - if(! strlen($it['title'])) { + if(!strlen($it['title'])) { $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' LIMIT 1", - dbesc($it['parent-uri']) - ); - if(count($r)) { - $subtitle = $r[0]['title']; - if($subtitle) { - if(strncasecmp($subtitle,'RE:',3)) - $subject = $subtitle; - else - $subject = 'Re: ' . $subtitle; - } - } + dbesc($it['parent-uri'])); + + if(count($r) AND ($r[0]['title'] != '')) + $subject = $r[0]['title']; } + if(strncasecmp($subject,'RE:',3)) + $subject = 'Re: '.$subject; } - - /*$headers .= 'MIME-Version: 1.0' . "\n"; - //$headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; - $headers .= 'Content-Type: text/plain; charset=UTF-8' . "\n"; - $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; - $html = prepare_body($it); - //$message = '<html><body>' . $html . '</body></html>'; - $message = html2plain($html); - logger('notifier: email delivery to ' . $addr); - mail($addr, $subject, $message, $headers);*/ email_send($addr, $subject, $headers, $it); } break; diff --git a/include/oauth.php b/include/oauth.php index 2724dcf7c..2724dcf7c 100755..100644 --- a/include/oauth.php +++ b/include/oauth.php diff --git a/include/oembed.php b/include/oembed.php index 5c3c595f5..1f45d2814 100755..100644 --- a/include/oembed.php +++ b/include/oembed.php @@ -1,6 +1,6 @@ <?php function oembed_replacecb($matches){ - logger('oembedcb'); +// logger('oembedcb'); $embedurl=$matches[1]; $j = oembed_fetch_url($embedurl); $s = oembed_format_object($j); @@ -14,6 +14,9 @@ function oembed_fetch_url($embedurl){ $txt = Cache::get($embedurl); + // These media files should now be caught in bbcode.php + // left here as a fallback in case this is called from another source + $noexts = array("mp3","mp4","ogg","ogv","oga","ogm","webm"); $ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION); @@ -35,7 +38,8 @@ function oembed_fetch_url($embedurl){ $entries = $xpath->query("//link[@type='application/json+oembed']"); foreach($entries as $e){ $href = $e->getAttributeNode("href")->nodeValue; - $txt = fetch_url($href); + $txt = fetch_url($href . '&maxwidth=425'); + break; } } } @@ -43,7 +47,7 @@ function oembed_fetch_url($embedurl){ if ($txt==false || $txt==""){ // try oohembed service - $ourl = "http://oohembed.com/oohembed/?url=".urlencode($embedurl); + $ourl = "http://oohembed.com/oohembed/?url=".urlencode($embedurl).'&maxwidth=425'; $txt = fetch_url($ourl); } @@ -62,7 +66,7 @@ function oembed_fetch_url($embedurl){ function oembed_format_object($j){ $embedurl = $j->embedurl; - $jhtml = oembed_iframe($j->embedurl,$j->width,$j->height ); + $jhtml = oembed_iframe($j->embedurl,(isset($j->width) ? $j->width : null), (isset($j->height) ? $j->height : null) ); $ret="<span class='oembed ".$j->type."'>"; switch ($j->type) { case "video": { diff --git a/include/pgettext.php b/include/pgettext.php index 83e76ba9d..83e76ba9d 100755..100644 --- a/include/pgettext.php +++ b/include/pgettext.php diff --git a/include/pidfile.php b/include/pidfile.php new file mode 100644 index 000000000..47df8d1f4 --- /dev/null +++ b/include/pidfile.php @@ -0,0 +1,32 @@ +<?php +class pidfile { + private $_file; + private $_running; + + public function __construct($dir, $name) { + $this->_file = "$dir/$name.pid"; + + if (file_exists($this->_file)) { + $pid = trim(file_get_contents($this->_file)); + if (posix_kill($pid, 0)) { + $this->_running = true; + } + } + + if (! $this->_running) { + $pid = getmypid(); + file_put_contents($this->_file, $pid); + } + } + + public function __destruct() { + if ((! $this->_running) && file_exists($this->_file)) { + unlink($this->_file); + } + } + + public function is_already_running() { + return $this->_running; + } +} +?> diff --git a/include/plugin.php b/include/plugin.php index 8280b1022..8196e8756 100755..100644 --- a/include/plugin.php +++ b/include/plugin.php @@ -17,7 +17,12 @@ function uninstall_plugin($plugin){ }} if (! function_exists('install_plugin')){ -function install_plugin($plugin){ +function install_plugin($plugin) { + + // silently fail if plugin was removed + + if(! file_exists('addon/' . $plugin . '/' . $plugin . '.php')) + return false; logger("Addons: installing " . $plugin); $t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); @include_once('addon/' . $plugin . '/' . $plugin . '.php'); @@ -32,9 +37,11 @@ function install_plugin($plugin){ intval($t), $plugin_admin ); + return true; } else { logger("Addons: FAILED installing " . $plugin); + return false; } }} @@ -249,6 +256,7 @@ function get_theme_info($theme){ list($k,$v) = array_map("trim", explode(":",$l,2)); $k= strtolower($k); if ($k=="author"){ + $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { $info['author'][] = array('name'=>$m[1], 'link'=>$m[2]); @@ -276,3 +284,13 @@ function get_theme_info($theme){ return $info; }} + +function get_theme_screenshot($theme) { + $a = get_app(); + $exts = array('.png','.jpg'); + foreach($exts as $ext) { + if(file_exists('view/theme/' . $theme . '/screenshot' . $ext)) + return($a->get_baseurl() . '/view/theme/' . $theme . '/screenshot' . $ext); + } + return($a->get_baseurl() . '/images/blank.png'); +} diff --git a/include/poller.php b/include/poller.php index cfbc46b87..499483d00 100755..100644 --- a/include/poller.php +++ b/include/poller.php @@ -1,7 +1,6 @@ <?php require_once("boot.php"); -require_once("include/quoteconvert.php"); function poller_run($argv, $argc){ @@ -26,10 +25,20 @@ function poller_run($argv, $argc){ 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'); + $lockpath = get_config('system','lockpath'); + if ($lockpath != '') { + $pidfile = new pidfile($lockpath, 'poller.lck'); + if($pidfile->is_already_running()) { + logger("poller: Already running"); + exit; + } + } + $a->set_baseurl(get_config('system','url')); load_hooks(); @@ -70,6 +79,19 @@ function poller_run($argv, $argc){ // clear old cache Cache::clear(); + // clear item cache files if they are older than one day + $cache = get_config('system','itemcache'); + if (($cache != '') and is_dir($cache)) { + if ($dh = opendir($cache)) { + while (($file = readdir($dh)) !== false) { + $fullpath = $cache."/".$file; + if ((filetype($fullpath) == "file") and filectime($fullpath) < (time() - 86400)) + unlink($fullpath); + } + closedir($dh); + } + } + $manual_id = 0; $generation = 0; $hub_update = false; @@ -141,7 +163,10 @@ function poller_run($argv, $argc){ if($manual_id) $contact['last-update'] = '0000-00-00 00:00:00'; - if($contact['network'] === NETWORK_DFRN || $contact['network'] === NETWORK_OSTATUS) + if($contact['network'] === NETWORK_DFRN) + $contact['priority'] = 2; + + if(!get_config('system','ostatus_use_priority') and ($contact['network'] === NETWORK_OSTATUS)) $contact['priority'] = 2; if($contact['priority'] || $contact['subhub']) { @@ -217,7 +242,7 @@ function poller_run($argv, $argc){ $importer_uid = $contact['uid']; - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", + $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)) @@ -489,12 +514,17 @@ function poller_run($argv, $argc){ //$datarray['title'] = notags(trim($meta->subject)); $datarray['created'] = datetime_convert('UTC','UTC',$meta->date); - $r = email_get_msg($mbox,$msg_uid); + // 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(convertquote($r['body'], false)); + $datarray['body'] = escape_tags($r['body']); logger("Mail: Importing ".$msg_uid); diff --git a/include/profile_advanced.php b/include/profile_advanced.php index 004a58524..004a58524 100755..100644 --- a/include/profile_advanced.php +++ b/include/profile_advanced.php diff --git a/include/profile_selectors.php b/include/profile_selectors.php index 92579f64a..92579f64a 100755..100644 --- a/include/profile_selectors.php +++ b/include/profile_selectors.php diff --git a/include/profile_update.php b/include/profile_update.php index 61eaee75d..61eaee75d 100755..100644 --- a/include/profile_update.php +++ b/include/profile_update.php diff --git a/include/queue.php b/include/queue.php index d312b50f5..7e92705be 100755..100644 --- a/include/queue.php +++ b/include/queue.php @@ -61,13 +61,18 @@ function queue_run($argv, $argc){ q("DELETE FROM `queue` WHERE `created` < UTC_TIMESTAMP() - INTERVAL 3 DAY"); } - if($queue_id) + if($queue_id) { $r = q("SELECT `id` FROM `queue` WHERE `id` = %d LIMIT 1", intval($queue_id) ); - else - $r = q("SELECT `id` FROM `queue` WHERE `last` < UTC_TIMESTAMP() - INTERVAL 15 MINUTE "); + } + else { + // For the first 12 hours we'll try to deliver every 15 minutes + // After that, we'll only attempt delivery once per hour. + + $r = q("SELECT `id` FROM `queue` WHERE (( `created` > UTC_TIMESTAMP() - INTERVAL 12 HOUR && `last` < UTC_TIMESTAMP() - INTERVAL 15 MINUTE ) OR ( `last` < UTC_TIMESTAMP() - INTERVAL 1 HOUR ))"); + } if(! count($r)){ return; } diff --git a/include/queue_fn.php b/include/queue_fn.php index 3c1087f4e..3c1087f4e 100755..100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php diff --git a/include/quoteconvert.php b/include/quoteconvert.php index 3aee93234..2a6d28370 100644 --- a/include/quoteconvert.php +++ b/include/quoteconvert.php @@ -124,7 +124,7 @@ function removetofu($message) } if ($quotestart != 0) { - $message = trim(substr($message, 0, $quotestart))."\n[collapsed]\n".substr($message, $quotestart+7, -8).'[/collapsed]'; + $message = trim(substr($message, 0, $quotestart))."\n[spoiler]".substr($message, $quotestart+7, -8).'[/spoiler]'; } return($message); diff --git a/include/remoteupdate.php b/include/remoteupdate.php index 9effc9b6e..9effc9b6e 100755..100644 --- a/include/remoteupdate.php +++ b/include/remoteupdate.php diff --git a/include/salmon.php b/include/salmon.php index 3d525f51a..3d525f51a 100755..100644 --- a/include/salmon.php +++ b/include/salmon.php diff --git a/include/security.php b/include/security.php index bc2c9f0bf..66622fd33 100755..100644 --- a/include/security.php +++ b/include/security.php @@ -9,6 +9,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive $_SESSION['authenticated'] = 1; $_SESSION['page_flags'] = $user_record['page-flags']; $_SESSION['my_url'] = $a->get_baseurl() . '/profile/' . $user_record['nickname']; + $_SESSION['my_address'] = $user_record['nickname'] . '@' . substr($a->get_baseurl(),strpos($a->get_baseurl(),'://')+3); $_SESSION['addr'] = $_SERVER['REMOTE_ADDR']; $a->user = $user_record; @@ -108,14 +109,18 @@ function can_write_wall(&$a,$owner) { if(remote_user()) { - // user remembered decision and avoid a DB lookup for each and every display item + // use remembered decision and avoid a DB lookup for each and every display item // DO NOT use this function if there are going to be multiple owners + // We have a contact-id for an authenticated remote user, this block determines if the contact + // belongs to this page owner, and has the necessary permissions to post content + if($verified === 2) return true; elseif($verified === 1) return false; else { + $r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` LEFT JOIN `user` on `user`.`uid` = `contact`.`uid` WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `user`.`blockwall` = 0 AND `readonly` = 0 AND ( `contact`.`rel` IN ( %d , %d ) OR `user`.`page-flags` = %d ) LIMIT 1", @@ -125,6 +130,7 @@ function can_write_wall(&$a,$owner) { intval(CONTACT_IS_FRIEND), intval(PAGE_COMMUNITY) ); + if(count($r)) { $verified = 2; return true; @@ -197,7 +203,7 @@ function permissions_sql($owner_id,$remote_verified = false,$groups = null) { " AND ( allow_cid = '' OR allow_cid REGEXP '<%d>' ) AND ( deny_cid = '' OR NOT deny_cid REGEXP '<%d>' ) AND ( allow_gid = '' OR allow_gid REGEXP '%s' ) - AND ( deny_gid = '' OR NOT deny_gid REGEXP '%s') + AND ( deny_gid = '' OR NOT deny_gid REGEXP '%s') ", intval($remote_user), intval($remote_user), @@ -207,4 +213,135 @@ function permissions_sql($owner_id,$remote_verified = false,$groups = null) { } } return $sql; +} + + +function item_permissions_sql($owner_id,$remote_verified = false,$groups = null) { + + $local_user = local_user(); + $remote_user = remote_user(); + + /** + * Construct permissions + * + * default permissions - anonymous user + */ + + $sql = " AND allow_cid = '' + AND allow_gid = '' + AND deny_cid = '' + AND deny_gid = '' + AND private = 0 + "; + + /** + * Profile owner - everything is visible + */ + + if(($local_user) && ($local_user == $owner_id)) { + $sql = ''; + } + + /** + * Authenticated visitor. Unless pre-verified, + * check that the contact belongs to this $owner_id + * and load the groups the visitor belongs to. + * If pre-verified, the caller is expected to have already + * done this and passed the groups into this function. + */ + + elseif($remote_user) { + + if(! $remote_verified) { + $r = q("SELECT id FROM contact WHERE id = %d AND uid = %d AND blocked = 0 LIMIT 1", + intval($remote_user), + intval($owner_id) + ); + if(count($r)) { + $remote_verified = true; + $groups = init_groups_visitor($remote_user); + } + } + if($remote_verified) { + + $gs = '<<>>'; // should be impossible to match + + if(is_array($groups) && count($groups)) { + foreach($groups as $g) + $gs .= '|<' . intval($g) . '>'; + } + + $sql = sprintf( + " AND ( private = 0 OR ( private = 1 AND wall = 1 AND ( allow_cid = '' OR allow_cid REGEXP '<%d>' ) + AND ( deny_cid = '' OR NOT deny_cid REGEXP '<%d>' ) + AND ( allow_gid = '' OR allow_gid REGEXP '%s' ) + AND ( deny_gid = '' OR NOT deny_gid REGEXP '%s'))) + ", + intval($remote_user), + intval($remote_user), + dbesc($gs), + dbesc($gs) + ); + } + } + + return $sql; +} + + +/* + * Functions used to protect against Cross-Site Request Forgery + * The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key. + * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; + * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). + * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: + * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). + * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. + * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, + * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). + */ +function get_form_security_token($typename = '') { + $a = get_app(); + + $timestamp = time(); + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename); + + return $timestamp . '.' . $sec_hash; +} + +function check_form_security_token($typename = '', $formname = 'form_security_token') { + if (!x($_REQUEST, $formname)) return false; + $hash = $_REQUEST[$formname]; + + $max_livetime = 10800; // 3 hours + + $a = get_app(); + + $x = explode('.', $hash); + if (time() > (IntVal($x[0]) + $max_livetime)) return false; + + $sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename); + + return ($sec_hash == $x[1]); +} + +function check_form_security_std_err_msg() { + return t('The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before subitting it.') . EOL; +} +function check_form_security_token_redirectOnErr($err_redirect, $typename = '', $formname = 'form_security_token') { + if (!check_form_security_token($typename, $formname)) { + $a = get_app(); + logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + notice( check_form_security_std_err_msg() ); + goaway($a->get_baseurl() . $err_redirect ); + } +} +function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'form_security_token') { + if (!check_form_security_token($typename, $formname)) { + logger('check_form_security_token failed: user ' . $a->user['guid'] . ' - form element ' . $typename); + logger('check_form_security_token failed: _REQUEST data: ' . print_r($_REQUEST, true), LOGGER_DATA); + header('HTTP/1.1 403 Forbidden'); + killme(); + } }
\ No newline at end of file diff --git a/include/session.php b/include/session.php index 6c32e299f..6c32e299f 100755..100644 --- a/include/session.php +++ b/include/session.php diff --git a/include/socgraph.php b/include/socgraph.php index 79d7340a4..3f5194049 100755..100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -230,19 +230,21 @@ function all_friends($uid,$cid,$start = 0, $limit = 80) { -function suggestion_query($uid, $start = 0, $limit = 40) { +function suggestion_query($uid, $start = 0, $limit = 80) { if(! $uid) return array(); $r = q("SELECT count(glink.gcid) as `total`, gcontact.* from gcontact left join glink on glink.gcid = gcontact.id - where uid = %d and not gcontact.nurl in ( select nurl from contact where uid = %d) + where uid = %d 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 ) group by glink.gcid order by total desc limit %d, %d ", intval($uid), intval($uid), intval($uid), + intval($uid), intval($start), intval($limit) ); @@ -252,11 +254,13 @@ function suggestion_query($uid, $start = 0, $limit = 40) { $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 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 ", intval($uid), intval($uid), + intval($uid), intval($start), intval($limit) ); diff --git a/include/system_unavailable.php b/include/system_unavailable.php index bd7196cdf..bd7196cdf 100755..100644 --- a/include/system_unavailable.php +++ b/include/system_unavailable.php diff --git a/include/template_processor.php b/include/template_processor.php index 8671587fc..46252c355 100755..100644 --- a/include/template_processor.php +++ b/include/template_processor.php @@ -13,12 +13,14 @@ var $debug=false; private function _preg_error(){ + switch(preg_last_error()){ case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break; case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break; case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break; case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break; - case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; +// This is only valid for php > 5.3, not certain how to code around it for unit tests +// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; default: //die("Unknown preg error."); return; @@ -80,8 +82,13 @@ */ private function _replcb_for($args){ $m = array_map('trim', explode(" as ", $args[2])); - list($keyname, $varname) = explode("=>",$m[1]); - if (is_null($varname)) { $varname=$keyname; $keyname=""; } + $x = explode("=>",$m[1]); + if (count($x) == 1) { + $varname = $x[0]; + $keyname = ""; + } else { + list($keyname, $varname) = $x; + } if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ; //$vals = $this->r[$m[0]]; $vals = $this->_get_var($m[0]); @@ -91,7 +98,7 @@ $this->_push_stack(); $r = $this->r; $r[$varname] = $v; - if ($keyname!='') $r[$keyname] = $k; + if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k); $ret .= $this->replace($args[3], $r); $this->_pop_stack(); } @@ -198,7 +205,7 @@ $os=$s; $count++; $s = $this->var_replace($s); } - return template_unescape($s); + return $s; } } diff --git a/include/text.php b/include/text.php index 042ee982c..aced9e0a8 100755..100644 --- a/include/text.php +++ b/include/text.php @@ -20,7 +20,7 @@ function replace_macros($s,$r) { //$a = get_app(); //$a->page['debug'] .= "$tt <br>\n"; - return $r; + return template_unescape($r); }} @@ -80,6 +80,9 @@ function escape_tags($string) { if(! function_exists('autoname')) { function autoname($len) { + if($len <= 0) + return ''; + $vowels = array('a','a','ai','au','e','e','e','ee','ea','i','ie','o','ou','u'); if(mt_rand(0,5) == 4) $vowels[] = 'y'; @@ -205,7 +208,6 @@ function hex2bin($s) { return ''; if(! ctype_xdigit($s)) { - logger('hex2bin: illegal input: ' . print_r(debug_backtrace(), true)); return($s); } @@ -226,6 +228,9 @@ if(! function_exists('paginate')) { function paginate(&$a) { $o = ''; $stripped = preg_replace('/(&page=[0-9]*)/','',$a->query_string); + +// $stripped = preg_replace('/&zrl=(.*?)([\?&]|$)/ism','',$stripped); + $stripped = str_replace('q=','',$stripped); $stripped = trim($stripped,'/'); $pagenum = $a->pager['page']; @@ -610,6 +615,8 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) { $url = $redirect_url; $sparkle = ' sparkle'; } + else + $url = zrl($url); } $click = ((x($contact,'click')) ? ' onclick="' . $contact['click'] . '" ' : ''); if($click) @@ -638,7 +645,7 @@ if(! function_exists('search')) { function search($s,$id='search-box',$url='/search',$save = false) { $a = get_app(); $o = '<div id="' . $id . '">'; - $o .= '<form action="' . $a->get_baseurl() . $url . '" method="get" >'; + $o .= '<form action="' . $a->get_baseurl((stristr($url,'network')) ? true : false) . $url . '" method="get" >'; $o .= '<input type="text" name="search" id="search-text" value="' . $s .'" />'; $o .= '<input type="submit" name="submit" id="search-submit" value="' . t('Search') . '" />'; if($save) @@ -694,8 +701,13 @@ function linkify($s) { if(! function_exists('smilies')) { function smilies($s, $sample = false) { + $a = get_app(); + if(intval(get_config('system','no_smilies')) + || (local_user() && intval(get_pconfig(local_user(),'system','no_smilies')))) + return $s; + $s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_encode',$s); $s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_encode',$s); @@ -704,27 +716,23 @@ function smilies($s, $sample = false) { '</3', '<\\3', ':-)', -// ':)', ';-)', -// ';)', ':-(', -// ':(', ':-P', -// ':P', + ':-p', ':-"', ':-"', ':-x', ':-X', ':-D', -// ':D', '8-|', '8-O', ':-O', '\\o/', 'o.O', 'O.o', - '\\.../', - '\\ooo/', + 'o_O', + 'O_o', ":'(", ":-!", ":-/", @@ -734,10 +742,9 @@ function smilies($s, $sample = false) { ':homebrew', ':coffee', ':facepalm', - ':headdesk', '~friendika', - '~friendica', - 'Diaspora*' + '~friendica' + ); $icons = array( @@ -745,27 +752,23 @@ function smilies($s, $sample = false) { '<img src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="</3" />', '<img src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="<\\3" />', '<img src="' . $a->get_baseurl() . '/images/smiley-smile.gif" alt=":-)" />', -// '<img src="' . $a->get_baseurl() . '/images/smiley-smile.gif" alt=":)" />', '<img src="' . $a->get_baseurl() . '/images/smiley-wink.gif" alt=";-)" />', -// '<img src="' . $a->get_baseurl() . '/images/smiley-wink.gif" alt=";)"/>', '<img src="' . $a->get_baseurl() . '/images/smiley-frown.gif" alt=":-(" />', -// '<img src="' . $a->get_baseurl() . '/images/smiley-frown.gif" alt=":(" />', '<img src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" />', -// '<img src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":P" />', + '<img src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-p" />', '<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />', '<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />', '<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" />', '<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" />', '<img src="' . $a->get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" />', -// '<img src="' . $a->get_baseurl() . '/images/smiley-laughing.gif" alt=":D"/>', '<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" />', '<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" />', '<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt=":-O" />', '<img src="' . $a->get_baseurl() . '/images/smiley-thumbsup.gif" alt="\\o/" />', '<img src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="o.O" />', '<img src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="O.o" />', - '<img src="' . $a->get_baseurl() . '/images/smiley-shaka.gif" alt="\\.../" />', - '<img src="' . $a->get_baseurl() . '/images/smiley-shaka.gif" alt="\\ooo/" />', + '<img src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="o_O" />', + '<img src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="O_o" />', '<img src="' . $a->get_baseurl() . '/images/smiley-cry.gif" alt=":\'(" />', '<img src="' . $a->get_baseurl() . '/images/smiley-foot-in-mouth.gif" alt=":-!" />', '<img src="' . $a->get_baseurl() . '/images/smiley-undecided.gif" alt=":-/" />', @@ -775,11 +778,8 @@ function smilies($s, $sample = false) { '<img src="' . $a->get_baseurl() . '/images/beer_mug.gif" alt=":homebrew" />', '<img src="' . $a->get_baseurl() . '/images/coffee.gif" alt=":coffee" />', '<img src="' . $a->get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" />', - '<img src="' . $a->get_baseurl() . '/images/smiley-bangheaddesk.gif" alt=":headdesk" />', '<a href="http://project.friendika.com">~friendika <img src="' . $a->get_baseurl() . '/images/friendika-16.png" alt="~friendika" /></a>', - '<a href="http://friendica.com">~friendica <img src="' . $a->get_baseurl() . '/images/friendica-16.png" alt="~friendica" /></a>', - '<a href="http://diasporafoundation.org">Diaspora<img src="' . $a->get_baseurl() . '/images/diaspora.png" alt="Diaspora*" /></a>', - + '<a href="http://friendica.com">~friendica <img src="' . $a->get_baseurl() . '/images/friendica-16.png" alt="~friendica" /></a>' ); $params = array('texts' => $texts, 'icons' => $icons, 'string' => $s); @@ -870,16 +870,30 @@ function link_compare($a,$b) { if(! function_exists('prepare_body')) { function prepare_body($item,$attach = false) { + $a = get_app(); call_hooks('prepare_body_init', $item); - $s = prepare_text($item['body']); + $cache = get_config('system','itemcache'); + + if (($cache != '')) { + $cachefile = $cache."/".$item["guid"]."-".strtotime($item["edited"])."-".hash("crc32", $item['body']); + + if (file_exists($cachefile)) + $s = file_get_contents($cachefile); + else { + $s = prepare_text($item['body']); + file_put_contents($cachefile, $s); + } + } else + $s = prepare_text($item['body']); $prep_arr = array('item' => $item, 'html' => $s); call_hooks('prepare_body', $prep_arr); $s = $prep_arr['html']; - if(! $attach) + if(! $attach) { return $s; + } $arr = explode(',',$item['attach']); if(count($arr)) { @@ -909,10 +923,67 @@ function prepare_body($item,$attach = false) { } $s .= '<div class="clear"></div></div>'; } + $matches = false; + $cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { +// logger('prepare_text: categories: ' . print_r($matches,true), LOGGER_DEBUG); + foreach($matches as $mtch) { + if(strlen($x)) + $x .= ','; + $x .= xmlify(file_tag_decode($mtch[1])); + } + if(strlen($x)) + $s .= '<div class="categorytags"><span>' . t('Categories:') . ' </span>' . $x . '</div>'; + + + } + $matches = false; + $x = ''; + $cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { +// logger('prepare_text: filed_under: ' . print_r($matches,true), LOGGER_DEBUG); + foreach($matches as $mtch) { + if(strlen($x)) + $x .= ' '; + $x .= xmlify(file_tag_decode($mtch[1])) . ' <a href="' . $a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&term=' . xmlify(file_tag_decode($mtch[1])) . '" title="' . t('remove') . '" >' . t('[remove]') . '</a>'; + } + if(strlen($x) && (local_user() == $item['uid'])) + $s .= '<div class="filesavetags"><span>' . t('Filed under:') . ' </span>' . $x . '</div>'; + } + + // Look for spoiler + $spoilersearch = '<blockquote class="spoiler">'; + + // Remove line breaks before the spoiler + while ((strpos($s, "\n".$spoilersearch) !== false)) + $s = str_replace("\n".$spoilersearch, $spoilersearch, $s); + while ((strpos($s, "<br />".$spoilersearch) !== false)) + $s = str_replace("<br />".$spoilersearch, $spoilersearch, $s); + + while ((strpos($s, $spoilersearch) !== false)) { + + $pos = strpos($s, $spoilersearch); + $rnd = random_string(8); + $spoilerreplace = '<br /> <span id="spoiler-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'spoiler-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'. + '<blockquote class="spoiler" id="spoiler-'.$rnd.'" style="display: none;">'; + $s = substr($s, 0, $pos).$spoilerreplace.substr($s, $pos+strlen($spoilersearch)); + } + + // Look for quote with author + $authorsearch = '<blockquote class="author">'; + + while ((strpos($s, $authorsearch) !== false)) { + $pos = strpos($s, $authorsearch); + $rnd = random_string(8); + $authorreplace = '<br /> <span id="author-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'author-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'. + '<blockquote class="author" id="author-'.$rnd.'" style="display: block;">'; + $s = substr($s, 0, $pos).$authorreplace.substr($s, $pos+strlen($authorsearch)); + } $prep_arr = array('item' => $item, 'html' => $s); call_hooks('prepare_body_final', $prep_arr); + return $prep_arr['html']; }} @@ -1231,4 +1302,207 @@ function item_post_type($item) { return t('post'); } +// post categories and "save to file" use the same item.file table for storage. +// We will differentiate the different uses by wrapping categories in angle brackets +// and save to file categories in square brackets. +// To do this we need to escape these characters if they appear in our tag. + +function file_tag_encode($s) { + return str_replace(array('<','>','[',']'),array('%3c','%3e','%5b','%5d'),$s); +} + +function file_tag_decode($s) { + return str_replace(array('%3c','%3e','%5b','%5d'),array('<','>','[',']'),$s); +} + +function file_tag_file_query($table,$s,$type = 'file') { + + if($type == 'file') + $str = preg_quote( '[' . str_replace('%','%%',file_tag_encode($s)) . ']' ); + else + $str = preg_quote( '<' . str_replace('%','%%',file_tag_encode($s)) . '>' ); + return " AND " . (($table) ? dbesc($table) . '.' : '') . "file regexp '" . dbesc($str) . "' "; +} + +// ex. given music,video return <music><video> or [music][video] +function file_tag_list_to_file($list,$type = 'file') { + $tag_list = ''; + if(strlen($list)) { + $list_array = explode(",",$list); + if($type == 'file') { + $lbracket = '['; + $rbracket = ']'; + } + else { + $lbracket = '<'; + $rbracket = '>'; + } + + foreach($list_array as $item) { + if(strlen($item)) { + $tag_list .= $lbracket . file_tag_encode(trim($item)) . $rbracket; + } + } + } + return $tag_list; +} + +// ex. given <music><video>[friends], return music,video or friends +function file_tag_file_to_list($file,$type = 'file') { + $matches = false; + $list = ''; + if($type == 'file') { + $cnt = preg_match_all('/\[(.*?)\]/',$file,$matches,PREG_SET_ORDER); + } + else { + $cnt = preg_match_all('/<(.*?)>/',$file,$matches,PREG_SET_ORDER); + } + if($cnt) { + foreach($matches as $mtch) { + if(strlen($list)) + $list .= ','; + $list .= file_tag_decode($mtch[1]); + } + } + + return $list; +} + +function file_tag_update_pconfig($uid,$file_old,$file_new,$type = 'file') { + // $file_old - categories previously associated with an item + // $file_new - new list of categories for an item + + if(! intval($uid)) + return false; + + if($file_old == $file_new) + return true; + + $saved = get_pconfig($uid,'system','filetags'); + if(strlen($saved)) { + if($type == 'file') { + $lbracket = '['; + $rbracket = ']'; + } + else { + $lbracket = '<'; + $rbracket = '>'; + } + + $filetags_updated = $saved; + + // check for new tags to be added as filetags in pconfig + $new_tags = array(); + $check_new_tags = explode(",",file_tag_file_to_list($file_new,$type)); + + foreach($check_new_tags as $tag) { + if(! stristr($saved,$lbracket . file_tag_encode($tag) . $rbracket)) + $new_tags[] = $tag; + } + + $filetags_updated .= file_tag_list_to_file(implode(",",$new_tags),$type); + + // check for deleted tags to be removed from filetags in pconfig + $deleted_tags = array(); + $check_deleted_tags = explode(",",file_tag_file_to_list($file_old,$type)); + + foreach($check_deleted_tags as $tag) { + if(! stristr($file_new,$lbracket . file_tag_encode($tag) . $rbracket)) + $deleted_tags[] = $tag; + } + + foreach($deleted_tags as $key => $tag) { + $r = q("select file from item where uid = %d " . file_tag_file_query('item',$tag,$type), + intval($uid) + ); + + if(count($r)) { + unset($deleted_tags[$key]); + } + else { + $filetags_updated = str_replace($lbracket . file_tag_encode($tag) . $rbracket,'',$filetags_updated); + } + } + + if($saved != $filetags_updated) { + set_pconfig($uid,'system','filetags', $filetags_updated); + } + return true; + } + else + if(strlen($file_new)) { + set_pconfig($uid,'system','filetags', $file_new); + } + return true; +} + +function file_tag_save_file($uid,$item,$file) { + $result = false; + if(! intval($uid)) + return false; + $r = q("select file from item where id = %d and uid = %d limit 1", + intval($item), + intval($uid) + ); + if(count($r)) { + if(! stristr($r[0]['file'],'[' . file_tag_encode($file) . ']')) + q("update item set file = '%s' where id = %d and uid = %d limit 1", + dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'), + intval($item), + intval($uid) + ); + $saved = get_pconfig($uid,'system','filetags'); + if((! strlen($saved)) || (! stristr($saved,'[' . file_tag_encode($file) . ']'))) + set_pconfig($uid,'system','filetags',$saved . '[' . file_tag_encode($file) . ']'); + info( t('Item filed') ); + } + return true; +} + +function file_tag_unsave_file($uid,$item,$file) { + $result = false; + if(! intval($uid)) + return false; + + $pattern = '[' . file_tag_encode($file) . ']' ; + + $r = q("select file from item where id = %d and uid = %d limit 1", + intval($item), + intval($uid) + ); + if(! count($r)) + return false; + + q("update item set file = '%s' where id = %d and uid = %d limit 1", + dbesc(str_replace($pattern,'',$r[0]['file'])), + intval($item), + intval($uid) + ); + + $r = q("select file from item where uid = %d " . file_tag_file_query('item',$file), + intval($uid) + ); + + if(! count($r)) { + $saved = get_pconfig($uid,'system','filetags'); + set_pconfig($uid,'system','filetags',str_replace($pattern,'',$saved)); + } + return true; +} + +function normalise_openid($s) { + return trim(str_replace(array('http://','https://'),array('',''),$s),'/'); +} + + +function undo_post_tagging($s) { + $matches = null; + $cnt = preg_match_all('/([@#])\[url=(.*?)\](.*?)\[\/url\]/ism',$s,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $s = str_replace($mtch[0], $mtch[1] . $mtch[3],$s); + } + } + return $s; +} |