diff options
Diffstat (limited to 'include')
-rwxr-xr-x | include/contact_widgets.php | 29 | ||||
-rwxr-xr-x | include/conversation.php | 83 | ||||
-rwxr-xr-x | include/event.php | 2 | ||||
-rwxr-xr-x | include/items.php | 22 | ||||
-rwxr-xr-x | include/nav.php | 8 | ||||
-rwxr-xr-x | include/oembed.php | 7 | ||||
-rwxr-xr-x | include/security.php | 46 | ||||
-rwxr-xr-x | include/template_processor.php | 9 | ||||
-rw-r--r-- | include/text.php | 101 |
9 files changed, 263 insertions, 44 deletions
diff --git a/include/contact_widgets.php b/include/contact_widgets.php index caa0572d2..605a3eb78 100755 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -75,4 +75,33 @@ function networks_widget($baseurl,$selected = '') { )); } +function fileas_widget($baseurl,$selected = '') { + $a = get_app(); + if(! local_user()) + return ''; + + $saved = get_pconfig(local_user(),'system','filetags'); + if(! strlen($saved)) + return; + + $matches = false; + $terms = array(); + $cnt = preg_match_all('/\[(.*?)\]/',$saved,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $unescaped = file_tag_decode($mtch[1]); + $terms[] = array('name' => $unescaped,'selected' => (($selected == $unescaped) ? 'selected' : '')); + } + } + + return replace_macros(get_markup_template('fileas_widget.tpl'),array( + '$title' => t('File Selections'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $baseurl, + + )); +} diff --git a/include/conversation.php b/include/conversation.php index 526c6ea00..88ecf502b 100755 --- a/include/conversation.php +++ b/include/conversation.php @@ -186,6 +186,8 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { require_once('bbcode.php'); + $ssl_state = ((local_user()) ? true : false); + $profile_owner = 0; $page_writeable = false; @@ -345,7 +347,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { 'like' => '', 'dislike' => '', 'comment' => '', - 'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl() . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))), + 'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state) . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))), 'previewing' => $previewing, 'wait' => t('Please wait'), ); @@ -375,7 +377,8 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $comments[$item['parent']] = 1; else $comments[$item['parent']] += 1; - } + } elseif(! x($comments,$item['parent'])) + $comments[$item['parent']] = 0; // avoid notices later on } // map all the like/dislike activities for each parent item @@ -460,7 +463,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $comment_lastcollapsed = true; } - $redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ; + $redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ; $lock = ((($item['private']) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])))) @@ -542,7 +545,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { } $edpost = (((($profile_owner == local_user()) && ($toplevelpost) && (intval($item['wall']) == 1)) || ($mode === 'notes')) - ? array($a->get_baseurl()."/editpost/".$item['id'], t("Edit")) + ? array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit")) : False); @@ -559,24 +562,28 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { ); $star = false; + $filer = false; + $isstarred = "unstarred"; - if ($profile_owner == local_user() && $toplevelpost) { - $isstarred = (($item['starred']) ? "starred" : "unstarred"); - - $star = array( - 'do' => t("add star"), - 'undo' => t("remove star"), - 'toggle' => t("toggle star status"), - 'classdo' => (($item['starred']) ? "hidden" : ""), - 'classundo' => (($item['starred']) ? "" : "hidden"), - 'starred' => t('starred'), - 'tagger' => t("add tag"), - 'classtagger' => "", - ); + if ($profile_owner == local_user()) { + if($toplevelpost) { + $isstarred = (($item['starred']) ? "starred" : "unstarred"); + + $star = array( + 'do' => t("add star"), + 'undo' => t("remove star"), + 'toggle' => t("toggle star status"), + 'classdo' => (($item['starred']) ? "hidden" : ""), + 'classundo' => (($item['starred']) ? "" : "hidden"), + 'starred' => t('starred'), + 'tagger' => t("add tag"), + 'classtagger' => "", + ); + } + $filer = t("file as"); } - $photo = $item['photo']; $thumb = $item['thumb']; @@ -670,6 +677,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { 'edpost' => $edpost, 'isstarred' => $isstarred, 'star' => $star, + 'filer' => $filer, 'drop' => $drop, 'vote' => $likebuttons, 'like' => $like, @@ -691,7 +699,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { $page_template = get_markup_template("conversation.tpl"); $o .= replace_macros($page_template, array( - '$baseurl' => $a->get_baseurl(), + '$baseurl' => $a->get_baseurl($ssl_state), '$mode' => $mode, '$user' => $a->user, '$threads' => $threads, @@ -701,7 +709,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) { return $o; }} -function best_link_url($item,&$sparkle) { +function best_link_url($item,&$sparkle,$ssl_state = false) { $a = get_app(); @@ -713,7 +721,7 @@ function best_link_url($item,&$sparkle) { if((local_user()) && (local_user() == $item['uid'])) { if(isset($a->contacts) && x($a->contacts,$clean_url)) { if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) { - $best_url = $a->get_baseurl() . '/redir/' . $a->contacts[$clean_url]['id']; + $best_url = $a->get_baseurl($ssl_state) . '/redir/' . $a->contacts[$clean_url]['id']; $sparkle = true; } else @@ -734,10 +742,14 @@ function best_link_url($item,&$sparkle) { if(! function_exists('item_photo_menu')){ function item_photo_menu($item){ $a = get_app(); - - if (local_user() && (! count($a->contacts))) - load_contact_links(local_user()); + $ssl_state = false; + + if(local_user()) { + $ssl_state = true; + if(! count($a->contacts)) + load_contact_links(local_user()); + } $contact_url=""; $pm_url=""; $status_link=""; @@ -745,7 +757,7 @@ function item_photo_menu($item){ $posts_link=""; $sparkle = false; - $profile_link = best_link_url($item,$sparkle); + $profile_link = best_link_url($item,$sparkle,$ssl_state); if($profile_link === 'mailbox') $profile_link = ''; @@ -754,7 +766,7 @@ function item_photo_menu($item){ $status_link = $profile_link . "?url=status"; $photos_link = $profile_link . "?url=photos"; $profile_link = $profile_link . "?url=profile"; - $pm_url = $a->get_baseurl() . '/message/new/' . $cid; + $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid; } else { if(local_user() && local_user() == $item['uid'] && link_compare($item['url'],$item['author-link'])) { @@ -765,8 +777,8 @@ function item_photo_menu($item){ } } if(($cid) && (! $item['self'])) { - $contact_url = $a->get_baseurl() . '/contacts/' . $cid; - $posts_link = $a->get_baseurl() . '/network/?cid=' . $cid; + $contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid; + $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $cid; } $menu = Array( @@ -802,7 +814,7 @@ function like_puller($a,$item,&$arr,$mode) { if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) { $url = $item['author-link']; if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === 'dfrn') && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) { - $url = $a->get_baseurl() . '/redir/' . $item['contact-id']; + $url = $a->get_baseurl(true) . '/redir/' . $item['contact-id']; $sparkle = ' class="sparkle" '; } if(! ((isset($arr[$item['parent'] . '-l'])) && (is_array($arr[$item['parent'] . '-l'])))) @@ -864,7 +876,7 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { $a->page['htmlhead'] .= replace_macros($tpl, array( '$newpost' => 'true', - '$baseurl' => $a->get_baseurl(), + '$baseurl' => $a->get_baseurl(true), '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), '$geotag' => $geotag, '$nickname' => $x['nickname'], @@ -873,6 +885,7 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { '$vidurl' => t("Please enter a video link/URL:"), '$audurl' => t("Please enter an audio link/URL:"), '$term' => t('Tag term:'), + '$fileas' => t('File as:'), '$whereareu' => t('Where are you right now?'), '$title' => t('Enter a title for this item') )); @@ -914,8 +927,8 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { $o .= replace_macros($tpl,array( '$return_path' => $a->cmd, - '$action' => $a->get_baseurl().'/item', - '$share' => (($x['button']) ? $x['button'] : t('Share')), + '$action' => $a->get_baseurl(true) . '/item', + '$share' => (x($x,'button') ? $x['button'] : t('Share')), '$upload' => t('Upload photo'), '$shortupload' => t('upload photo'), '$attach' => t('Attach file'), @@ -938,7 +951,7 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) { '$ptyp' => (($notes_cid) ? 'note' : 'wall'), '$content' => '', '$post_id' => '', - '$baseurl' => $a->get_baseurl(), + '$baseurl' => $a->get_baseurl(true), '$defloc' => $x['default_location'], '$visitor' => $x['visitor'], '$pvisit' => (($notes_cid) ? 'none' : $x['visitor']), @@ -980,8 +993,8 @@ function conv_sort($arr,$order) { usort($parents,'sort_thr_commented'); if(count($parents)) - foreach($parents as $x) - $x['children'] = array(); + foreach($parents as $i=>$_x) + $parents[$i]['children'] = array(); foreach($arr as $x) { if($x['id'] != $x['parent']) { diff --git a/include/event.php b/include/event.php index 4a9a9a004..29202badd 100755 --- a/include/event.php +++ b/include/event.php @@ -163,7 +163,7 @@ function bbtoevent($s) { if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match)) $ev['adjust'] = $match[1]; $match = ''; - $ev['nofinish'] = (($ev['start'] && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); + $ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); return $ev; } diff --git a/include/items.php b/include/items.php index 1a7aa6c46..4b1523ff6 100755 --- a/include/items.php +++ b/include/items.php @@ -682,7 +682,7 @@ function item_store($arr,$force_parent = false) { unset($arr['dsprsig']); } - if($arr['gravity']) + if(x($arr, 'gravity')) $arr['gravity'] = intval($arr['gravity']); elseif($arr['parent-uri'] === $arr['uri']) $arr['gravity'] = 0; @@ -742,6 +742,7 @@ function item_store($arr,$force_parent = false) { if($arr['parent-uri'] === $arr['uri']) { $parent_id = 0; + $parent_deleted = 0; $allow_cid = $arr['allow_cid']; $allow_gid = $arr['allow_gid']; $deny_cid = $arr['deny_cid']; @@ -800,6 +801,8 @@ function item_store($arr,$force_parent = false) { logger('item_store: item parent was not found - ignoring item'); return 0; } + + $parent_deleted = 0; } } @@ -1043,6 +1046,21 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { if(! $rino_enable) $rino = 0; + $ssl_val = intval(get_config('system','ssl_policy')); + $ssl_policy = ''; + switch($ssl_val){ + case SSL_POLICY_FULL: + $ssl_policy = 'full'; + break; + case SSL_POLICY_SELFSIGN: + $ssl_policy = 'self'; + break; + case SSL_POLICY_NONE: + default: + $ssl_policy = 'none'; + break; + } + $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino=1' : ''); logger('dfrn_deliver: ' . $url); @@ -1115,6 +1133,8 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $postvars['perm'] = 'r'; } + $postvars['ssl_policy'] = $ssl_policy; + if($rino && $rino_allowed && (! $dissolve)) { $key = substr(random_string(),0,16); $data = bin2hex(aes_encrypt($postvars['data'],$key)); diff --git a/include/nav.php b/include/nav.php index aadfa82fd..e28081839 100755 --- a/include/nav.php +++ b/include/nav.php @@ -8,6 +8,8 @@ function nav(&$a) { * */ + $ssl_state = ((local_user()) ? true : false); + if(!(x($a->page,'nav'))) $a->page['nav'] = ''; @@ -27,7 +29,7 @@ function nav(&$a) { $myident = ((is_array($a->user) && isset($a->user['nickname'])) ? $a->user['nickname'] . '@' : ''); - $sitelocation = $myident . substr($a->get_baseurl(),strpos($a->get_baseurl(),'//') + 2 ); + $sitelocation = $myident . substr($a->get_baseurl($ssl_state),strpos($a->get_baseurl($ssl_state),'//') + 2 ); // nav links: array of array('href', 'text', 'extra css classes', 'title') @@ -53,7 +55,7 @@ function nav(&$a) { // user info $r = q("SELECT micro FROM contact WHERE uid=%d AND self=1", intval($a->user['uid'])); $userinfo = array( - 'icon' => (count($r) ? $r[0]['micro']: $a->get_baseurl()."/images/default-profile-mm.jpg"), + 'icon' => (count($r) ? $r[0]['micro']: $a->get_baseurl($ssl_state)."/images/default-profile-mm.jpg"), 'name' => $a->user['username'], ); @@ -76,7 +78,7 @@ function nav(&$a) { if(($a->config['register_policy'] == REGISTER_OPEN) && (! local_user()) && (! remote_user())) $nav['register'] = array('register',t('Register'), "", t('Create an account')); - $help_url = $a->get_baseurl() . '/help'; + $help_url = $a->get_baseurl($ssl_state) . '/help'; if(! get_config('system','hide_help')) $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation')); diff --git a/include/oembed.php b/include/oembed.php index 5c3c595f5..cc71f9757 100755 --- a/include/oembed.php +++ b/include/oembed.php @@ -1,6 +1,6 @@ <?php function oembed_replacecb($matches){ - logger('oembedcb'); +// logger('oembedcb'); $embedurl=$matches[1]; $j = oembed_fetch_url($embedurl); $s = oembed_format_object($j); @@ -14,6 +14,9 @@ function oembed_fetch_url($embedurl){ $txt = Cache::get($embedurl); + // These media files should now be caught in bbcode.php + // left here as a fallback in case this is called from another source + $noexts = array("mp3","mp4","ogg","ogv","oga","ogm","webm"); $ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION); @@ -62,7 +65,7 @@ function oembed_fetch_url($embedurl){ function oembed_format_object($j){ $embedurl = $j->embedurl; - $jhtml = oembed_iframe($j->embedurl,$j->width,$j->height ); + $jhtml = oembed_iframe($j->embedurl,(isset($j->width) ? $j->width : null), (isset($j->height) ? $j->height : null) ); $ret="<span class='oembed ".$j->type."'>"; switch ($j->type) { case "video": { diff --git a/include/security.php b/include/security.php index 8c536b656..6ea515bff 100755 --- a/include/security.php +++ b/include/security.php @@ -288,3 +288,49 @@ function item_permissions_sql($owner_id,$remote_verified = false,$groups = null) } +/* + * Functions used to protect against Cross-Site Request Forgery + * The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key. + * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; + * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). + * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: + * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). + * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. + * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, + * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). + */ +function get_form_security_token($typename = "") { + $a = get_app(); + + $timestamp = time(); + $sec_hash = hash('whirlpool', $a->user["guid"] . $a->user["prvkey"] . session_id() . $timestamp . $typename); + + return $timestamp . "." . $sec_hash; +} + +function check_form_security_token($typename = "", $formname = 'form_security_token') { + if (!x($_REQUEST, $formname)) return false; + $hash = $_REQUEST[$formname]; + + $max_livetime = 10800; // 3 hours + + $a = get_app(); + + $x = explode(".", $hash); + if (time() > (IntVal($x[0]) + $max_livetime)) return false; + + $sec_hash = hash('whirlpool', $a->user["guid"] . $a->user["prvkey"] . session_id() . $x[0] . $typename); + + return ($sec_hash == $x[1]); +} + +function check_form_security_std_err_msg() { + return t('The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before subitting it.') . EOL; +} +function check_form_security_token_redirectOnErr($err_redirect, $typename = "", $formname = 'form_security_token') { + if (!check_form_security_token($typename, $formname)) { + $a = get_app(); + notice( check_form_security_std_err_msg() ); + goaway($a->get_baseurl() . $err_redirect ); + } +} diff --git a/include/template_processor.php b/include/template_processor.php index 8671587fc..7f7b0b55b 100755 --- a/include/template_processor.php +++ b/include/template_processor.php @@ -80,8 +80,13 @@ */ private function _replcb_for($args){ $m = array_map('trim', explode(" as ", $args[2])); - list($keyname, $varname) = explode("=>",$m[1]); - if (is_null($varname)) { $varname=$keyname; $keyname=""; } + $x = explode("=>",$m[1]); + if (count($x) == 1) { + $varname = $x[0]; + $keyname = ""; + } else { + list($keyname, $varname) = $x; + } if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ; //$vals = $this->r[$m[0]]; $vals = $this->_get_var($m[0]); diff --git a/include/text.php b/include/text.php index 08c5a5424..d34fd7fbe 100644 --- a/include/text.php +++ b/include/text.php @@ -874,6 +874,7 @@ function link_compare($a,$b) { if(! function_exists('prepare_body')) { function prepare_body($item,$attach = false) { + $a = get_app(); call_hooks('prepare_body_init', $item); $cache = get_config('system','itemcache'); @@ -926,6 +927,33 @@ function prepare_body($item,$attach = false) { } $s .= '<div class="clear"></div></div>'; } + $matches = false; + $cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { +// logger('prepare_text: categories: ' . print_r($matches,true), LOGGER_DEBUG); + foreach($matches as $mtch) { + if(strlen($x)) + $x .= ','; + $x .= file_tag_decode($mtch[1]); + } + if(strlen($x)) + $s .= '<div class="categorytags"><span>' . t('Categories:') . ' </span>' . $x . '</div>'; + + + } + $matches = false; + $x = ''; + $cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER); + if($cnt) { +// logger('prepare_text: filed_under: ' . print_r($matches,true), LOGGER_DEBUG); + foreach($matches as $mtch) { + if(strlen($x)) + $x .= ' '; + $x .= file_tag_decode($mtch[1]). ' <a href="' . $a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&term=' . file_tag_decode($mtch[1]) . '" title="' . t('remove') . '" >' . t('[remove]') . '</a>'; + } + if(strlen($x) && (local_user() == $item['uid'])) + $s .= '<div class="filesavetags"><span>' . t('Filed under:') . ' </span>' . $x . '</div>'; + } $prep_arr = array('item' => $item, 'html' => $s); call_hooks('prepare_body_final', $prep_arr); @@ -1248,4 +1276,77 @@ function item_post_type($item) { return t('post'); } +// post categories and "save to file" use the same item.file table for storage. +// We will differentiate the different uses by wrapping categories in angle brackets +// and save to file categories in square brackets. +// To do this we need to escape these characters if they appear in our tag. + +function file_tag_encode($s) { + return str_replace(array('<','>','[',']'),array('%3c','%3e','%5b','%5d'),$s); +} + +function file_tag_decode($s) { + return str_replace(array('%3c','%3e','%5b','%5d'),array('<','>','[',']'),$s); +} + +function file_tag_file_query($table,$s,$type = 'file') { + if($type == 'file') + $str = preg_quote( '[' . file_tag_encode($s) . ']' ); + else + $str = preg_quote( '<' . file_tag_encode($s) . '>' ); + return " AND " . (($table) ? dbesc($table) . '.' : '') . "file regexp '" . dbesc($str) . "' "; +} + +function file_tag_save_file($uid,$item,$file) { + $result = false; + if(! intval($uid)) + return false; + $r = q("select file from item where id = %d and uid = %d limit 1", + intval($item), + intval($uid) + ); + if(count($r)) { + if(! stristr($r[0]['file'],'[' . file_tag_encode($file) . ']')) + q("update item set file = '%s' where id = %d and uid = %d limit 1", + dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'), + intval($item), + intval($uid) + ); + $saved = get_pconfig($uid,'system','filetags'); + if((! strlen($saved)) || (! stristr($saved,'[' . file_tag_encode($file) . ']'))) + set_pconfig($uid,'system','filetags',$saved . '[' . file_tag_encode($file) . ']'); + } + return true; +} + +function file_tag_unsave_file($uid,$item,$file) { + $result = false; + if(! intval($uid)) + return false; + + $pattern = '[' . file_tag_encode($file) . ']' ; + + $r = q("select file from item where id = %d and uid = %d limit 1", + intval($item), + intval($uid) + ); + if(! count($r)) + return false; + + q("update item set file = '%s' where id = %d and uid = %d limit 1", + dbesc(str_replace($pattern,'',$r[0]['file'])), + intval($item), + intval($uid) + ); + + $r = q("select file from item where uid = %d " . file_tag_file_query('item',$file), + intval($uid) + ); + + if(! count($r)) { + $saved = get_pconfig($uid,'system','filetags'); + set_pconfig($uid,'system','filetags',str_replace($pattern,'',$saved)); + } + return true; +} |