aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfriendica <info@friendica.com>2013-09-02 01:38:17 -0700
committerfriendica <info@friendica.com>2013-09-02 01:38:17 -0700
commit8b7757e033c4483da24700722c186057bb431164 (patch)
treec331db3262084b08b47970c20f2d8657d6ebef81
parenta35d440ff1fee806a8aa17a0297e1163db6a3ba5 (diff)
downloadvolse-hubzilla-8b7757e033c4483da24700722c186057bb431164.tar.gz
volse-hubzilla-8b7757e033c4483da24700722c186057bb431164.tar.bz2
volse-hubzilla-8b7757e033c4483da24700722c186057bb431164.zip
webpage content-type -- needs cleaning up and a security check once all the important bits are in place.
-rw-r--r--include/conversation.php8
-rwxr-xr-xinclude/items.php10
-rwxr-xr-xinclude/text.php60
-rw-r--r--mod/blocks.php2
-rw-r--r--mod/item.php244
-rw-r--r--mod/webpages.php3
-rw-r--r--version.inc2
-rwxr-xr-xview/tpl/jot.tpl3
8 files changed, 206 insertions, 126 deletions
diff --git a/include/conversation.php b/include/conversation.php
index 2157f8291..a357e1480 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -1009,9 +1009,16 @@ function status_editor($a,$x,$popup=false) {
$geotag = (($x['allow_location']) ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : '');
$plaintext = true;
+
if(feature_enabled(local_user(),'richtext'))
$plaintext = false;
+ if(intval($x['plaintext']))
+ $plaintext = true;
+
+ if(intval($x['mimeselect']))
+ $mimeselect = mimetype_select($x['profile_uid']);
+
$tpl = get_markup_template('jot-header.tpl');
$a->page['htmlhead'] .= replace_macros($tpl, array(
@@ -1079,6 +1086,7 @@ function status_editor($a,$x,$popup=false) {
'$emtitle' => t('Example: bob@example.com, mary@example.com'),
'$lockstate' => $x['lockstate'],
'$acl' => $x['acl'],
+ '$mimeselect' => $mimeselect,
'$showacl' => ((array_key_exists('showacl',$x)) ? $x['showacl'] : 'yes'),
'$bang' => $x['bang'],
'$profile_uid' => $x['profile_uid'],
diff --git a/include/items.php b/include/items.php
index 712c416de..66172ade3 100755
--- a/include/items.php
+++ b/include/items.php
@@ -1397,14 +1397,10 @@ function item_store($arr,$allow_exec = false) {
$arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : 0 );
$arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 );
- // this is a bit messy - we really need an input filter chain that temporarily undoes obscuring
- if($arr['mimetype'] != 'text/html' && $arr['mimetype'] != 'application/x-php') {
- if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
- $arr['body'] = escape_tags($arr['body']);
- if((strpos($arr['title'],'<') !== false) || (strpos($arr['title'],'>') !== false))
- $arr['title'] = escape_tags($arr['title']);
- }
+ $arr['body'] = z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']);
+ $arr['title'] = escape_tags($arr['title']);
+
// only detect language if we have text content, and if the post is private but not yet
// obscured, make it so.
diff --git a/include/text.php b/include/text.php
index 99d5c9d78..606ef421c 100755
--- a/include/text.php
+++ b/include/text.php
@@ -81,6 +81,34 @@ function escape_tags($string) {
}
+function z_input_filter($channel_id,$s,$type = 'text/bbcode') {
+
+ if($type === 'text/bbcode')
+ return escape_tags($s);
+ if($type === 'text/markdown')
+ return escape_tags($s);
+ if($type == 'text/plain')
+ return escape_tags($s);
+ $r = q("select account_id, account_roles from account left join channel on channel_account_id = account_id where channel_id = %d limit 1",
+ intval($channel_id)
+ );
+ if($r && ($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWEXEC)) {
+ if(local_user() && (get_account_id() == $r[0]['account_id'])) {
+ return $s;
+ }
+ }
+
+ if($type === 'text/html')
+ return purify_html($s);
+
+ return escape_tags($s);
+
+}
+
+
+
+
+
function purify_html($s) {
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
@@ -1127,6 +1155,7 @@ function prepare_body(&$item,$attach = false) {
function prepare_text($text,$content_type = 'text/bbcode') {
+
switch($content_type) {
case 'text/plain':
@@ -1291,6 +1320,37 @@ function unamp($s) {
}
+function mimetype_select($channel_id, $current = 'text/bbcode') {
+
+ $x = array(
+ 'text/bbcode',
+ 'text/html',
+ 'text/markdown',
+ 'text/plain'
+ );
+
+ $r = q("select account_flags from account left join channel on account_id = channel_account_id where
+ channel_id = %d limit 1",
+ intval($channel_id)
+ );
+
+ if($r) {
+ if($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) {
+ $x[] = 'application/x-php';
+ }
+ }
+
+ $o = t('Page content type: ');
+ $o .= '<select name="mimetype" id="mimetype-select">';
+ foreach($x as $y) {
+ $select = (($y == $current) ? ' selected="selected" ' : '');
+ $o .= '<option name="' . $y . '"' . $select . '>' . $y . '</option>';
+ }
+ $o .= '</select>';
+
+ return $o;
+
+}
diff --git a/mod/blocks.php b/mod/blocks.php
index bb1b68e8b..29117eae8 100644
--- a/mod/blocks.php
+++ b/mod/blocks.php
@@ -1,6 +1,6 @@
<?php
-function webpages_content(&$a) {
+function blocks_content(&$a) {
if(argc() > 1)
$which = argv(1);
diff --git a/mod/item.php b/mod/item.php
index 060f36fdd..50644607d 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -44,7 +44,7 @@ function item_post(&$a) {
call_hooks('post_local_start', $_REQUEST);
-// logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
+ logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
$api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
@@ -221,7 +221,7 @@ function item_post(&$a) {
$verb = $orig_post['verb'];
$app = $orig_post['app'];
$title = escape_tags(trim($_REQUEST['title']));
- $body = escape_tags(trim($_REQUEST['body']));
+ $body = $_REQUEST['body'];
$private = $orig_post['item_private'];
}
@@ -255,7 +255,7 @@ function item_post(&$a) {
$coord = notags(trim($_REQUEST['coord']));
$verb = notags(trim($_REQUEST['verb']));
$title = escape_tags(trim($_REQUEST['title']));
- $body = escape_tags(trim($_REQUEST['body']));
+ $body = $_REQUEST['body'];
$private = (
( strlen($str_group_allow)
@@ -310,154 +310,164 @@ function item_post(&$a) {
$post_type = notags(trim($_REQUEST['type']));
- $content_type = notags(trim($_REQUEST['content_type']));
- if(! $content_type)
- $content_type = 'text/bbcode';
+ $mimetype = notags(trim($_REQUEST['mimetype']));
+ if(! $mimetype)
+ $mimetype = 'text/bbcode';
+ // Verify ability to use html or php!!!
-// BBCODE alert: the following functions assume bbcode input
-// and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
-// we may need virtual or template classes to implement the possible alternatives
+ if($preview) {
+ $body = z_input_filter($profile_uid,$body,$mimetype);
+ }
- // Work around doubled linefeeds in Tinymce 3.5b2
- // First figure out if it's a status post that would've been
- // created using tinymce. Otherwise leave it alone.
+logger('body: ' . $body);
- $plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
- if((! $parent) && (! $api_source) && (! $plaintext)) {
- $body = fix_mce_lf($body);
- }
+ if($mimetype === 'text/bbcode') {
- // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it.
+ // BBCODE alert: the following functions assume bbcode input
+ // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
+ // we may need virtual or template classes to implement the possible alternatives
- if((! $parent) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) {
- $x = q("select abook_id, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
- dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)),
- intval($profile_uid)
- );
- if($x && ($x[0]['abook_their_perms'] & PERMS_W_TAGWALL))
- $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
- }
+ // Work around doubled linefeeds in Tinymce 3.5b2
+ // First figure out if it's a status post that would've been
+ // created using tinymce. Otherwise leave it alone.
- /**
- * fix naked links by passing through a callback to see if this is a red site
- * (already known to us) which will get a zrl, otherwise link with url
- */
+ $plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
+ if((! $parent) && (! $api_source) && (! $plaintext)) {
+ $body = fix_mce_lf($body);
+ }
- $body = preg_replace_callback("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]+)/ism", 'red_zrl_callback', $body);
+ // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it.
- /**
- *
- * When a photo was uploaded into the message using the (profile wall) ajax
- * uploader, The permissions are initially set to disallow anybody but the
- * owner from seeing it. This is because the permissions may not yet have been
- * set for the post. If it's private, the photo permissions should be set
- * appropriately. But we didn't know the final permissions on the post until
- * now. So now we'll look for links of uploaded messages that are in the
- * post and set them to the same permissions as the post itself.
- *
- */
+ if((! $parent) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) {
+ $x = q("select abook_id, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+ dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)),
+ intval($profile_uid)
+ );
+ if($x && ($x[0]['abook_their_perms'] & PERMS_W_TAGWALL))
+ $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
+ }
- if(! $preview) {
- fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],$body,
- $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
+ /**
+ * fix naked links by passing through a callback to see if this is a red site
+ * (already known to us) which will get a zrl, otherwise link with url
+ */
- fix_attached_file_permissions($channel,$observer['xchan_hash'],$body,
- $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
+ $body = preg_replace_callback("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]+)/ism", 'red_zrl_callback', $body);
- }
+ /**
+ *
+ * When a photo was uploaded into the message using the (profile wall) ajax
+ * uploader, The permissions are initially set to disallow anybody but the
+ * owner from seeing it. This is because the permissions may not yet have been
+ * set for the post. If it's private, the photo permissions should be set
+ * appropriately. But we didn't know the final permissions on the post until
+ * now. So now we'll look for links of uploaded messages that are in the
+ * post and set them to the same permissions as the post itself.
+ *
+ */
+ if(! $preview) {
+ fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],$body,
+ $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
+ fix_attached_file_permissions($channel,$observer['xchan_hash'],$body,
+ $str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
- $body = bb_translate_video($body);
+ }
- /**
- * Fold multi-line [code] sequences
- */
- $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
- $body = scale_external_images($body,false);
+ $body = bb_translate_video($body);
- /**
- * Look for any tags and linkify them
- */
+ /**
+ * Fold multi-line [code] sequences
+ */
- $str_tags = '';
- $inform = '';
- $post_tags = array();
+ $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
- $tags = get_tags($body);
+ $body = scale_external_images($body,false);
- $tagged = array();
+ /**
+ * Look for any tags and linkify them
+ */
- $private_forum = false;
+ $str_tags = '';
+ $inform = '';
+ $post_tags = array();
- if(count($tags)) {
- foreach($tags as $tag) {
+ $tags = get_tags($body);
- // If we already tagged 'Robert Johnson', don't try and tag 'Robert'.
- // Robert Johnson should be first in the $tags array
+ $tagged = array();
- $fullnametagged = false;
- for($x = 0; $x < count($tagged); $x ++) {
- if(stristr($tagged[$x],$tag . ' ')) {
- $fullnametagged = true;
- break;
+ $private_forum = false;
+
+ if(count($tags)) {
+ foreach($tags as $tag) {
+
+ // If we already tagged 'Robert Johnson', don't try and tag 'Robert'.
+ // Robert Johnson should be first in the $tags array
+
+ $fullnametagged = false;
+ for($x = 0; $x < count($tagged); $x ++) {
+ if(stristr($tagged[$x],$tag . ' ')) {
+ $fullnametagged = true;
+ break;
+ }
+ }
+ if($fullnametagged)
+ continue;
+
+ $success = handle_tag($a, $body, $inform, $str_tags, (local_user()) ? local_user() : $profile_uid , $tag);
+ logger('handle_tag: ' . print_r($success,tue));
+
+ if($success['replaced']) {
+ $tagged[] = $tag;
+ $post_tags[] = array(
+ 'uid' => $profile_uid,
+ 'type' => $success['termtype'],
+ 'otype' => TERM_OBJ_POST,
+ 'term' => $success['term'],
+ 'url' => $success['url']
+ );
+ }
+ if(is_array($success['contact']) && intval($success['contact']['prv'])) {
+ $private_forum = true;
+ $private_id = $success['contact']['id'];
}
- }
- if($fullnametagged)
- continue;
-
- $success = handle_tag($a, $body, $inform, $str_tags, (local_user()) ? local_user() : $profile_uid , $tag);
- logger('handle_tag: ' . print_r($success,tue));
-
- if($success['replaced']) {
- $tagged[] = $tag;
- $post_tags[] = array(
- 'uid' => $profile_uid,
- 'type' => $success['termtype'],
- 'otype' => TERM_OBJ_POST,
- 'term' => $success['term'],
- 'url' => $success['url']
- );
- }
- if(is_array($success['contact']) && intval($success['contact']['prv'])) {
- $private_forum = true;
- $private_id = $success['contact']['id'];
}
}
- }
// logger('post_tags: ' . print_r($post_tags,true));
- if(($private_forum) && (! $parent) && (! $private)) {
- // we tagged a private forum in a top level post and the message was public.
- // Restrict it.
- $private = 1;
- $str_contact_allow = '<' . $private_id . '>';
- }
-
- $attachments = '';
- $match = false;
+ if(($private_forum) && (! $parent) && (! $private)) {
+ // we tagged a private forum in a top level post and the message was public.
+ // Restrict it.
+ $private = 1;
+ $str_contact_allow = '<' . $private_id . '>';
+ }
- if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
- $attachments = array();
- foreach($match[2] as $mtch) {
- $hash = substr($mtch,0,strpos($mtch,','));
- $rev = intval(substr($mtch,strpos($mtch,',')));
- $r = attach_by_hash_nodata($hash,$rev);
- if($r['success']) {
- $attachments[] = array(
- 'href' => $a->get_baseurl() . '/attach/' . $r['data']['hash'],
- 'length' => $r['data']['filesize'],
- 'type' => $r['data']['filetype'],
- 'title' => urlencode($r['data']['filename']),
- 'revision' => $r['data']['revision']
- );
+ $attachments = '';
+ $match = false;
+
+ if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
+ $attachments = array();
+ foreach($match[2] as $mtch) {
+ $hash = substr($mtch,0,strpos($mtch,','));
+ $rev = intval(substr($mtch,strpos($mtch,',')));
+ $r = attach_by_hash_nodata($hash,$rev);
+ if($r['success']) {
+ $attachments[] = array(
+ 'href' => $a->get_baseurl() . '/attach/' . $r['data']['hash'],
+ 'length' => $r['data']['filesize'],
+ 'type' => $r['data']['filetype'],
+ 'title' => urlencode($r['data']['filename']),
+ 'revision' => $r['data']['revision']
+ );
+ }
+ $body = str_replace($match[1],'',$body);
}
- $body = str_replace($match[1],'',$body);
}
}
@@ -530,7 +540,7 @@ function item_post(&$a) {
$datarray['changed'] = datetime_convert();
$datarray['mid'] = $mid;
$datarray['parent_mid'] = $parent_mid;
- $datarray['mimetype'] = $content_type;
+ $datarray['mimetype'] = $mimetype;
$datarray['title'] = $title;
$datarray['body'] = $body;
$datarray['app'] = $app;
diff --git a/mod/webpages.php b/mod/webpages.php
index f3e1cd2f7..081297eb9 100644
--- a/mod/webpages.php
+++ b/mod/webpages.php
@@ -52,10 +52,13 @@ require_once ('include/conversation.php');
'bang' => (($group || $cid) ? '!' : ''),
'visitor' => 'block',
'profile_uid' => intval($owner),
+ 'plaintext' => 1,
+ 'mimeselect' => 1,
);
$o .= status_editor($a,$x);
+
//Get a list of webpages. We can't display all them because endless scroll makes that unusable, so just list titles and an edit link.
//TODO - this should be replaced with pagelist_widget
diff --git a/version.inc b/version.inc
index 6119cf100..5a1e9d9a7 100644
--- a/version.inc
+++ b/version.inc
@@ -1 +1 @@
-2013-09-01.423
+2013-09-02.424
diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl
index 8092a7047..e67caf3d2 100755
--- a/view/tpl/jot.tpl
+++ b/view/tpl/jot.tpl
@@ -9,6 +9,9 @@
<input type="hidden" name="post_id" value="{{$post_id}}" />
<input type="hidden" name="webpage" value="{{$webpage}}" />
<input type="hidden" name="preview" id="jot-preview" value="0" />
+
+ {{$mimeselect}}
+
<div id="jot-title-wrap"><input name="title" id="jot-title" type="text" placeholder="{{$placeholdertitle}}" value="{{$title}}" class="jothidden" style="display:none"></div>
{{if $catsenabled}}
<div id="jot-category-wrap"><input name="category" id="jot-category" type="text" placeholder="{{$placeholdercategory}}" value="{{$category}}" class="jothidden" style="display:none" /></div>