diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/api.php | 113 | ||||
-rw-r--r-- | include/auth.php | 2 | ||||
-rw-r--r-- | include/bb2diaspora.php | 7 | ||||
-rw-r--r-- | include/config.php | 26 | ||||
-rw-r--r-- | include/dba.php | 22 | ||||
-rw-r--r-- | include/delivery.php | 2 | ||||
-rw-r--r-- | include/diaspora.php | 16 | ||||
-rw-r--r-- | include/enotify.php | 2 | ||||
-rw-r--r-- | include/event.php | 17 | ||||
-rw-r--r-- | include/items.php | 115 | ||||
-rw-r--r-- | include/nav.php | 2 | ||||
-rw-r--r-- | include/notifier.php | 2 | ||||
-rw-r--r-- | include/profile_advanced.php | 4 | ||||
-rw-r--r-- | include/profile_selectors.php | 7 | ||||
-rw-r--r-- | include/text.php | 4 | ||||
-rw-r--r-- | include/user.php | 325 |
16 files changed, 571 insertions, 95 deletions
diff --git a/include/api.php b/include/api.php index a693a32c8..5c17b35f5 100644 --- a/include/api.php +++ b/include/api.php @@ -4,26 +4,26 @@ require_once("conversation.php"); require_once("oauth.php"); require_once("html2plain.php"); - /* + /* * Twitter-Like API - * + * */ $API = Array(); - $called_api = Null; + $called_api = Null; function api_date($str){ //Wed May 23 06:01:13 +0000 2007 return datetime_convert('UTC', 'UTC', $str, "D M d H:i:s +0000 Y" ); } - - + + function api_register_func($path, $func, $auth=false){ global $API; $API[$path] = array('func'=>$func, 'auth'=>$auth); } - + /** * Simple HTTP Login */ @@ -691,24 +691,24 @@ 'geo' => '', 'coordinates' => $lastwall['coord'], 'place' => $lastwall['location'], - 'contributors' => '' + 'contributors' => '' ); } return api_apply_template("user", $type, array('$user' => $user_info)); - + } api_register_func('api/users/show','api_users_show'); - + /** - * + * * http://developer.twitter.com/doc/get/statuses/home_timeline - * + * * TODO: Optional parameters * TODO: Add reply info */ function api_statuses_home_timeline(&$a, $type){ if (local_user()===false) return false; - + $user_info = api_get_user($a); // get last newtork messages @@ -720,7 +720,7 @@ $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); @@ -728,7 +728,7 @@ if ($max_id > 0) $sql_extra = 'AND `item`.`id` <= '.intval($max_id); - $r = q("SELECT `item`.*, `item`.`id` AS `item_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` @@ -747,7 +747,7 @@ $ret = api_format_items($r,$user_info); - + $data = array('$statuses' => $ret); switch($type){ case "atom": @@ -761,7 +761,7 @@ return($as); break; } - + return api_apply_template("timeline", $type, $data); } api_register_func('api/statuses/home_timeline','api_statuses_home_timeline', true); @@ -769,7 +769,7 @@ function api_statuses_public_timeline(&$a, $type){ if (local_user()===false) return false; - + $user_info = api_get_user($a); // get last newtork messages @@ -781,7 +781,7 @@ $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); @@ -789,7 +789,7 @@ if ($max_id > 0) $sql_extra = 'AND `item`.`id` <= '.intval($max_id); - /*$r = q("SELECT `item`.*, `item`.`id` AS `item_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` @@ -806,17 +806,17 @@ intval($since_id), intval($start), intval($count) );*/ - $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + $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`.`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 `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 @@ -827,7 +827,7 @@ $ret = api_format_items($r,$user_info); - + $data = array('$statuses' => $ret); switch($type){ case "atom": @@ -841,7 +841,7 @@ return($as); break; } - + return api_apply_template("timeline", $type, $data); } api_register_func('api/statuses/public_timeline','api_statuses_public_timeline', true); @@ -857,11 +857,11 @@ // params $id = intval($a->argv[3]); - logger('API: api_statuses_show: '.$id); + 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`, + $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` @@ -875,7 +875,7 @@ ); $ret = api_format_items($r,$user_info); - + $data = array('$status' => $ret[0]); /*switch($type){ case "atom": @@ -976,7 +976,7 @@ $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); @@ -985,11 +985,19 @@ $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 (get_config('system','use_fulltext_engine')) + $sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where (MATCH(`author-link`) AGAINST ('".'"%s"'."' in boolean mode) or MATCH(`tag`) AGAINST ('".'"%s"'."' in boolean mode) or MATCH(tag) AGAINST ('".'"%s"'."' in boolean mode))) ", + dbesc(protect_sprintf($myurl)), + dbesc(protect_sprintf($myurl)), + dbesc(protect_sprintf($diasp_url)) + ); + else + $sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where ( `author-link` like '%s' or `tag` like '%s' or tag like '%s' )) ", + dbesc(protect_sprintf('%' . $myurl)), + dbesc(protect_sprintf('%' . $myurl . ']%')), + dbesc(protect_sprintf('%' . $diasp_url . ']%')) + ); if ($max_id > 0) $sql_extra .= ' AND `item`.`id` <= '.intval($max_id); @@ -1013,7 +1021,7 @@ $ret = api_format_items($r,$user_info); - + $data = array('$statuses' => $ret); switch($type){ case "atom": @@ -1027,7 +1035,7 @@ return($as); break; } - + return api_apply_template("timeline", $type, $data); } api_register_func('api/statuses/mentions','api_statuses_mentions', true); @@ -1078,14 +1086,14 @@ $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); } - + return api_apply_template("timeline", $type, $data); } @@ -1094,25 +1102,25 @@ function api_favorites(&$a, $type){ if (local_user()===false) return false; - + $user_info = api_get_user($a); // in friendica starred item are private // return favorites only for self logger('api_favorites: self:' . $user_info['self']); - + if ($user_info['self']==0) { $ret = array(); } else { - - + + // params $count = (x($_GET,'count')?$_GET['count']:20); $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); if ($page<0) $page=0; - + $start = $page*$count; - $r = q("SELECT `item`.*, `item`.`id` AS `item_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` @@ -1129,16 +1137,16 @@ ); $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); } - + return api_apply_template("timeline", $type, $data); } @@ -1208,7 +1216,7 @@ $as['link']['type'] = "text/html"; return($as); } - + function api_format_items($r,$user_info) { //logger('api_format_items: ' . print_r($r,true)); @@ -1223,14 +1231,14 @@ $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", + $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 + $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']; @@ -1251,6 +1259,9 @@ else $statustext = trim($statustitle."\n\n".$statusbody); + if (($item["network"] == NETWORK_FEED) and (strlen($statustext)> 1000)) + $statustext = substr($statustext, 0, 1000)."... \n".$item["plink"]; + $status = array( 'text' => $statustext, 'truncated' => False, diff --git a/include/auth.php b/include/auth.php index b87662fea..cba6a67a7 100644 --- a/include/auth.php +++ b/include/auth.php @@ -53,6 +53,8 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p $check = get_config('system','paranoia'); // extra paranoia - if the IP changed, log them out if($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) { + logger('Session address changed. Paranoid setting in effect, blocking session. ' + . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']); nuke_session(); goaway(z_root()); } diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index 8487f845a..d86ba4543 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -221,13 +221,18 @@ function bb2diaspora($Text,$preserve_nl = false) { $Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text); - $Text = preg_replace('/\[(.*?)\]\((.*?)\\\\_(.*?)\)/ism','[$1]($2_$3)',$Text); + $Text = preg_replace_callback('/\[(.*?)\]\((.*?)\)/ism','unescape_underscores_in_links',$Text); call_hooks('bb2diaspora',$Text); return $Text; } +function unescape_underscores_in_links($m) { + $y = str_replace('\\_','_', $m[2]); + return('[' . $m[1] . '](' . $y . ')'); +} + function format_event_diaspora($ev) { $a = get_app(); diff --git a/include/config.php b/include/config.php index 12fc9cafc..df1070c13 100644 --- a/include/config.php +++ b/include/config.php @@ -6,7 +6,7 @@ * Note: * Please do not store booleans - convert to 0/1 integer values * The get_?config() functions return boolean false for keys that are unset, - * and this could lead to subtle bugs. + * and this could lead to subtle bugs. * * There are a few places in the code (such as the admin panel) where boolean * configurations need to be fixed as of 10/08/2011. @@ -30,6 +30,9 @@ function load_config($family) { $a->config[$family][$k] = $rr['v']; } } + } else if ($rr['cat'] != 'config') { + // Negative caching + $a->config[$family] = "!<unset>!"; } }} @@ -47,6 +50,13 @@ function get_config($family, $key, $instore = false) { global $a; if(! $instore) { + // Looking if the whole family isn't set + if(isset($a->config[$family])) { + if($a->config[$family] === '!<unset>!') { + return false; + } + } + if(isset($a->config[$family][$key])) { if($a->config[$family][$key] === '!<unset>!') { return false; @@ -87,11 +97,11 @@ function set_config($family,$key,$value) { dbesc($key), dbesc($dbvalue) ); - if($ret) + if($ret) return $value; return $ret; } - + $ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1", dbesc($dbvalue), dbesc($family), @@ -118,6 +128,9 @@ function load_pconfig($uid,$family) { $k = $rr['k']; $a->config[$uid][$family][$k] = $rr['v']; } + } else if ($rr['cat'] != 'config') { + // Negative caching + $a->config[$uid][$family] = "!<unset>!"; } }} @@ -129,6 +142,13 @@ function get_pconfig($uid,$family, $key, $instore = false) { global $a; if(! $instore) { + // Looking if the whole family isn't set + if(isset($a->config[$uid][$family])) { + if($a->config[$uid][$family] === '!<unset>!') { + return false; + } + } + if(isset($a->config[$uid][$family][$key])) { if($a->config[$uid][$family][$key] === '!<unset>!') { return false; diff --git a/include/dba.php b/include/dba.php index c9f880241..881097f30 100644 --- a/include/dba.php +++ b/include/dba.php @@ -32,9 +32,9 @@ class dba { if (!(strlen($server) && strlen($user))){ $this->connected = false; $this->db = null; - return; + return; } - + if($install) { if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) { if(! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) { @@ -71,23 +71,29 @@ class dba { } public function q($sql) { - + if((! $this->db) || (! $this->connected)) return false; - + $this->error = ''; + //if (get_config("system", "db_log") != "") + // @file_put_contents(get_config("system", "db_log"), datetime_convert().':'.session_id(). ' Start '.$sql."\n", FILE_APPEND); + if($this->mysqli) $result = @$this->db->query($sql); else $result = @mysql_query($sql,$this->db); + //if (get_config("system", "db_log") != "") + // @file_put_contents(get_config("system", "db_log"), datetime_convert().':'.session_id(). ' Stop '."\n", FILE_APPEND); + if($this->mysqli) { if($this->db->errno) $this->error = $this->db->error; } elseif(mysql_errno($this->db)) - $this->error = mysql_error($this->db); + $this->error = mysql_error($this->db); if(strlen($this->error)) { logger('dba: ' . $this->error); @@ -107,8 +113,8 @@ class dba { else $mesg = mysql_num_rows($result) . ' results' . EOL; } - - $str = 'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg + + $str = 'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg . (($this->error) ? ' error: ' . $this->error : '') . EOL; @@ -146,7 +152,7 @@ class dba { } } - + if($this->debug) logger('dba: ' . printable(print_r($r, true))); return($r); diff --git a/include/delivery.php b/include/delivery.php index 61b0bd33a..32943d5da 100644 --- a/include/delivery.php +++ b/include/delivery.php @@ -288,7 +288,7 @@ function delivery_run($argv, $argc){ if($normal_mode) { if($item_id == $item['id'] || $item['id'] == $item['parent']) - $atom .= atom_entry($item,'text',null,$owner,true); + $atom .= atom_entry($item,'text',null,$owner,true,(($top_level) ? $contact['id'] : 0)); } else $atom .= atom_entry($item,'text',null,$owner,true); diff --git a/include/diaspora.php b/include/diaspora.php index 3f2cdf8e4..f7c2c5e8e 100644 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -2055,8 +2055,12 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) { $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); $theiraddr = $contact['addr']; - $p = q("select guid from item where parent = %d limit 1", - $item['parent'] + // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always + // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent. + // The only item with `parent` and `id` as the parent id is the parent item. + $p = q("select guid from item where parent = %d and id = %d limit 1", + intval($item['parent']), + intval($item['parent']) ); if(count($p)) $parent_guid = $p[0]['guid']; @@ -2111,8 +2115,12 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { $theiraddr = $contact['addr']; - $p = q("select guid from item where parent = %d limit 1", - $item['parent'] + // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always + // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent. + // The only item with `parent` and `id` as the parent id is the parent item. + $p = q("select guid from item where parent = %d and id = %d limit 1", + intval($item['parent']), + intval($item['parent']) ); if(count($p)) $parent_guid = $p[0]['guid']; diff --git a/include/enotify.php b/include/enotify.php index ca134ac86..f7ef74fac 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -13,7 +13,7 @@ function notification($params) { $banner = t('Friendica Notification'); $product = FRIENDICA_PLATFORM; - $siteurl = z_path(); + $siteurl = $a->get_baseurl(true); $thanks = t('Thank You,'); $sitename = get_config('config','sitename'); $site_admin = sprintf( t('%s Administrator'), $sitename); diff --git a/include/event.php b/include/event.php index 29202badd..866ae8c3f 100644 --- a/include/event.php +++ b/include/event.php @@ -42,7 +42,7 @@ function format_event_html($ev) { return $o; } - +/* function parse_event($h) { require_once('include/Scrape.php'); @@ -108,7 +108,7 @@ function parse_event($h) { return $ret; } - +*/ function format_event_bbcode($ev) { @@ -162,7 +162,6 @@ function bbtoevent($s) { $match = ''; if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match)) $ev['adjust'] = $match[1]; - $match = ''; $ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); return $ev; @@ -294,10 +293,14 @@ function event_store($arr) { intval($arr['uid']) ); - return $r[0]['id']; + $item_id = $r[0]['id']; } else - return 0; + $item_id = 0; + + call_hooks("event_updated", $arr['id']); + + return $item_id; } else { @@ -361,7 +364,7 @@ function event_store($arr) { $item_arr['body'] = format_event_bbcode($event); - $item_arr['object'] = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($uri) . '</id>'; + $item_arr['object'] = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($arr['uri']) . '</id>'; $item_arr['object'] .= '<content>' . xmlify(format_event_bbcode($event)) . '</content>'; $item_arr['object'] .= '</object>' . "\n"; @@ -383,6 +386,8 @@ function event_store($arr) { ); } + call_hooks("event_created", $event['id']); + return $item_id; } } diff --git a/include/items.php b/include/items.php index e5b640fd2..0ed16217f 100644 --- a/include/items.php +++ b/include/items.php @@ -180,6 +180,10 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) foreach($items as $item) { + // prevent private email from leaking. + if($item['network'] === NETWORK_MAIL) + continue; + // public feeds get html, our own nodes use bbcode if($public_feed) { @@ -1063,9 +1067,6 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $a = get_app(); -// if((! strlen($contact['issued-id'])) && (! $contact['duplex']) && (! ($owner['page-flags'] == PAGE_COMMUNITY))) -// return 3; - $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); if($contact['duplex'] && $contact['dfrn-id']) @@ -1130,6 +1131,9 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $rino_allowed = ((intval($res->rino) === 1) ? 1 : 0); $page = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0); + if($owner['page-flags'] == PAGE_PRVGROUP) + $page = 2; + $final_dfrn_id = ''; if($perm) { @@ -1183,7 +1187,7 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $postvars['ssl_policy'] = $ssl_policy; if($page) - $postvars['page'] = '1'; + $postvars['page'] = $page; if($rino && $rino_allowed && (! $dissolve)) { $key = substr(random_string(),0,16); @@ -2832,7 +2836,7 @@ function atom_author($tag,$name,$uri,$h,$w,$photo) { return $o; } -function atom_entry($item,$type,$author,$owner,$comment = false) { +function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { $a = get_app(); @@ -2844,7 +2848,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false) { if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) - $body = fix_private_photos($item['body'],$owner['uid']); + $body = fix_private_photos($item['body'],$owner['uid'],$item,$cid); else $body = $item['body']; @@ -2927,14 +2931,17 @@ function atom_entry($item,$type,$author,$owner,$comment = false) { return $o; } -function fix_private_photos($s,$uid) { +function fix_private_photos($s,$uid, $item = null, $cid = 0) { $a = get_app(); - logger('fix_private_photos'); - if(preg_match("/\[img\](.*?)\[\/img\]/is",$s,$matches)) { - $image = $matches[1]; - logger('fix_private_photos: found photo ' . $image); - if(stristr($image ,$a->get_baseurl() . '/photo/')) { + logger('fix_private_photos', LOGGER_DEBUG); + $site = substr($a->get_baseurl(),strpos($a->get_baseurl(),'://')); + + if(preg_match("/\[img(.*?)\](.*?)\[\/img\]/is",$s,$matches)) { + $image = $matches[2]; + logger('fix_private_photos: found photo ' . $image, LOGGER_DEBUG); + if(stristr($image , $site . '/photo/')) { + $replace = false; $i = basename($image); $i = str_replace('.jpg','',$i); $x = strpos($i,'-'); @@ -2947,17 +2954,86 @@ function fix_private_photos($s,$uid) { intval($uid) ); if(count($r)) { - logger('replacing photo'); - $s = str_replace($image, 'data:image/jpg;base64,' . base64_encode($r[0]['data']), $s); + + // Check to see if we should replace this photo link with an embedded image + // 1. No need to do so if the photo is public + // 2. If there's a contact-id provided, see if they're in the access list + // for the photo. If so, embed it. + // 3. Otherwise, if we have an item, see if the item permissions match the photo + // permissions, regardless of order but first check to see if they're an exact + // match to save some processing overhead. + + // Currently we only embed one private photo per message so as not to hit import + // size limits at the receiving end. + + // To embed multiples, we would need to parse out the embedded photos on message + // receipt and limit size based only on the text component. Would also need to + // ignore all photos during bbcode translation and item localisation, as these + // will hit internal regex backtrace limits. + + if(has_permissions($r[0])) { + if($cid) { + $recips = enumerate_permissions($r[0]); + if(in_array($cid, $recips)) { + $replace = true; + } + } + elseif($item) { + if(compare_permissions($item,$r[0])) + $replace = true; + } + } + if($replace) { + logger('fix_private_photos: replacing photo', LOGGER_DEBUG); + $s = str_replace($image, 'data:image/jpg;base64,' . base64_encode($r[0]['data']), $s); + logger('fix_private_photos: replaced: ' . $s, LOGGER_DATA); + } } } - logger('fix_private_photos: replaced: ' . $s, LOGGER_DATA); } } return($s); } +function has_permissions($obj) { + if(($obj['allow_cid'] != '') || ($obj['allow_gid'] != '') || ($obj['deny_cid'] != '') || ($obj['deny_gid'] != '')) + return true; + return false; +} + +function compare_permissions($obj1,$obj2) { + // first part is easy. Check that these are exactly the same. + if(($obj1['allow_cid'] == $obj2['allow_cid']) + && ($obj1['allow_gid'] == $obj2['allow_gid']) + && ($obj1['deny_cid'] == $obj2['deny_cid']) + && ($obj1['deny_gid'] == $obj2['deny_gid'])) + return true; + + // This is harder. Parse all the permissions and compare the resulting set. + + $recipients1 = enumerate_permissions($obj1); + $recipients2 = enumerate_permissions($obj2); + sort($recipients1); + sort($recipients2); + if($recipients1 == $recipients2) + return true; + return false; +} + +// returns an array of contact-ids that are allowed to see this object + +function enumerate_permissions($obj) { + require_once('include/group.php'); + $allow_people = expand_acl($obj['allow_cid']); + $allow_groups = expand_groups(expand_acl($obj['allow_gid'])); + $deny_people = expand_acl($obj['deny_cid']); + $deny_groups = expand_groups(expand_acl($obj['deny_gid'])); + $recipients = array_unique(array_merge($allow_people,$allow_groups)); + $deny = array_unique(array_merge($deny_people,$deny_groups)); + $recipients = array_diff($recipients,$deny); + return $recipients; +} function item_getfeedtags($item) { $ret = array(); @@ -3004,13 +3080,20 @@ function item_getfeedattach($item) { function item_expire($uid,$days) { - if((! $uid) || (! $days)) + if((! $uid) || ($days < 1)) return; + // $expire_network_only = save your own wall posts + // and just expire conversations started by others + + $expire_network_only = get_pconfig($uid,'expire','network_only'); + $sql_extra = ((intval($expire_network_only)) ? " AND wall = 0 " : ""); + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `created` < UTC_TIMESTAMP() - INTERVAL %d DAY AND `id` = `parent` + $sql_extra AND `deleted` = 0", intval($uid), intval($days) diff --git a/include/nav.php b/include/nav.php index 2c9c643a9..909ba9b54 100644 --- a/include/nav.php +++ b/include/nav.php @@ -117,7 +117,7 @@ function nav(&$a) { /* only show friend requests for normal pages. Other page types have automatic friendship. */ - if($_SESSION['page_flags'] == PAGE_NORMAL) { + if($_SESSION['page_flags'] == PAGE_NORMAL || $_SESSION['page_flags'] == PAGE_PRVGROUP) { $nav['introductions'] = array('notifications/intros', t('Introductions'), "", t('Friend Requests')); $nav['notifications'] = array('notifications', t('Notifications'), "", t('Notifications')); $nav['notifications']['all']=array('notifications/system', t('See all notifications'), "", ""); diff --git a/include/notifier.php b/include/notifier.php index cb4fb2a31..070e7a436 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -345,7 +345,7 @@ function notifier_run($argv, $argc){ if($mail) { $public_message = false; // mail is not public - $body = fix_private_photos($item['body'],$owner['uid']); + $body = fix_private_photos($item['body'],$owner['uid'],null,$message[0]['contact-id']); $atom .= replace_macros($mail_template, array( '$name' => xmlify($owner['name']), diff --git a/include/profile_advanced.php b/include/profile_advanced.php index bb9850cd0..8c2acd8e7 100644 --- a/include/profile_advanced.php +++ b/include/profile_advanced.php @@ -25,8 +25,8 @@ function advanced_profile(&$a) { $val = ((intval($a->profile['dob'])) ? day_translate(datetime_convert('UTC','UTC',$a->profile['dob'] . ' 00:00 +00:00',$year_bd_format)) - : day_translate(datetime_convert('UTC','UTC','2001-' . substr($a->profile['dob'],6) . ' 00:00 +00:00',$short_bd_format))); - + : day_translate(datetime_convert('UTC','UTC','2001-' . substr($a->profile['dob'],5) . ' 00:00 +00:00',$short_bd_format))); + $profile['birthday'] = array( t('Birthday:'), $val); } diff --git a/include/profile_selectors.php b/include/profile_selectors.php index 4700bb96f..8d29fd099 100644 --- a/include/profile_selectors.php +++ b/include/profile_selectors.php @@ -5,6 +5,8 @@ function gender_selector($current="",$suffix="") { $o = ''; $select = array('', t('Male'), t('Female'), t('Currently Male'), t('Currently Female'), t('Mostly Male'), t('Mostly Female'), t('Transgender'), t('Intersex'), t('Transsexual'), t('Hermaphrodite'), t('Neuter'), t('Non-specific'), t('Other'), t('Undecided')); + call_hooks('gender_selector', $select); + $o .= "<select name=\"gender$suffix\" id=\"gender-select$suffix\" size=\"1\" >"; foreach($select as $selection) { if($selection !== 'NOTRANSLATION') { @@ -20,6 +22,9 @@ function sexpref_selector($current="",$suffix="") { $o = ''; $select = array('', t('Males'), t('Females'), t('Gay'), t('Lesbian'), t('No Preference'), t('Bisexual'), t('Autosexual'), t('Abstinent'), t('Virgin'), t('Deviant'), t('Fetish'), t('Oodles'), t('Nonsexual')); + + call_hooks('sexpref_selector', $select); + $o .= "<select name=\"sexual$suffix\" id=\"sexual-select$suffix\" size=\"1\" >"; foreach($select as $selection) { if($selection !== 'NOTRANSLATION') { @@ -36,6 +41,8 @@ function marital_selector($current="",$suffix="") { $o = ''; $select = array('', t('Single'), t('Lonely'), t('Available'), t('Unavailable'), t('Has crush'), t('Infatuated'), t('Dating'), t('Unfaithful'), t('Sex Addict'), t('Friends'), t('Friends/Benefits'), t('Casual'), t('Engaged'), t('Married'), t('Imaginarily married'), t('Partners'), t('Cohabiting'), t('Common law'), t('Happy'), t('Not looking'), t('Swinger'), t('Betrayed'), t('Separated'), t('Unstable'), t('Divorced'), t('Imaginarily divorced'), t('Widowed'), t('Uncertain'), t('It\'s complicated'), t('Don\'t care'), t('Ask me') ); + call_hooks('marital_selector', $select); + $o .= "<select name=\"marital\" id=\"marital-select\" size=\"1\" >"; foreach($select as $selection) { if($selection !== 'NOTRANSLATION') { diff --git a/include/text.php b/include/text.php index d6a9ef5d3..376ac473d 100644 --- a/include/text.php +++ b/include/text.php @@ -742,6 +742,8 @@ function smilies($s, $sample = false) { ':homebrew', ':coffee', ':facepalm', + ':like', + ':dislike', '~friendika', '~friendica' @@ -778,6 +780,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/like.gif" alt=":like" />', + '<img src="' . $a->get_baseurl() . '/images/dislike.gif" alt=":dislike" />', '<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>' ); diff --git a/include/user.php b/include/user.php new file mode 100644 index 000000000..75a91b096 --- /dev/null +++ b/include/user.php @@ -0,0 +1,325 @@ +<?php + +require_once('include/config.php'); +require_once('include/network.php'); +require_once('include/plugin.php'); +require_once('include/text.php'); +require_once('include/pgettext.php'); +require_once('include/datetime.php'); + +function create_user($arr) { + + // Required: { username, nickname, email } or { openid_url } + + $a = get_app(); + $result = array('success' => false, 'user' => null, 'password' => '', 'message' => ''); + + $using_invites = get_config('system','invitation_only'); + $num_invites = get_config('system','number_invites'); + + + $invite_id = ((x($arr,'invite_id')) ? notags(trim($arr['invite_id'])) : ''); + $username = ((x($arr,'username')) ? notags(trim($arr['username'])) : ''); + $nickname = ((x($arr,'nickname')) ? notags(trim($arr['nickname'])) : ''); + $email = ((x($arr,'email')) ? notags(trim($arr['email'])) : ''); + $openid_url = ((x($arr,'openid_url')) ? notags(trim($arr['openid_url'])) : ''); + $photo = ((x($arr,'photo')) ? notags(trim($arr['photo'])) : ''); + $publish = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0); + $password = ((x($arr,'password')) ? trim($arr['password']) : ''); + + $netpublish = ((strlen(get_config('system','directory_submit_url'))) ? $publish : 0); + + $tmp_str = $openid_url; + + if($using_invites) { + if(! $invite_id) { + $result['message'] .= t('An invitation is required.') . EOL; + return $result; + } + $r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_id)); + if(! results($r)) { + $result['message'] .= t('Invitation could not be verified.') . EOL; + return $result; + } + } + + if((! x($username)) || (! x($email)) || (! x($nickname))) { + if($openid_url) { + if(! validate_url($tmp_str)) { + $result['message'] .= t('Invalid OpenID url') . EOL; + return $result; + } + $_SESSION['register'] = 1; + $_SESSION['openid'] = $openid_url; + require_once('library/openid.php'); + $openid = new LightOpenID; + $openid->identity = $openid_url; + $openid->returnUrl = $a->get_baseurl() . '/openid'; + $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson'); + $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default'); + goaway($openid->authUrl()); + // NOTREACHED + } + + notice( t('Please enter the required information.') . EOL ); + return; + } + + if(! validate_url($tmp_str)) + $openid_url = ''; + + + $err = ''; + + // collapse multiple spaces in name + $username = preg_replace('/ +/',' ',$username); + + if(mb_strlen($username) > 48) + $result['message'] .= t('Please use a shorter name.') . EOL; + if(mb_strlen($username) < 3) + $result['message'] .= t('Name too short.') . EOL; + + // I don't really like having this rule, but it cuts down + // on the number of auto-registrations by Russian spammers + + // Using preg_match was completely unreliable, due to mixed UTF-8 regex support + // $no_utf = get_config('system','no_utf'); + // $pat = (($no_utf) ? '/^[a-zA-Z]* [a-zA-Z]*$/' : '/^\p{L}* \p{L}*$/u' ); + + // So now we are just looking for a space in the full name. + + $loose_reg = get_config('system','no_regfullname'); + if(! $loose_reg) { + $username = mb_convert_case($username,MB_CASE_TITLE,'UTF-8'); + if(! strpos($username,' ')) + $result['message'] .= t("That doesn't appear to be your full \x28First Last\x29 name.") . EOL; + } + + + if(! allowed_email($email)) + $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL; + + if((! valid_email($email)) || (! validate_email($email))) + $result['message'] .= t('Not a valid email address.') . EOL; + + // Disallow somebody creating an account using openid that uses the admin email address, + // since openid bypasses email verification. We'll allow it if there is not yet an admin account. + + if((x($a->config,'admin_email')) && (strcasecmp($email,$a->config['admin_email']) == 0) && strlen($openid_url)) { + $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1", + dbesc($email) + ); + if(count($r)) + $result['message'] .= t('Cannot use that email.') . EOL; + } + + $nickname = $arr['nickname'] = strtolower($nickname); + + if(! preg_match("/^[a-z][a-z0-9\-\_]*$/",$nickname)) + $result['message'] .= t('Your "nickname" can only contain "a-z", "0-9", "-", and "_", and must also begin with a letter.') . EOL; + $r = q("SELECT `uid` FROM `user` + WHERE `nickname` = '%s' LIMIT 1", + dbesc($nickname) + ); + if(count($r)) + $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL; + + // Check deleted accounts that had this nickname. Doesn't matter to us, + // but could be a security issue for federated platforms. + + $r = q("SELECT * FROM `userd` + WHERE `username` = '%s' LIMIT 1", + dbesc($nickname) + ); + if(count($r)) + $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL; + + if(strlen($result['message'])) { + return $result; + } + + $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999)); + $new_password_encoded = hash('whirlpool',$new_password); + + $result['password'] = $new_password; + + require_once('include/crypto.php'); + + $keys = new_keypair(1024); + + if($keys === false) { + $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL; + return $result; + } + + $prvkey = $keys['prvkey']; + $pubkey = $keys['pubkey']; + + /** + * + * Create another keypair for signing/verifying + * salmon protocol messages. We have to use a slightly + * less robust key because this won't be using openssl + * but the phpseclib. Since it is PHP interpreted code + * it is not nearly as efficient, and the larger keys + * will take several minutes each to process. + * + */ + + $sres = new_keypair(512); + $sprvkey = $sres['prvkey']; + $spubkey = $sres['pubkey']; + + $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`, + `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone` ) + VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC' )", + dbesc(generate_user_guid()), + dbesc($username), + dbesc($new_password_encoded), + dbesc($email), + dbesc($openid_url), + dbesc($nickname), + dbesc($pubkey), + dbesc($prvkey), + dbesc($spubkey), + dbesc($sprvkey), + dbesc(datetime_convert()), + intval($verified), + intval($blocked) + ); + + if($r) { + $r = q("SELECT * FROM `user` + WHERE `username` = '%s' AND `password` = '%s' LIMIT 1", + dbesc($username), + dbesc($new_password_encoded) + ); + if($r !== false && count($r)) { + $u = $r[0]; + $newuid = intval($r[0]['uid']); + } + } + else { + $result['message'] .= t('An error occurred during registration. Please try again.') . EOL ; + return $result; + } + + /** + * if somebody clicked submit twice very quickly, they could end up with two accounts + * due to race condition. Remove this one. + */ + + $r = q("SELECT `uid` FROM `user` + WHERE `nickname` = '%s' ", + dbesc($nickname) + ); + if((count($r) > 1) && $newuid) { + $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL; + q("DELETE FROM `user` WHERE `uid` = %d LIMIT 1", + intval($newuid) + ); + return $result; + } + + if(x($newuid) !== false) { + $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` ) + VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ", + intval($newuid), + t('default'), + 1, + dbesc($username), + dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"), + dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"), + intval($publish), + intval($netpublish) + + ); + if($r === false) { + $result['message'] .= t('An error occurred creating your default profile. Please try again.') . EOL; + // Start fresh next time. + $r = q("DELETE FROM `user` WHERE `uid` = %d", + intval($newuid)); + return $result; + } + $r = q("INSERT INTO `contact` ( `uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`, + `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness` ) + VALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0 ) ", + intval($newuid), + datetime_convert(), + dbesc($username), + dbesc($nickname), + dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"), + dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"), + dbesc($a->get_baseurl() . "/photo/micro/{$newuid}.jpg"), + dbesc($a->get_baseurl() . "/profile/$nickname"), + dbesc(normalise_link($a->get_baseurl() . "/profile/$nickname")), + dbesc($a->get_baseurl() . "/dfrn_request/$nickname"), + dbesc($a->get_baseurl() . "/dfrn_notify/$nickname"), + dbesc($a->get_baseurl() . "/dfrn_poll/$nickname"), + dbesc($a->get_baseurl() . "/dfrn_confirm/$nickname"), + dbesc($a->get_baseurl() . "/poco/$nickname"), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(datetime_convert()) + ); + + // Create a group with no members. This allows somebody to use it + // right away as a default group for new contacts. + + require_once('include/group.php'); + group_add($newuid, t('Friends')); + + } + + // if we have no OpenID photo try to look up an avatar + if(! strlen($photo)) + $photo = avatar_img($email); + + // unless there is no avatar-plugin loaded + if(strlen($photo)) { + require_once('include/Photo.php'); + $photo_failure = false; + + $filename = basename($photo); + $img_str = fetch_url($photo,true); + $img = new Photo($img_str); + if($img->is_valid()) { + + $img->scaleImageSquare(175); + + $hash = photo_new_resource(); + + $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 ); + + if($r === false) + $photo_failure = true; + + $img->scaleImage(80); + + $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 ); + + if($r === false) + $photo_failure = true; + + $img->scaleImage(48); + + $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 ); + + if($r === false) + $photo_failure = true; + + if(! $photo_failure) { + q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ", + dbesc($hash) + ); + } + } + } + + call_hooks('register_account', $newuid); + + $result['success'] = true; + $result['user'] = $u; + return $result; + +}
\ No newline at end of file |