Merge branch 'master', remote-tracking branch 'remotes/upstream/master'
* remotes/upstream/master: sort inbox by recently replied conversations first file as widget and basic filing implementation for duepuntozero,slackr much more work needed - this is just for test/evaluation currently don't count self in number of contatcs invite potential connectees to the free social web In HTML2BBCode: fetch the URL of [EMBED] using JavaScript instead of an ajax-call to a php-script. Once there actually is embedded Code in the HTML, this function is called after every single keypress. Not only is making an ajax-call every keypress bandith intensive - it also made typing hard / slow. Making a lot of JavaScript-RegExp-Computation every keypress isn't exactly great either, but still performs better. Some security against XSRF-attacks A 'PHP Fatal error: Call to a member function getElementsByTagName() on a non-object in mod/parse_url.php on line 191' occurred when the linked HTML-File doesn't have a HEAD. The HTML-file couln't be link to in the editor therefore. Mostly some checks in order to avoid Notices; 1 real bugfix in /mod/network.php Avoid notices contact.network is used later to check if a direct link or a redirect by /redir/contactid should be used wasn't actually changed before Avoid a notice Avoid a Notice Avoid a Notice Avoid a Notice * master:
This commit is contained in:
commit
a2073bcfc0
36 changed files with 425 additions and 191 deletions
6
boot.php
6
boot.php
|
@ -9,7 +9,7 @@ require_once('include/nav.php');
|
|||
require_once('include/cache.php');
|
||||
|
||||
define ( 'FRIENDICA_PLATFORM', 'Friendica');
|
||||
define ( 'FRIENDICA_VERSION', '2.3.1279' );
|
||||
define ( 'FRIENDICA_VERSION', '2.3.1280' );
|
||||
define ( 'DFRN_PROTOCOL_VERSION', '2.22' );
|
||||
define ( 'DB_UPDATE_VERSION', 1131 );
|
||||
|
||||
|
@ -1209,7 +1209,7 @@ function current_theme(){
|
|||
$a = get_app();
|
||||
|
||||
$system_theme = ((isset($a->config['system']['theme'])) ? $a->config['system']['theme'] : '');
|
||||
$theme_name = ((is_array($_SESSION) && x($_SESSION,'theme')) ? $_SESSION['theme'] : $system_theme);
|
||||
$theme_name = ((isset($_SESSION) && x($_SESSION,'theme')) ? $_SESSION['theme'] : $system_theme);
|
||||
|
||||
if($theme_name && file_exists('view/theme/' . $theme_name . '/style.css'))
|
||||
return($theme_name);
|
||||
|
@ -1335,7 +1335,7 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
|
|||
array(
|
||||
'label' => t('Profile'),
|
||||
'url' => $url.'/?tab=profile',
|
||||
'sel' => (($tab=='profile')?'active':''),
|
||||
'sel' => ((isset($tab) && $tab=='profile')?'active':''),
|
||||
),
|
||||
array(
|
||||
'label' => t('Photos'),
|
||||
|
|
|
@ -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,
|
||||
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -375,7 +375,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
|
||||
|
@ -571,6 +572,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
|
|||
'classundo' => (($item['starred']) ? "" : "hidden"),
|
||||
'starred' => t('starred'),
|
||||
'tagger' => t("add tag"),
|
||||
'filer' => t("file as"),
|
||||
'classtagger' => "",
|
||||
);
|
||||
}
|
||||
|
@ -873,6 +875,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')
|
||||
));
|
||||
|
@ -915,7 +918,7 @@ 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')),
|
||||
'$share' => (x($x,'button') ? $x['button'] : t('Share')),
|
||||
'$upload' => t('Upload photo'),
|
||||
'$shortupload' => t('upload photo'),
|
||||
'$attach' => t('Attach file'),
|
||||
|
@ -980,8 +983,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']) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,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": {
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -1294,7 +1294,7 @@ function file_tag_save_file($uid,$item,$file) {
|
|||
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) . ']'),
|
||||
dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'),
|
||||
intval($item),
|
||||
intval($uid)
|
||||
);
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
|
||||
/* oembed */
|
||||
function _h2b_cb(match) {
|
||||
/*
|
||||
function s_h2b(data) {
|
||||
match = data;
|
||||
}
|
||||
|
@ -90,6 +91,23 @@
|
|||
success: s_h2b,
|
||||
dataType: 'html'
|
||||
});
|
||||
*/
|
||||
|
||||
var f, g, tof = [], tor = [];
|
||||
var find_spanc = /<span [^>]*class *= *[\"'](?:[^\"']* )*oembed(?: [^\"']*)*[\"'][^>]*>(.*?(?:<span[^>]*>(.*?)<\/span *>)*.*?)<\/span *>/ig;
|
||||
while (f = find_spanc.exec(match)) {
|
||||
var find_a = /<a([^>]* rel=[\"']oembed[\"'][^>]*)>.*?<\/a *>/ig;
|
||||
if (g = find_a.exec(f[1])) {
|
||||
var find_href = /href=[\"']([^\"']*)[\"']/ig;
|
||||
var m2 = find_href.exec(g[1]);
|
||||
if (m2[1]) {
|
||||
tof.push(f[0]);
|
||||
tor.push("[EMBED]" + m2[1] + "[/EMBED]");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < tof.length; i++) match = match.replace(tof[i], tor[i]);
|
||||
|
||||
return match;
|
||||
}
|
||||
if (s.indexOf('class="oembed')>=0){
|
||||
|
|
|
@ -445,7 +445,7 @@ function contacts_content(&$a) {
|
|||
|
||||
|
||||
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
|
||||
WHERE `uid` = %d AND `pending` = 0 $sql_extra $sql_extra2 ",
|
||||
WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ",
|
||||
intval($_SESSION['uid']));
|
||||
if(count($r)) {
|
||||
$a->set_pager_total($r[0]['total']);
|
||||
|
@ -454,7 +454,7 @@ function contacts_content(&$a) {
|
|||
|
||||
|
||||
|
||||
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `pending` = 0 $sql_extra $sql_extra2 ORDER BY `name` ASC LIMIT %d , %d ",
|
||||
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ORDER BY `name` ASC LIMIT %d , %d ",
|
||||
intval($_SESSION['uid']),
|
||||
intval($a->pager['start']),
|
||||
intval($a->pager['itemspage'])
|
||||
|
@ -465,8 +465,6 @@ function contacts_content(&$a) {
|
|||
if(count($r)) {
|
||||
|
||||
foreach($r as $rr) {
|
||||
if($rr['self'])
|
||||
continue;
|
||||
|
||||
switch($rr['rel']) {
|
||||
case CONTACT_IS_FRIEND:
|
||||
|
|
|
@ -43,7 +43,7 @@ function dfrn_request_post(&$a) {
|
|||
return;
|
||||
|
||||
|
||||
if($_POST['cancel']) {
|
||||
if(x($_POST, 'cancel')) {
|
||||
goaway(z_root());
|
||||
}
|
||||
|
||||
|
@ -666,7 +666,11 @@ function dfrn_request_content(&$a) {
|
|||
$page_desc = sprintf( t('Diaspora members: Please do not use this form. Instead, enter "%s" into your Diaspora search bar.'),
|
||||
$target_addr) . EOL . EOL;
|
||||
|
||||
$page_desc .= t("Please enter your 'Identity Address' from one of the following supported social networks:");
|
||||
$page_desc .= t("Please enter your 'Identity Address' from one of the following supported communications networks:");
|
||||
|
||||
$emailnet = t("<strike>Connect as an email follower</strike> \x28Coming soon\x29");
|
||||
|
||||
$invite_desc = t('If you are not yet a member of the free social web, <a href="http://dir.friendica.com/siteinfo">follow this link to find a public Friendica site and join us today</a>.');
|
||||
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$header' => t('Friend/Connection Request'),
|
||||
|
@ -682,6 +686,8 @@ function dfrn_request_content(&$a) {
|
|||
'$diaspora' => t('Diaspora'),
|
||||
'$diasnote' => t('- please share from your own site as noted above'),
|
||||
'$your_address' => t('Your Identity Address:'),
|
||||
'$invite_desc' => $invite_desc,
|
||||
'$emailnet' => $emailnet,
|
||||
'$submit' => t('Submit Request'),
|
||||
'$cancel' => t('Cancel'),
|
||||
'$nickname' => $a->argv[1],
|
||||
|
|
23
mod/filer.php
Executable file
23
mod/filer.php
Executable file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
function filer_content(&$a) {
|
||||
|
||||
if(! local_user()) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$term = notags(trim($_GET['term']));
|
||||
$item_id = (($a->argc > 1) ? notags(trim($a->argv[1])) : 0);
|
||||
|
||||
logger('filer: tag ' . $term . ' item ' . $item_id);
|
||||
|
||||
if($item_id && strlen($term))
|
||||
file_tag_save_file(local_user(),$item_id,$term);
|
||||
|
||||
killme();
|
||||
}
|
|
@ -192,9 +192,9 @@ function message_content(&$a) {
|
|||
$a->set_pager_total($r[0]['total']);
|
||||
|
||||
$r = q("SELECT max(`mail`.`created`) AS `mailcreated`, min(`mail`.`seen`) AS `mailseen`,
|
||||
`mail`.* , `contact`.`name`, `contact`.`url`, `contact`.`thumb`
|
||||
`mail`.* , `contact`.`name`, `contact`.`url`, `contact`.`thumb` , `contact`.`network`
|
||||
FROM `mail` LEFT JOIN `contact` ON `mail`.`contact-id` = `contact`.`id`
|
||||
WHERE `mail`.`uid` = %d AND `from-url` $eq '%s' GROUP BY `parent-uri` ORDER BY `created` DESC LIMIT %d , %d ",
|
||||
WHERE `mail`.`uid` = %d AND `from-url` $eq '%s' GROUP BY `parent-uri` ORDER BY `mailcreated` DESC LIMIT %d , %d ",
|
||||
intval(local_user()),
|
||||
dbesc($myprofile),
|
||||
intval($a->pager['start']),
|
||||
|
|
|
@ -44,8 +44,9 @@ function network_init(&$a) {
|
|||
}
|
||||
|
||||
$a->page['aside'] .= group_side('network','network',true,$group_id);
|
||||
$a->page['aside'] .= networks_widget($a->get_baseurl() . '/network',(($_GET['nets']) ? $_GET['nets'] : ''));
|
||||
$a->page['aside'] .= networks_widget($a->get_baseurl() . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
|
||||
$a->page['aside'] .= saved_searches($search);
|
||||
$a->page['aside'] .= fileas_widget($a->get_baseurl() . '/network',(x($_GET, 'file') ? $_GET['file'] : ''));
|
||||
|
||||
}
|
||||
|
||||
|
@ -132,15 +133,15 @@ function network_content(&$a, $update = 0) {
|
|||
$starred_active = 'active';
|
||||
}
|
||||
|
||||
if($_GET['bmark']) {
|
||||
if(x($_GET,'bmark')) {
|
||||
$bookmarked_active = 'active';
|
||||
}
|
||||
|
||||
if($_GET['conv']) {
|
||||
if(x($_GET,'conv')) {
|
||||
$conv_active = 'active';
|
||||
}
|
||||
|
||||
if($_GET['spam']) {
|
||||
if(x($_GET,'spam')) {
|
||||
$spam_active = 'active';
|
||||
}
|
||||
|
||||
|
@ -248,7 +249,7 @@ function network_content(&$a, $update = 0) {
|
|||
$def_acl = array('allow_cid' => '<' . intval($cid) . '>');
|
||||
|
||||
if(! $update) {
|
||||
if(group) {
|
||||
if($group) {
|
||||
if(($t = group_public_members($group)) && (! get_pconfig(local_user(),'system','nowarn_insecure'))) {
|
||||
notice( sprintf( tt('Warning: This group contains %s member from an insecure network.',
|
||||
'Warning: This group contains %s members from an insecure network.',
|
||||
|
@ -498,6 +499,8 @@ function network_content(&$a, $update = 0) {
|
|||
|
||||
$items = conv_sort($items,$ordering);
|
||||
|
||||
} else {
|
||||
$items = array();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ function parse_url_content(&$a) {
|
|||
|
||||
if(! $text) {
|
||||
logger('parsing meta');
|
||||
$items = $domhead->getElementsByTagName('meta');
|
||||
$items = (isset($domhead) && is_object($domhead) ? $domhead->getElementsByTagName('meta') : null);
|
||||
if($items) {
|
||||
foreach($items as $item) {
|
||||
$property = $item->getAttribute('property');
|
||||
|
|
|
@ -15,10 +15,12 @@ function profile_photo_init(&$a) {
|
|||
|
||||
function profile_photo_post(&$a) {
|
||||
|
||||
if(! local_user()) {
|
||||
notice ( t('Permission denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
if(! local_user()) {
|
||||
notice ( t('Permission denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
|
||||
|
||||
|
@ -149,6 +151,8 @@ function profile_photo_content(&$a) {
|
|||
return;
|
||||
};
|
||||
|
||||
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
$resource_id = $a->argv[2];
|
||||
//die(":".local_user());
|
||||
$r=q("SELECT * FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' ORDER BY `scale` ASC",
|
||||
|
@ -203,6 +207,7 @@ function profile_photo_content(&$a) {
|
|||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$title' => t('Upload Profile Photo'),
|
||||
'$submit' => t('Upload'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . $a->get_baseurl() . '">' . t('skip this step') . '</a>' : '<a href="'. $a->get_baseurl() . '/photos/' . $a->user['nickname'] . '">' . t('select a photo from your photo albums') . '</a>')
|
||||
));
|
||||
|
||||
|
@ -218,6 +223,7 @@ function profile_photo_content(&$a) {
|
|||
'$image_url' => $a->get_baseurl() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$done' => t('Done Editing')
|
||||
));
|
||||
return $o;
|
||||
|
|
|
@ -21,6 +21,9 @@ function profiles_post(&$a) {
|
|||
notice( t('Profile not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
|
||||
|
||||
$is_default = (($orig[0]['is-default']) ? 1 : 0);
|
||||
|
||||
$profile_name = notags(trim($_POST['profile_name']));
|
||||
|
@ -241,6 +244,8 @@ function profiles_content(&$a) {
|
|||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't');
|
||||
|
||||
// move every contact using this profile as their default to the user default
|
||||
|
||||
$r = q("UPDATE `contact` SET `profile-id` = (SELECT `profile`.`id` AS `profile-id` FROM `profile` WHERE `profile`.`is-default` = 1 AND `profile`.`uid` = %d LIMIT 1) WHERE `profile-id` = %d AND `uid` = %d ",
|
||||
|
@ -265,6 +270,8 @@ function profiles_content(&$a) {
|
|||
|
||||
if(($a->argc > 1) && ($a->argv[1] === 'new')) {
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't');
|
||||
|
||||
$r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
|
||||
intval(local_user()));
|
||||
$num_profiles = count($r0);
|
||||
|
@ -291,11 +298,14 @@ function profiles_content(&$a) {
|
|||
info( t('New profile created.') . EOL);
|
||||
if(count($r3) == 1)
|
||||
goaway($a->get_baseurl() . '/profiles/' . $r3[0]['id']);
|
||||
|
||||
goaway($a->get_baseurl() . '/profiles');
|
||||
}
|
||||
|
||||
if(($a->argc > 2) && ($a->argv[1] === 'clone')) {
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't');
|
||||
|
||||
$r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
|
||||
intval(local_user()));
|
||||
$num_profiles = count($r0);
|
||||
|
@ -330,8 +340,10 @@ function profiles_content(&$a) {
|
|||
info( t('New profile created.') . EOL);
|
||||
if(count($r3) == 1)
|
||||
goaway($a->get_baseurl() . '/profiles/' . $r3[0]['id']);
|
||||
goaway($a->get_baseurl() . '/profiles');
|
||||
return; // NOTREACHED
|
||||
|
||||
goaway($a->get_baseurl() . '/profiles');
|
||||
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
|
@ -371,6 +383,9 @@ function profiles_content(&$a) {
|
|||
$is_default = (($r[0]['is-default']) ? 1 : 0);
|
||||
$tpl = get_markup_template("profile_edit.tpl");
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$form_security_token' => get_form_security_token("profile_edit"),
|
||||
'$profile_clone_link' => 'profiles/clone/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_clone"),
|
||||
'$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"),
|
||||
'$banner' => t('Edit Profile Details'),
|
||||
'$submit' => t('Submit'),
|
||||
'$viewprof' => t('View this profile'),
|
||||
|
@ -460,7 +475,8 @@ function profiles_content(&$a) {
|
|||
$o .= replace_macros($tpl_header,array(
|
||||
'$header' => t('Edit/Manage Profiles'),
|
||||
'$chg_photo' => t('Change profile photo'),
|
||||
'$cr_new' => t('Create New Profile')
|
||||
'$cr_new' => t('Create New Profile'),
|
||||
'$cr_new_link' => 'profiles/new?t=' . get_form_security_token("profile_new")
|
||||
));
|
||||
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ function settings_post(&$a) {
|
|||
$old_page_flags = $a->user['page-flags'];
|
||||
|
||||
if(($a->argc > 1) && ($a->argv[1] === 'oauth') && x($_POST,'remove')){
|
||||
check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
|
||||
|
||||
$key = $_POST['remove'];
|
||||
q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
|
||||
dbesc($key),
|
||||
|
@ -63,6 +65,8 @@ function settings_post(&$a) {
|
|||
|
||||
if(($a->argc > 2) && ($a->argv[1] === 'oauth') && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && x($_POST,'submit')) {
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
|
||||
|
||||
$name = ((x($_POST,'name')) ? $_POST['name'] : '');
|
||||
$key = ((x($_POST,'key')) ? $_POST['key'] : '');
|
||||
$secret = ((x($_POST,'secret')) ? $_POST['secret'] : '');
|
||||
|
@ -105,13 +109,18 @@ function settings_post(&$a) {
|
|||
}
|
||||
|
||||
if(($a->argc > 1) && ($a->argv[1] == 'addon')) {
|
||||
check_form_security_token_redirectOnErr('/settings/addon', 'settings_addon');
|
||||
|
||||
call_hooks('plugin_settings_post', $_POST);
|
||||
return;
|
||||
}
|
||||
|
||||
if(($a->argc > 1) && ($a->argv[1] == 'connectors')) {
|
||||
|
||||
if(x($_POST['imap-submit'])) {
|
||||
check_form_security_token_redirectOnErr('/settings/connectors', 'settings_connectors');
|
||||
|
||||
if(x($_POST, 'imap-submit')) {
|
||||
|
||||
$mail_server = ((x($_POST,'mail_server')) ? $_POST['mail_server'] : '');
|
||||
$mail_port = ((x($_POST,'mail_port')) ? $_POST['mail_port'] : '');
|
||||
$mail_ssl = ((x($_POST,'mail_ssl')) ? strtolower(trim($_POST['mail_ssl'])) : '');
|
||||
|
@ -185,6 +194,7 @@ function settings_post(&$a) {
|
|||
return;
|
||||
}
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings', 'settings');
|
||||
|
||||
call_hooks('settings_post', $_POST);
|
||||
|
||||
|
@ -460,6 +470,7 @@ function settings_content(&$a) {
|
|||
if(($a->argc > 2) && ($a->argv[2] === 'add')) {
|
||||
$tpl = get_markup_template("settings_oauth_edit.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("settings_oauth"),
|
||||
'$tabs' => $tabs,
|
||||
'$title' => t('Add application'),
|
||||
'$submit' => t('Submit'),
|
||||
|
@ -486,6 +497,7 @@ function settings_content(&$a) {
|
|||
|
||||
$tpl = get_markup_template("settings_oauth_edit.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("settings_oauth"),
|
||||
'$tabs' => $tabs,
|
||||
'$title' => t('Add application'),
|
||||
'$submit' => t('Update'),
|
||||
|
@ -500,6 +512,8 @@ function settings_content(&$a) {
|
|||
}
|
||||
|
||||
if(($a->argc > 3) && ($a->argv[2] === 'delete')) {
|
||||
check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't');
|
||||
|
||||
$r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
|
||||
dbesc($a->argv[3]),
|
||||
local_user());
|
||||
|
@ -518,6 +532,7 @@ function settings_content(&$a) {
|
|||
|
||||
$tpl = get_markup_template("settings_oauth.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("settings_oauth"),
|
||||
'$baseurl' => $a->get_baseurl(),
|
||||
'$title' => t('Connected Apps'),
|
||||
'$add' => t('Add application'),
|
||||
|
@ -544,6 +559,7 @@ function settings_content(&$a) {
|
|||
|
||||
$tpl = get_markup_template("settings_addons.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("settings_addons"),
|
||||
'$title' => t('Plugin Settings'),
|
||||
'$tabs' => $tabs,
|
||||
'$settings_addons' => $settings_addons
|
||||
|
@ -586,28 +602,28 @@ function settings_content(&$a) {
|
|||
|
||||
$tpl = get_markup_template("settings_connectors.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("settings_connectors"),
|
||||
|
||||
'$title' => t('Connector Settings'),
|
||||
'$tabs' => $tabs,
|
||||
|
||||
'$diasp_enabled' => $diasp_enabled,
|
||||
'$ostat_enabled' => $ostat_enabled,
|
||||
|
||||
'$h_imap' => t('Email/Mailbox Setup'),
|
||||
'$imap_desc' => t("If you wish to communicate with email contacts using this service \x28optional\x29, please specify how to connect to your mailbox."),
|
||||
'$imap_lastcheck' => array('imap_lastcheck', t('Last successful email check:'), $mail_chk,''),
|
||||
'$mail_disabled' => (($mail_disabled) ? t('Email access is disabled on this site.') : ''),
|
||||
'$mail_server' => array('mail_server', t('IMAP server name:'), $mail_server, ''),
|
||||
'$mail_port' => array('mail_port', t('IMAP port:'), $mail_port, ''),
|
||||
'$mail_ssl' => array('mail_ssl', t('Security:'), strtoupper($mail_ssl), '', array( ''=>t('None'), 'TLS'=>'TLS', 'SSL'=>'SSL')),
|
||||
'$mail_user' => array('mail_user', t('Email login name:'), $mail_user, ''),
|
||||
'$mail_pass' => array('mail_pass', t('Email password:'), '', ''),
|
||||
'$mail_replyto' => array('mail_replyto', t('Reply-to address:'), '', 'Optional'),
|
||||
'$mail_pubmail' => array('mail_pubmail', t('Send public posts to all email contacts:'), $mail_pubmail, ''),
|
||||
'$mail_action' => array('mail_action', t('Action after import:'), $mail_action, '', array(0=>t('None'), 1=>t('Delete'), 2=>t('Mark as seen'), 3=>t('Move to folder'))),
|
||||
'$mail_movetofolder' => array('mail_movetofolder', t('Move to folder:'), $mail_movetofolder, ''),
|
||||
'$submit' => t('Submit'),
|
||||
|
||||
'$diasp_enabled' => $diasp_enabled,
|
||||
'$ostat_enabled' => $ostat_enabled,
|
||||
|
||||
'$h_imap' => t('Email/Mailbox Setup'),
|
||||
'$imap_desc' => t("If you wish to communicate with email contacts using this service \x28optional\x29, please specify how to connect to your mailbox."),
|
||||
'$imap_lastcheck' => array('imap_lastcheck', t('Last successful email check:'), $mail_chk,''),
|
||||
'$mail_disabled' => (($mail_disabled) ? t('Email access is disabled on this site.') : ''),
|
||||
'$mail_server' => array('mail_server', t('IMAP server name:'), $mail_server, ''),
|
||||
'$mail_port' => array('mail_port', t('IMAP port:'), $mail_port, ''),
|
||||
'$mail_ssl' => array('mail_ssl', t('Security:'), strtoupper($mail_ssl), '', array( ''=>t('None'), 'TLS'=>'TLS', 'SSL'=>'SSL')),
|
||||
'$mail_user' => array('mail_user', t('Email login name:'), $mail_user, ''),
|
||||
'$mail_pass' => array('mail_pass', t('Email password:'), '', ''),
|
||||
'$mail_replyto' => array('mail_replyto', t('Reply-to address:'), '', 'Optional'),
|
||||
'$mail_pubmail' => array('mail_pubmail', t('Send public posts to all email contacts:'), $mail_pubmail, ''),
|
||||
'$mail_action' => array('mail_action', t('Action after import:'), $mail_action, '', array(0=>t('None'), 1=>t('Delete'), 2=>t('Mark as seen'), 3=>t('Move to folder'))),
|
||||
'$mail_movetofolder' => array('mail_movetofolder', t('Move to folder:'), $mail_movetofolder, ''),
|
||||
'$submit' => t('Submit'),
|
||||
|
||||
'$settings_connectors' => $settings_connectors
|
||||
));
|
||||
|
@ -805,6 +821,7 @@ function settings_content(&$a) {
|
|||
'$submit' => t('Submit'),
|
||||
'$baseurl' => $a->get_baseurl(),
|
||||
'$uid' => local_user(),
|
||||
'$form_security_token' => get_form_security_token("settings"),
|
||||
|
||||
'$nickname_block' => $prof_addr,
|
||||
|
||||
|
|
|
@ -7,8 +7,15 @@ $page_desc<br />
|
|||
<li><a href="http://friendica.com" title="$friendica">$friendica</a></li>
|
||||
<li><a href="http://joindiaspora.com" title="$diaspora">$diaspora</a> $diasnote</li>
|
||||
<li><a href="http://ostatus.org" title="$public_net" >$statusnet</a></li>
|
||||
<li>$emailnet</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
$invite_desc
|
||||
</p>
|
||||
<p>
|
||||
$desc
|
||||
</p>
|
||||
|
||||
<form action="dfrn_request/$nickname" method="post" />
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ $desc
|
|||
</script>
|
||||
|
||||
<form action="profile_photo/$resource" id="crop-image-form" method="post" />
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
<input type="hidden" name="cropfinal" value="1" />
|
||||
<input type="hidden" name="xstart" id="x1" />
|
||||
|
|
|
@ -7,7 +7,11 @@ $page_desc<br />
|
|||
<li><a href="http://friendica.com" title="$friendica">$friendica</a></li>
|
||||
<li><a href="http://joindiaspora.com" title="$diaspora">$diaspora</a> $diasnote</li>
|
||||
<li><a href="http://ostatus.org" title="$public_net" >$statusnet</a></li>
|
||||
<li>$emailnet</li>
|
||||
</ul>
|
||||
$invite_desc
|
||||
</p>
|
||||
<p>
|
||||
$desc
|
||||
</p>
|
||||
|
||||
|
|
12
view/fileas_widget.tpl
Executable file
12
view/fileas_widget.tpl
Executable file
|
@ -0,0 +1,12 @@
|
|||
<div id="fileas-sidebar" class="widget">
|
||||
<h3>$title</h3>
|
||||
<div id="nets-desc">$desc</div>
|
||||
|
||||
<ul class="fileas-ul">
|
||||
<li class="tool"><a href="$base" class="fileas-link fileas-all{{ if $sel_all }} fileas-selected{{ endif }}">$all</a></li>
|
||||
{{ for $terms as $term }}
|
||||
<li class="tool"><a href="$base?f=&file=$term.name" class="fileas-link{{ if $term.selected }} fileas-selected{{ endif }}">$term.name</a></li>
|
||||
{{ endfor }}
|
||||
</ul>
|
||||
|
||||
</div>
|
|
@ -262,6 +262,18 @@ function enableOnUser(){
|
|||
}
|
||||
}
|
||||
|
||||
function itemFiler(id) {
|
||||
reply = prompt("$fileas");
|
||||
if(reply && reply.length) {
|
||||
commentBusy = true;
|
||||
$('body').css('cursor', 'wait');
|
||||
$.get('filer/' + id + '?term=' + reply);
|
||||
if(timer) clearTimeout(timer);
|
||||
timer = setTimeout(NavUpdate,3000);
|
||||
liking = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function jotClearLocation() {
|
||||
$('#jot-coord').val('');
|
||||
$('#profile-nolocation-wrapper').hide();
|
||||
|
|
|
@ -5,9 +5,9 @@ $default
|
|||
<div id="profile-edit-links">
|
||||
<ul>
|
||||
<li><a href="profile/$profile_id/view?tab=profile" id="profile-edit-view-link" title="$viewprof">$viewprof</a></li>
|
||||
<li><a href="profiles/clone/$profile_id" id="profile-edit-clone-link" title="$cr_prof">$cl_prof</a></li>
|
||||
<li><a href="$profile_clone_link" id="profile-edit-clone-link" title="$cr_prof">$cl_prof</a></li>
|
||||
<li></li>
|
||||
<li><a href="profiles/drop/$profile_id" id="profile-edit-drop-link" title="$del_prof" $disabled >$del_prof</a></li>
|
||||
<li><a href="$profile_drop_link" id="profile-edit-drop-link" title="$del_prof" $disabled >$del_prof</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -17,6 +17,7 @@ $default
|
|||
|
||||
<div id="profile-edit-wrapper" >
|
||||
<form id="profile-edit-form" name="form1" action="profiles/$profile_id" method="post" >
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
<div id="profile-edit-profile-name-wrapper" >
|
||||
<label id="profile-edit-profile-name-label" for="profile-edit-profile-name" >$lbl_profname </label>
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
<a href="profile_photo" >$chg_photo</a>
|
||||
</p>
|
||||
<div id="profile-listing-new-link-wrapper" class="button" >
|
||||
<a href="profiles/new" id="profile-listing-new-link" title="$cr_new" >$cr_new</a>
|
||||
<a href="$cr_new_link" id="profile-listing-new-link" title="$cr_new" >$cr_new</a>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<h1>$title</h1>
|
||||
|
||||
<form enctype="multipart/form-data" action="profile_photo" method="post">
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
<div id="profile-photo-upload-wrapper">
|
||||
<label id="profile-photo-upload-label" for="profile-photo-upload">$lbl_upfile </label>
|
||||
|
|
|
@ -5,7 +5,7 @@ $tabs
|
|||
$nickname_block
|
||||
|
||||
<form action="settings" id="settings-form" method="post" autocomplete="off" >
|
||||
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
<h3 class="settings-heading">$h_pass</h3>
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ $tabs
|
|||
|
||||
|
||||
<form action="settings/addon" method="post" autocomplete="off">
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
$settings_addons
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ $tabs
|
|||
<div class="connector_statusmsg">$ostat_enabled</div>
|
||||
|
||||
<form action="settings/connectors" method="post" autocomplete="off">
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
$settings_connectors
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ $tabs
|
|||
|
||||
|
||||
<form action="settings/oauth" method="post" autocomplete="off">
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
<div id="profile-edit-links">
|
||||
<ul>
|
||||
|
@ -24,7 +25,7 @@ $tabs
|
|||
{{ endif }}
|
||||
{{ if $app.my }}
|
||||
<a href="$baseurl/settings/oauth/edit/$app.client_id" class="icon s22 edit" title="$edit"> </a>
|
||||
<a href="$baseurl/settings/oauth/delete/$app.client_id" class="icon s22 delete" title="$delete"> </a>
|
||||
<a href="$baseurl/settings/oauth/delete/$app.client_id?t=$form_security_token" class="icon s22 delete" title="$delete"> </a>
|
||||
{{ endif }}
|
||||
</div>
|
||||
{{ endfor }}
|
||||
|
|
|
@ -3,6 +3,8 @@ $tabs
|
|||
<h1>$title</h1>
|
||||
|
||||
<form method="POST">
|
||||
<input type='hidden' name='form_security_token' value='$form_security_token'>
|
||||
|
||||
{{ inc field_input.tpl with $field=$name }}{{ endinc }}
|
||||
{{ inc field_input.tpl with $field=$key }}{{ endinc }}
|
||||
{{ inc field_input.tpl with $field=$secret }}{{ endinc }}
|
||||
|
|
BIN
view/theme/duepuntozero/file.gif
Normal file
BIN
view/theme/duepuntozero/file.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 615 B |
|
@ -309,7 +309,7 @@ div.wall-item-content-wrapper.shiny {
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.group-selected, .nets-selected {
|
||||
.group-selected, .nets-selected, .fileas-selected {
|
||||
padding: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
|
@ -1024,6 +1024,10 @@ input#dfrn-url {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.filer-item {
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.wall-item-links-wrapper {
|
||||
float: left;
|
||||
|
@ -1864,11 +1868,11 @@ a.mail-list-link {
|
|||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.nets-ul {
|
||||
.nets-ul, .fileas-ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.nets-ul li {
|
||||
.nets-ul li, .fileas-ul li {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
@ -1879,6 +1883,14 @@ a.mail-list-link {
|
|||
margin-left: 42px;
|
||||
}
|
||||
|
||||
.fileas-link {
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.fileas-all {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
#search-save {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
@ -2902,6 +2914,11 @@ aside input[type='text'] {
|
|||
.tagged { background-position: -48px -48px; }
|
||||
|
||||
|
||||
.filer-icon {
|
||||
display: block; width: 16px; height: 16px;
|
||||
background-image: url('file.gif');
|
||||
}
|
||||
|
||||
.icon.dim { opacity: 0.3;filter:alpha(opacity=30); }
|
||||
|
||||
.attachtype {
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
{{ if $item.star }}
|
||||
<a href="#" id="starred-$item.id" onclick="dostar($item.id); return false;" class="star-item icon $item.isstarred" title="$item.star.toggle"></a>
|
||||
<a href="#" id="tagger-$item.id" onclick="itemTag($item.id); return false;" class="tag-item icon tagged" title="$item.star.tagger"></a>
|
||||
<a href="#" id="filer-$item.id" onclick="itemFiler($item.id); return false;" class="filer-item filer-icon" title="$item.star.filer"></a>
|
||||
{{ endif }}
|
||||
|
||||
<div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-$item.id" >
|
||||
|
|
BIN
view/theme/greenzero/file.gif
Normal file
BIN
view/theme/greenzero/file.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 614 B |
Loading…
Reference in a new issue