This commit is contained in:
marijus 2014-08-21 13:20:49 +02:00
commit 1a3be50451
14 changed files with 360 additions and 469 deletions

View File

@ -358,11 +358,6 @@ define ( 'MAX_LIKERS', 10);
define ( 'ZCURL_TIMEOUT' , (-1)); define ( 'ZCURL_TIMEOUT' , (-1));
/**
* Hours before chat lines are deleted
*/
define ( 'MAX_CHATROOM_HOURS' , 36);
/** /**
* email notification options * email notification options

View File

@ -128,8 +128,10 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) {
} }
} }
if(intval($x[0]['cr_expire'])) if(intval($x[0]['cr_expire'])) {
$r = q("delete from chat where created < UTC_TIMESTAMP() - INTERVAL " . intval($x[0]['cr_expire']) . " MINUTE and chat_room = " . intval($x[0]['cr_id'])); $sql = "delete from chat where created < UTC_TIMESTAMP() - INTERVAL " . intval($x[0]['cr_expire']) . " MINUTE and chat_room = " . intval($x[0]['cr_id']);
$r = q($sql);
}
$r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1", $r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1",
dbesc($observer_xchan), dbesc($observer_xchan),
@ -153,7 +155,6 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) {
dbesc($client) dbesc($client)
); );
chatroom_flush($room_id,$xchan);
return $r; return $r;
} }
@ -226,21 +227,5 @@ function chat_message($uid,$room_id,$xchan,$text) {
); );
$ret['success'] = true; $ret['success'] = true;
chatroom_flush($room_id,$xchan);
return $ret; return $ret;
} }
/**
* Reduces the number of lines shown in chat by removing those older than MAX_CHATROOM_HOURS
*/
function chatroom_flush($room_id,$xchan) {
$date_limit = date('Y-m-d H:i:s', time() - 3600 * MAX_CHATROOM_HOURS);
$d = q("delete from chat where chat_room = %d and chat_xchan = '%s' and created < '%s'",
intval($room_id),
dbesc($xchan),
datetime_convert('','', $date_limit));
return true;
}

View File

@ -1224,21 +1224,21 @@ function get_profile_elements($x) {
function get_atom_elements($feed,$item) { function get_atom_elements($feed,$item,&$author) {
$best_photo = array(); $best_photo = array();
$res = array(); $res = array();
$author = $item->get_author(); $found_author = $item->get_author();
if($author) { if($found_author) {
$res['author_name'] = unxmlify($author->get_name()); $author['author_name'] = unxmlify($found_author->get_name());
$res['author_link'] = unxmlify($author->get_link()); $author['author_link'] = unxmlify($found_author->get_link());
} }
else { else {
$res['author_name'] = unxmlify($feed->get_title()); $author['author_name'] = unxmlify($feed->get_title());
$res['author_link'] = unxmlify($feed->get_permalink()); $author['author_link'] = unxmlify($feed->get_permalink());
} }
$res['mid'] = unxmlify($item->get_id()); $res['mid'] = unxmlify($item->get_id());
@ -1265,9 +1265,9 @@ function get_atom_elements($feed,$item) {
if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) { if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']; $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
foreach($base as $link) { foreach($base as $link) {
if(!x($res, 'author_photo') || !$res['author_photo']) { if(!x($author, 'author_photo') || ! $author['author_photo']) {
if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
$res['author_photo'] = unxmlify($link['attribs']['']['href']); $author['author_photo'] = unxmlify($link['attribs']['']['href']);
} }
} }
} }
@ -1279,10 +1279,10 @@ function get_atom_elements($feed,$item) {
if($base && count($base)) { if($base && count($base)) {
foreach($base as $link) { foreach($base as $link) {
if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link'])) if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link']))
$res['author_link'] = unxmlify($link['attribs']['']['href']); $author['author_link'] = unxmlify($link['attribs']['']['href']);
if(!x($res, 'author_photo') || !$res['author_photo']) { if(!x($author, 'author_photo') || ! $author['author_photo']) {
if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo') if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
$res['author_photo'] = unxmlify($link['attribs']['']['href']); $author['author_photo'] = unxmlify($link['attribs']['']['href']);
} }
} }
} }
@ -1290,16 +1290,16 @@ function get_atom_elements($feed,$item) {
// No photo/profile-link on the item - look at the feed level // No photo/profile-link on the item - look at the feed level
if((! (x($res,'author_link'))) || (! (x($res,'author_photo')))) { if((! (x($author,'author_link'))) || (! (x($author,'author_photo')))) {
$rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author'); $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) { if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']; $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
foreach($base as $link) { foreach($base as $link) {
if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link'])) if($link['attribs']['']['rel'] === 'alternate' && (! $author['author_link']))
$res['author_link'] = unxmlify($link['attribs']['']['href']); $author['author_link'] = unxmlify($link['attribs']['']['href']);
if(! $res['author_photo']) { if(! $author['author_photo']) {
if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
$res['author_photo'] = unxmlify($link['attribs']['']['href']); $author['author_photo'] = unxmlify($link['attribs']['']['href']);
} }
} }
} }
@ -1312,10 +1312,10 @@ function get_atom_elements($feed,$item) {
if($base && count($base)) { if($base && count($base)) {
foreach($base as $link) { foreach($base as $link) {
if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link'])) if($link['attribs']['']['rel'] === 'alternate' && (! $res['author_link']))
$res['author_link'] = unxmlify($link['attribs']['']['href']); $author['author_link'] = unxmlify($link['attribs']['']['href']);
if(! (x($res,'author_photo'))) { if(! (x($author,'author_photo'))) {
if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo') if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
$res['author_photo'] = unxmlify($link['attribs']['']['href']); $author['author_photo'] = unxmlify($link['attribs']['']['href']);
} }
} }
} }
@ -1340,6 +1340,12 @@ function get_atom_elements($feed,$item) {
$res['body'] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$res['body']); $res['body'] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$res['body']);
// make sure nobody is trying to sneak some html tags by us // make sure nobody is trying to sneak some html tags by us
$res['body'] = notags(base64url_decode($res['body'])); $res['body'] = notags(base64url_decode($res['body']));
// We could probably turn these old Friendica bbcode bookmarks into bookmark tags but we'd have to
// create a term table item for them. For now just make sure they stay as links.
$res['body'] = preg_replace('/\[bookmark(.*?)\](.*?)\[\/bookmark\]','[url$1]$2[/url]',$res['body']);
} }
@ -1419,22 +1425,25 @@ function get_atom_elements($feed,$item) {
$res['edited'] = datetime_convert(); $res['edited'] = datetime_convert();
$rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner'); $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
if(! $rawowner)
$rawowner = $item->get_item_tags(NAMESPACE_ZOT,'owner');
if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']) if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])
$res['owner_name'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']); $author['owner_name'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']);
elseif($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']) elseif($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data'])
$res['owner_name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']); $author['owner_name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']) if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
$res['owner_link'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']); $author['owner_link'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']) elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
$res['owner_link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']); $author['owner_link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) { if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']; $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
foreach($base as $link) { foreach($base as $link) {
if(!x($res, 'owner_photo') || !$res['owner_photo']) { if(!x($author, 'owner_photo') || ! $author['owner_photo']) {
if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
$res['owner_photo'] = unxmlify($link['attribs']['']['href']); $author['owner_photo'] = unxmlify($link['attribs']['']['href']);
} }
} }
} }
@ -1579,39 +1588,11 @@ function get_atom_elements($feed,$item) {
$res['target'] = $obj; $res['target'] = $obj;
} }
// This is some experimental stuff. By now retweets are shown with "RT:"
// But: There is data so that the message could be shown similar to native retweets
// There is some better way to parse this array - but it didn't worked for me.
/*
$child = $item->feed->data["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["feed"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["entry"][0]["child"]["http://activitystrea.ms/spec/1.0/"][object][0]["child"];
if (is_array($child)) {
$message = $child["http://activitystrea.ms/spec/1.0/"]["object"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["content"][0]["data"];
$author = $child[SIMPLEPIE_NAMESPACE_ATOM_10]["author"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10];
$uri = $author["uri"][0]["data"];
$name = $author["name"][0]["data"];
$avatar = @array_shift($author["link"][2]["attribs"]);
$avatar = $avatar["href"];
if (($name != "") and ($uri != "") and ($avatar != "") and ($message != "")) {
$res["owner-name"] = $res["author-name"];
$res["owner-link"] = $res["author-link"];
$res["owner-avatar"] = $res["author-avatar"];
$res["author-name"] = $name;
$res["author-link"] = $uri;
$res["author-avatar"] = $avatar;
$res["body"] = html2bbcode($message);
}
}
*/
$arr = array('feed' => $feed, 'item' => $item, 'result' => $res); $arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
call_hooks('parse_atom', $arr); call_hooks('parse_atom', $arr);
logger('get_atom_elements: ' . print_r($res,true)); logger('get_atom_elements: author: ' . print_r($author,true),LOGGER_DATA);
logger('get_atom_elements: ' . print_r($res,true),LOGGER_DATA);
return $res; return $res;
} }
@ -1621,9 +1602,6 @@ function encode_rel_links($links) {
if(! ((is_array($links)) && (count($links)))) if(! ((is_array($links)) && (count($links))))
return $o; return $o;
//fixme
return '';
foreach($links as $link) { foreach($links as $link) {
$o .= '<link '; $o .= '<link ';
if($link['attribs']['']['rel']) if($link['attribs']['']['rel'])
@ -2374,8 +2352,9 @@ function tag_deliver($uid,$item_id) {
$item = $i[0]; $item = $i[0];
if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK) && ($item['item_flags'] & ITEM_THREAD_TOP) && ($item['edited'] != $item['created'])) { if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK)
// this is an update to a post which was already processed by us and has a second delivery chain && ($item['item_flags'] & ITEM_THREAD_TOP) && ($item['edited'] != $item['created'])) {
// this is an update (edit) to a post which was already processed by us and has a second delivery chain
// Just start the second delivery chain to deliver the updated post // Just start the second delivery chain to deliver the updated post
proc_run('php','include/notifier.php','tgroup',$item['id']); proc_run('php','include/notifier.php','tgroup',$item['id']);
return; return;
@ -2472,78 +2451,14 @@ function tag_deliver($uid,$item_id) {
// This might be a followup (e.g. comment) by the original post author to a tagged forum // This might be a followup (e.g. comment) by the original post author to a tagged forum
// If so setup a second delivery chain // If so setup a second delivery chain
$r = null;
if( ! ($item['item_flags'] & ITEM_THREAD_TOP)) { if( ! ($item['item_flags'] & ITEM_THREAD_TOP)) {
$x = q("select * from item where id = parent and parent = %d and uid = %d limit 1", $x = q("select * from item where id = parent and parent = %d and uid = %d limit 1",
intval($item['parent']), intval($item['parent']),
intval($uid) intval($uid)
); );
if(($x) && ($x[0]['item_flags'] & ITEM_UPLINK)) { if(($x) && ($x[0]['item_flags'] & ITEM_UPLINK)) {
start_delivery_chain($u[0],$item,$item_id,$x[0]);
logger('tag_deliver: creating second delivery chain for comment to tagged post.');
// now change this copy of the post to a forum head message and deliver to all the tgroup members
// also reset all the privacy bits to the forum default permissions
$private = (($u[0]['channel_allow_cid'] || $u[0]['channel_allow_gid'] || $u[0]['channel_deny_cid'] || $u[0]['channel_deny_gid']) ? 1 : 0);
$new_public_policy = map_scope($u[0]['channel_r_stream'],true);
if((! $private) && $new_public_policy)
$private = 1;
$flag_bits = $item['item_flags'] | ITEM_WALL|ITEM_ORIGIN;
// maintain the original source, which will be the original item owner and was stored in source_xchan
// when we created the delivery fork
$r = q("update item set source_xchan = '%s' where id = %d limit 1",
dbesc($x[0]['source_xchan']),
intval($item_id)
);
$title = $item['title'];
$body = $item['body'];
if($private) {
if(!($flag_bits & ITEM_OBSCURED)) {
$key = get_config('system','pubkey');
$flag_bits = $flag_bits|ITEM_OBSCURED;
$title = json_encode(aes_encapsulate($title,$key));
$body = json_encode(aes_encapsulate($body,$key));
}
}
else {
if($flag_bits & ITEM_OBSCURED) {
$key = get_config('system','prvkey');
$flag_bits = $flag_bits ^ ITEM_OBSCURED;
$title = json_encode(aes_unencapsulate($title,$key));
$body = json_encode(aes_unencapsulate($body,$key));
}
}
$r = q("update item set item_flags = %d, owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s',
deny_cid = '%s', deny_gid = '%s', item_private = %d, public_policy = '%s', comment_policy = '%s', title = '%s', body = '%s' where id = %d limit 1",
intval($flag_bits),
dbesc($u[0]['channel_hash']),
dbesc($u[0]['channel_allow_cid']),
dbesc($u[0]['channel_allow_gid']),
dbesc($u[0]['channel_deny_cid']),
dbesc($u[0]['channel_deny_gid']),
intval($private),
dbesc($new_public_policy),
dbesc(map_scope($u[0]['channel_w_comment'])),
dbesc($title),
dbesc($body),
intval($item_id)
);
if($r)
proc_run('php','include/notifier.php','tgroup',$item_id);
else
logger('tag_deliver: failed to update item');
} }
} }
@ -2577,8 +2492,6 @@ function tag_deliver($uid,$item_id) {
intval($item_id) intval($item_id)
); );
// At this point we've determined that the person receiving this post was mentioned in it or it is a union. // At this point we've determined that the person receiving this post was mentioned in it or it is a union.
// Now let's check if this mention was inside a reshare so we don't spam a forum // Now let's check if this mention was inside a reshare so we don't spam a forum
// If it's private we may have to unobscure it momentarily so that we can parse it. // If it's private we may have to unobscure it momentarily so that we can parse it.
@ -2650,81 +2563,20 @@ function tag_deliver($uid,$item_id) {
return; return;
} }
// tgroup delivery - setup a second delivery chain // tgroup delivery - setup a second delivery chain
// prevent delivery looping - only proceed // prevent delivery looping - only proceed
// if the message originated elsewhere and is a top-level post // if the message originated elsewhere and is a top-level post
if(($item['item_flags'] & ITEM_WALL) || ($item['item_flags'] & ITEM_ORIGIN) || (!($item['item_flags'] & ITEM_THREAD_TOP)) || ($item['id'] != $item['parent'])) { if(($item['item_flags'] & ITEM_WALL)
|| ($item['item_flags'] & ITEM_ORIGIN)
|| (!($item['item_flags'] & ITEM_THREAD_TOP))
|| ($item['id'] != $item['parent'])) {
logger('tag_deliver: item was local or a comment. rejected.'); logger('tag_deliver: item was local or a comment. rejected.');
return; return;
} }
/**
* At this point we're committed to setting up a second delivery chain. We just have to mangle some bits first.
*/
logger('tag_deliver: creating second delivery chain.'); logger('tag_deliver: creating second delivery chain.');
start_delivery_chain($u[0],$item,$item_id,null);
// now change this copy of the post to a forum head message and deliver to all the tgroup members
// also reset all the privacy bits to the forum default permissions
$private = (($u[0]['channel_allow_cid'] || $u[0]['channel_allow_gid'] || $u[0]['channel_deny_cid'] || $u[0]['channel_deny_gid']) ? 1 : 0);
$new_public_policy = map_scope($u[0]['channel_r_stream'],true);
if((! $private) && $new_public_policy)
$private = 1;
$flag_bits = $item['item_flags'] | ITEM_WALL|ITEM_ORIGIN|ITEM_UPLINK;
// preserve the source
$r = q("update item set source_xchan = owner_xchan where id = %d limit 1",
intval($item_id)
);
// make sure encryption matches the new scope
$title = $item['title'];
$body = $item['body'];
if($private) {
if(!($flag_bits & ITEM_OBSCURED)) {
$key = get_config('system','pubkey');
$flag_bits = $flag_bits|ITEM_OBSCURED;
$title = json_encode(aes_encapsulate($title,$key));
$body = json_encode(aes_encapsulate($body,$key));
}
}
else {
if($flag_bits & ITEM_OBSCURED) {
$key = get_config('system','prvkey');
$flag_bits = $flag_bits ^ ITEM_OBSCURED;
$title = json_encode(aes_unencapsulate($title,$key));
$body = json_encode(aes_unencapsulate($body,$key));
}
}
$r = q("update item set item_flags = %d, owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s',
deny_cid = '%s', deny_gid = '%s', item_private = %d, public_policy = '%s', comment_policy = '%s', title = '%s', body = '%s' where id = %d limit 1",
intval($flag_bits),
dbesc($u[0]['channel_hash']),
dbesc($u[0]['channel_allow_cid']),
dbesc($u[0]['channel_allow_gid']),
dbesc($u[0]['channel_deny_cid']),
dbesc($u[0]['channel_deny_gid']),
intval($private),
dbesc($new_public_policy),
dbesc(map_scope($u[0]['channel_w_comment'])),
dbesc($title),
dbesc($body),
intval($item_id)
);
if($r)
proc_run('php','include/notifier.php','tgroup',$item_id);
else
logger('tag_deliver: failed to update item');
} }
@ -2808,6 +2660,90 @@ function tgroup_check($uid,$item) {
} }
/**
* Sourced and tag-delivered posts are re-targetted for delivery to the connections of the channel
* receiving the post. This starts the second delivery chain, by resetting permissions and ensuring
* that ITEM_UPLINK is set on the parent post, and storing the current owner_xchan as the source_xchan.
* We'll become the new owner. If called without $parent, this *is* the parent post.
*/
function start_delivery_chain($channel,$item,$item_id,$parent) {
// Change this copy of the post to a forum head message and deliver to all the tgroup members
// also reset all the privacy bits to the forum default permissions
$private = (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0);
$new_public_policy = map_scope($channel['channel_r_stream'],true);
if((! $private) && $new_public_policy)
$private = 1;
$flag_bits = $item['item_flags'] | ITEM_WALL|ITEM_ORIGIN;
// maintain the original source, which will be the original item owner and was stored in source_xchan
// when we created the delivery fork
if($parent) {
$r = q("update item set source_xchan = '%s' where id = %d limit 1",
dbesc($parent['source_xchan']),
intval($item_id)
);
}
else {
$flag_bits = $flag_bits | ITEM_UPLINK;
$r = q("update item set source_xchan = owner_xchan where id = %d limit 1",
intval($item_id)
);
}
$title = $item['title'];
$body = $item['body'];
if($private) {
if(!($flag_bits & ITEM_OBSCURED)) {
$key = get_config('system','pubkey');
$flag_bits = $flag_bits|ITEM_OBSCURED;
$title = json_encode(aes_encapsulate($title,$key));
$body = json_encode(aes_encapsulate($body,$key));
}
}
else {
if($flag_bits & ITEM_OBSCURED) {
$key = get_config('system','prvkey');
$flag_bits = $flag_bits ^ ITEM_OBSCURED;
$title = json_encode(aes_unencapsulate($title,$key));
$body = json_encode(aes_unencapsulate($body,$key));
}
}
$r = q("update item set item_flags = %d, owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s',
deny_cid = '%s', deny_gid = '%s', item_private = %d, public_policy = '%s', comment_policy = '%s', title = '%s', body = '%s' where id = %d limit 1",
intval($flag_bits),
dbesc($channel['channel_hash']),
dbesc($channel['channel_allow_cid']),
dbesc($channel['channel_allow_gid']),
dbesc($channel['channel_deny_cid']),
dbesc($channel['channel_deny_gid']),
intval($private),
dbesc($new_public_policy),
dbesc(map_scope($channel['channel_w_comment'])),
dbesc($title),
dbesc($body),
intval($item_id)
);
if($r)
proc_run('php','include/notifier.php','tgroup',$item_id);
else
logger('start_delivery_chain: failed to update item');
return;
}
/** /**
* @function check_item_source($uid,$item) * @function check_item_source($uid,$item)
@ -3014,9 +2950,6 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) {
return; return;
} }
// Want to see this work as a content source for the matrix?
// Read this: https://github.com/friendica/red/wiki/Service_Federation
$feed = new SimplePie(); $feed = new SimplePie();
$feed->set_raw_data($xml); $feed->set_raw_data($xml);
$feed->init(); $feed->init();
@ -3095,14 +3028,15 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) {
// Have we seen it? If not, import it. // Have we seen it? If not, import it.
$item_id = $item->get_id(); $item_id = $item->get_id();
$datarray = get_atom_elements($feed,$item); $author = array();
$datarray = get_atom_elements($feed,$item,$author);
if(! x($datarray,'author_name')) if(! x($author,'author_name'))
$datarray['author_name'] = $contact['xchan_name']; $author['author_name'] = $contact['xchan_name'];
if(! x($datarray,'author_link')) if(! x($author,'author_link'))
$datarray['author_link'] = $contact['xchan_url']; $author['author_link'] = $contact['xchan_url'];
if(! x($datarray,'author_photo')) if(! x($author,'author_photo'))
$datarray['author_photo'] = $contact['xchan_photo_m']; $author['author_photo'] = $contact['xchan_photo_m'];
$r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1",
dbesc($item_id), dbesc($item_id),
@ -3126,6 +3060,8 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) {
$datarray['parent_mid'] = $parent_mid; $datarray['parent_mid'] = $parent_mid;
$datarray['uid'] = $importer['channel_id']; $datarray['uid'] = $importer['channel_id'];
//FIXME
$datarray['author_xchan'] = $contact['xchan_hash']; $datarray['author_xchan'] = $contact['xchan_hash'];
// FIXME pull out the author and owner // FIXME pull out the author and owner
@ -3143,20 +3079,20 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) {
// Head post of a conversation. Have we seen it? If not, import it. // Head post of a conversation. Have we seen it? If not, import it.
$item_id = $item->get_id(); $item_id = $item->get_id();
$author = array();
$datarray = get_atom_elements($feed,$item); $datarray = get_atom_elements($feed,$item,$author);
if(is_array($contact)) { if(is_array($contact)) {
if(! x($datarray,'author_name')) if(! x($author,'author_name'))
$datarray['author_name'] = $contact['xchan_name']; $author['author_name'] = $contact['xchan_name'];
if(! x($datarray,'author_link')) if(! x($author,'author_link'))
$datarray['author_link'] = $contact['xchan_url']; $author['author_link'] = $contact['xchan_url'];
if(! x($datarray,'author_photo')) if(! x($author,'author_photo'))
$datarray['author_photo'] = $contact['xchan_photo_m']; $author['author_photo'] = $contact['xchan_photo_m'];
} }
if((! x($datarray,'author_name')) || (! x($datarray,'author_link'))) { if((! x($author,'author_name')) || (! x($author,'author_link'))) {
logger('consume_feed: no author information! ' . print_r($datarray,true)); logger('consume_feed: no author information! ' . print_r($author,true));
continue; continue;
} }
@ -3185,14 +3121,15 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) {
$datarray['parent_mid'] = $item_id; $datarray['parent_mid'] = $item_id;
$datarray['uid'] = $importer['channel_id']; $datarray['uid'] = $importer['channel_id'];
//FIXME
$datarray['author_xchan'] = $contact['author_xchan']; $datarray['author_xchan'] = $contact['author_xchan'];
// if(! link_compare($datarray['owner_link'],$contact['xchan_url'])) { if(! link_compare($author['owner_link'],$contact['xchan_url'])) {
// logger('consume_feed: Correcting item owner.', LOGGER_DEBUG); logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
// $datarray['owner-name'] = $contact['name']; $author['owner-name'] = $contact['name'];
// $datarray['owner-link'] = $contact['url']; $author['owner-link'] = $contact['url'];
// $datarray['owner-avatar'] = $contact['thumb']; $author['owner-avatar'] = $contact['thumb'];
// } }
logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA); logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA);

View File

@ -965,4 +965,168 @@ logger('fetch_xrd_links: ' . $url);
logger('fetch_xrd_links: ' . print_r($links,true), LOGGER_DATA); logger('fetch_xrd_links: ' . print_r($links,true), LOGGER_DATA);
return $links; return $links;
} }
function scrape_vcard($url) {
$a = get_app();
$ret = array();
logger('scrape_vcard: url=' . $url);
$x = z_fetch_url($url);
if(! $x['success'])
return $ret;
$s = $x['body'];
if(! $s)
return $ret;
$headers = $x['header'];
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
// don't try and run feeds through the html5 parser
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml'))))
return ret;
}
}
try {
$dom = HTML5_Parser::parse($s);
} catch (DOMException $e) {
logger('scrape_vcard: parse error: ' . $e);
}
if(! $dom)
return $ret;
// Pull out hCard profile elements
$largest_photo = 0;
$items = $dom->getElementsByTagName('*');
foreach($items as $item) {
if(attribute_contains($item->getAttribute('class'), 'vcard')) {
$level2 = $item->getElementsByTagName('*');
foreach($level2 as $x) {
if(attribute_contains($x->getAttribute('class'),'fn'))
$ret['fn'] = $x->textContent;
if((attribute_contains($x->getAttribute('class'),'photo'))
|| (attribute_contains($x->getAttribute('class'),'avatar'))) {
$size = intval($x->getAttribute('width'));
if(($size > $largest_photo) || (! $largest_photo)) {
$ret['photo'] = $x->getAttribute('src');
$largest_photo = $size;
}
}
if((attribute_contains($x->getAttribute('class'),'nickname'))
|| (attribute_contains($x->getAttribute('class'),'uid'))) {
$ret['nick'] = $x->textContent;
}
}
}
}
return $ret;
}
function scrape_feed($url) {
$a = get_app();
$ret = array();
$level = 0;
$x = z_fetch_url($url,false,$level,array('novalidate' => true));
if(! $x['success'])
return $ret;
$headers = $x['header'];
$code = $x['return_code'];
$s = $x['body'];
logger('scrape_feed: returns: ' . $code . ' headers=' . $headers, LOGGER_DEBUG);
if(! $s) {
logger('scrape_feed: no data returned for ' . $url);
return $ret;
}
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
if(stristr($line,'content-type:')) {
if(stristr($line,'application/atom+xml') || stristr($s,'<feed')) {
$ret['feed_atom'] = $url;
return $ret;
}
if(stristr($line,'application/rss+xml') || stristr($s,'<rss')) {
$ret['feed_rss'] = $url;
return $ret;
}
}
}
// perhaps an RSS version 1 feed with a generic or incorrect content-type?
if(stristr($s,'</item>')) {
$ret['feed_rss'] = $url;
return $ret;
}
}
try {
$dom = HTML5_Parser::parse($s);
} catch (DOMException $e) {
logger('scrape_feed: parse error: ' . $e);
}
if(! $dom) {
logger('scrape_feed: failed to parse.');
return $ret;
}
$head = $dom->getElementsByTagName('base');
if($head) {
foreach($head as $head0) {
$basename = $head0->getAttribute('href');
break;
}
}
if(! $basename)
$basename = implode('/', array_slice(explode('/',$url),0,3)) . '/';
$items = $dom->getElementsByTagName('link');
// get Atom/RSS link elements, take the first one of either.
if($items) {
foreach($items as $item) {
$x = $item->getAttribute('rel');
if(($x === 'alternate') && ($item->getAttribute('type') === 'application/atom+xml')) {
if(! x($ret,'feed_atom'))
$ret['feed_atom'] = $item->getAttribute('href');
}
if(($x === 'alternate') && ($item->getAttribute('type') === 'application/rss+xml')) {
if(! x($ret,'feed_rss'))
$ret['feed_rss'] = $item->getAttribute('href');
}
}
}
// Drupal and perhaps others only provide relative URL's. Turn them into absolute.
if(x($ret,'feed_atom') && (! strstr($ret['feed_atom'],'://')))
$ret['feed_atom'] = $basename . $ret['feed_atom'];
if(x($ret,'feed_rss') && (! strstr($ret['feed_rss'],'://')))
$ret['feed_rss'] = $basename . $ret['feed_rss'];
return $ret;
}

View File

@ -265,50 +265,10 @@ function admin_page_site_post(&$a){
$delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0); $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0);
$poll_interval = ((x($_POST,'poll_interval'))? intval(trim($_POST['poll_interval'])) : 0); $poll_interval = ((x($_POST,'poll_interval'))? intval(trim($_POST['poll_interval'])) : 0);
$maxloadavg = ((x($_POST,'maxloadavg'))? intval(trim($_POST['maxloadavg'])) : 50); $maxloadavg = ((x($_POST,'maxloadavg'))? intval(trim($_POST['maxloadavg'])) : 50);
// $ssl_policy = ((x($_POST,'ssl_policy')) ? intval($_POST['ssl_policy']) : 0); $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
/*
if($ssl_policy != intval(get_config('system','ssl_policy'))) {
if($ssl_policy == SSL_POLICY_FULL) { set_config('system','feed_contacts',$feed_contacts);
q("update `contact` set
`url` = replace(`url` , 'http:' , 'https:'),
`photo` = replace(`photo` , 'http:' , 'https:'),
`thumb` = replace(`thumb` , 'http:' , 'https:'),
`micro` = replace(`micro` , 'http:' , 'https:'),
`request` = replace(`request`, 'http:' , 'https:'),
`notify` = replace(`notify` , 'http:' , 'https:'),
`poll` = replace(`poll` , 'http:' , 'https:'),
`confirm` = replace(`confirm`, 'http:' , 'https:'),
`poco` = replace(`poco` , 'http:' , 'https:')
where `self` = 1"
);
q("update `profile` set
`photo` = replace(`photo` , 'http:' , 'https:'),
`thumb` = replace(`thumb` , 'http:' , 'https:')
where 1 "
);
}
elseif($ssl_policy == SSL_POLICY_SELFSIGN) {
q("update `contact` set
`url` = replace(`url` , 'https:' , 'http:'),
`photo` = replace(`photo` , 'https:' , 'http:'),
`thumb` = replace(`thumb` , 'https:' , 'http:'),
`micro` = replace(`micro` , 'https:' , 'http:'),
`request` = replace(`request`, 'https:' , 'http:'),
`notify` = replace(`notify` , 'https:' , 'http:'),
`poll` = replace(`poll` , 'https:' , 'http:'),
`confirm` = replace(`confirm`, 'https:' , 'http:'),
`poco` = replace(`poco` , 'https:' , 'http:')
where `self` = 1"
);
q("update `profile` set
`photo` = replace(`photo` , 'https:' , 'http:'),
`thumb` = replace(`thumb` , 'https:' , 'http:')
where 1 "
);
}
}
*/
// set_config('system','ssl_policy',$ssl_policy);
set_config('system','delivery_interval',$delivery_interval); set_config('system','delivery_interval',$delivery_interval);
set_config('system','poll_interval',$poll_interval); set_config('system','poll_interval',$poll_interval);
set_config('system','maxloadavg',$maxloadavg); set_config('system','maxloadavg',$maxloadavg);
@ -464,7 +424,7 @@ function admin_page_site(&$a) {
'$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile), '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
'$theme_accessibility' => array('theme_accessibility', t("Accessibility system theme"), get_config('system','accessibility_theme'), t("Accessibility theme"), $theme_choices_accessibility), '$theme_accessibility' => array('theme_accessibility', t("Accessibility system theme"), get_config('system','accessibility_theme'), t("Accessibility theme"), $theme_choices_accessibility),
'$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")), '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
// '$ssl_policy' => array('ssl_policy', t("SSL link policy"), (string) intval(get_config('system','ssl_policy')), t("Determines whether generated links should be forced to use SSL"), $ssl_choices), '$feed_contacts' => array('feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)')),
'$maximagesize' => array('maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")), '$maximagesize' => array('maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")),
'$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices), '$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
'$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices), '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices),

View File

@ -154,7 +154,7 @@ function dirsearch_content(&$a) {
else { else {
$qlimit = " LIMIT " . intval($startrec) . " , " . intval($perpage); $qlimit = " LIMIT " . intval($startrec) . " , " . intval($perpage);
if($return_total) { if($return_total) {
$r = q("SELECT COUNT(xchan_hash) AS `total` FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and not ( xchan_flags & %d) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) $safesql ", $r = q("SELECT COUNT(xchan_hash) AS `total` FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot' and not ( xchan_flags & %d) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) $safesql ",
intval(XCHAN_FLAGS_HIDDEN), intval(XCHAN_FLAGS_HIDDEN),
intval(XCHAN_FLAGS_ORPHAN), intval(XCHAN_FLAGS_ORPHAN),
intval(XCHAN_FLAGS_DELETED) intval(XCHAN_FLAGS_DELETED)
@ -199,7 +199,7 @@ function dirsearch_content(&$a) {
json_return_and_die($spkt); json_return_and_die($spkt);
} }
else { else {
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash where ( $logic $sql_extra ) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) $safesql $order $qlimit ", $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash where ( $logic $sql_extra ) and xchan_network = 'zot' and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) and not ( xchan_flags & %d ) $safesql $order $qlimit ",
intval(XCHAN_FLAGS_HIDDEN), intval(XCHAN_FLAGS_HIDDEN),
intval(XCHAN_FLAGS_ORPHAN), intval(XCHAN_FLAGS_ORPHAN),
intval(XCHAN_FLAGS_DELETED) intval(XCHAN_FLAGS_DELETED)

View File

@ -1,87 +0,0 @@
<?php
function frphotos_init(&$a) {
if(! local_user())
return;
if(intval(get_pconfig(local_user(),'frphotos','complete')))
return;
$channel = $a->get_channel();
$fr_server = $_REQUEST['fr_server'];
$fr_username = $_REQUEST['fr_username'];
$fr_password = $_REQUEST['fr_password'];
$cookies = 'store/[data]/frphoto_cookie_' . $channel['channel_address'];
if($fr_server && $fr_username && $fr_password) {
$ch = curl_init($fr_server . '/api/friendica/photos/list');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookies);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookies);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $fr_username . ':' . $fr_password);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'RedMatrix');
$output = curl_exec($ch);
curl_close($ch);
$j = json_decode($output,true);
// echo print_r($j,true);
$total = 0;
if(count($j)) {
foreach($j as $jj) {
$r = q("select uid from photo where resource_id = '%s' and uid = %d limit 1",
dbesc($jj),
intval($channel['channel_id'])
);
if($r)
continue;
$total ++;
proc_run('php','util/frphotohelper.php',$jj, $channel['channel_address'], urlencode($fr_server));
sleep(3);
}
}
if($total) {
set_pconfig(local_user(),'frphotos','complete','1');
}
@unlink($cookies);
goaway(z_root() . '/photos/' . $channel['channel_address']);
}
}
function frphotos_content(&$a) {
if(! local_user()) {
notice( t('Permission denied') . EOL);
return;
}
if(intval(get_pconfig(local_user(),'frphotos','complete'))) {
info('Friendica photos have already been imported into this channel.');
return;
}
$o = replace_macros(get_markup_template('frphotos.tpl'),array(
'$header' => t('Friendica Photo Album Import'),
'$desc' => t('This will import all your Friendica photo albums to this Red channel.'),
'$fr_server' => array('fr_server', t('Friendica Server base URL'),'',''),
'$fr_username' => array('fr_username', t('Friendica Login Username'),'',''),
'$fr_password' => array('fr_password', t('Friendica Login Password'),'',''),
'$submit' => t('Submit'),
));
return $o;
}

View File

@ -568,6 +568,24 @@ function profiles_content(&$a) {
'$no_selected' => (($r[0]['hide_friends'] == 0) ? " checked=\"checked\" " : "") '$no_selected' => (($r[0]['hide_friends'] == 0) ? " checked=\"checked\" " : "")
)); ));
$q = q("select * from profdef where true");
if($q) {
$extra_fields = array();
foreach($q as $qq) {
$mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1",
dbesc($qq['field_name']),
dbesc($r[0]['profile_guid']),
intval(local_user())
);
if(array_key_exists($qq['field_name'],$fields)) {
$extra_fields[] = array($qq['field_name'],$qq['field_desc'],(($mine) ? $mine[0]['v'] : ''), $qq['field_help']);
}
}
}
logger('extra_fields: ' . print_r($extra_fields,true));
$f = get_config('system','birthday_input_format'); $f = get_config('system','birthday_input_format');
if(! $f) if(! $f)
@ -674,6 +692,7 @@ function profiles_content(&$a) {
'$education' => $r[0]['education'], '$education' => $r[0]['education'],
'$contact' => $r[0]['contact'], '$contact' => $r[0]['contact'],
'$channels' => $r[0]['channels'], '$channels' => $r[0]['channels'],
'$extra_fields' => $extra_fields,
)); ));
$arr = array('profile' => $r[0], 'entry' => $o); $arr = array('profile' => $r[0], 'entry' => $o);

View File

@ -1,75 +0,0 @@
<?php
require_once('include/cli_startup.php');
cli_startup();
$a = get_app();
$photo_id = $argv[1];
$channel_address = $argv[2];
$fr_server = urldecode($argv[3]);
require_once('include/photos.php');
$cookies = 'store/[data]/frphoto_cookie_' . $channel_address;
$c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1",
dbesc($channel_address)
);
if(! $c) {
logger('frphotohelper: channel not found');
killme();
}
$channel = $c[0];
$ch = curl_init($fr_server . '/api/friendica/photo?f=&photo_id=' . $photo_id);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookies);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookies);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'RedMatrix');
$output = curl_exec($ch);
curl_close($ch);
$j = json_decode($output,true);
// logger('frphotohelper: ' . print_r($j,true));
$args = array();
$args['data'] = base64_decode($j['data']);
$args['filename'] = $j['filename'];
$args['resource_id'] = $j['resource-id'];
$args['scale'] = $j['scale'];
$args['album'] = $j['album'];
$args['not_visible'] = 1;
$args['created'] = $j['created'];
$args['edited'] = $j['edited'];
$args['title'] = $j['title'];
$args['description'] = $j['desc'];
if($j['allow_cid'] || $j['allow_gid'] || $j['deny_cid'] || $j['deny_gid'])
$args['contact_allow'] = $channel['channel_hash'];
$args['type'] = $j['type'];
$r = q("select * from photo where resource_id = '%s' and uid = %d limit 1",
dbesc($args['resource_id']),
intval($channel['channel_id'])
);
if($r) {
killme();
}
$ret = photo_upload($channel,$channel,$args);
logger('photo_import: ' . print_r($ret,true));
killme();

View File

@ -1 +1 @@
2014-08-20.773 2014-08-21.774

View File

@ -65,6 +65,7 @@
<h3>{{$corporate}}</h3> <h3>{{$corporate}}</h3>
{{include file="field_checkbox.tpl" field=$block_public}} {{include file="field_checkbox.tpl" field=$block_public}}
{{include file="field_checkbox.tpl" field=$feed_contacts}}
{{include file="field_checkbox.tpl" field=$force_publish}} {{include file="field_checkbox.tpl" field=$force_publish}}
{{include file="field_checkbox.tpl" field=$disable_discover_tab}} {{include file="field_checkbox.tpl" field=$disable_discover_tab}}

View File

@ -6,7 +6,7 @@
<input type="checkbox" name='them_{{$field.0}}' id='them_id_{{$field.0}}' value="1" disabled="disabled" {{if $field.2}}checked="checked"{{/if}} /> <input type="checkbox" name='them_{{$field.0}}' id='them_id_{{$field.0}}' value="1" disabled="disabled" {{if $field.2}}checked="checked"{{/if}} />
</td> </td>
<td class="abook-me"> <td class="abook-me">
<input type="checkbox" name='{{$field.0}}' id='me_id_{{$field.0}}' value="{{$field.4}}" {{if $field.3}}checked="checked"{{/if}} /> <input type="checkbox" name='{{$field.0}}' class='abook-edit-me' id='me_id_{{$field.0}}' value="{{$field.4}}" {{if $field.3}}checked="checked"{{/if}} />
</td> </td>
<td> <td>
{{if $field.5}}<span class="permission-inherited">{{$inherited}}</span> {{/if}} {{if $field.5}}<span class="permission-inherited">{{$inherited}}</span> {{/if}}

View File

@ -1,13 +0,0 @@
<h3>{{$header}}</h3>
<p class="descriptive-text">{{$desc}}</p>
<form action="frphotos" method="post" autocomplete="off" >
{{include file="field_input.tpl" field=$fr_server}}
{{include file="field_input.tpl" field=$fr_username}}
{{include file="field_password.tpl" field=$fr_password}}
<input type="submit" name="submit" value="{{$submit}}" />
</form>

View File

@ -349,6 +349,11 @@
<div id="education-jot-end"></div> <div id="education-jot-end"></div>
{{/if}} {{/if}}
{{if $extra_fields}}
{{foreach $extra_fields as $field }}
{{include file="field_input.tpl" field=$field}}
{{/foreach}}
{{/if}}
<div class="profile-edit-submit-wrapper" > <div class="profile-edit-submit-wrapper" >
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" /> <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />