From afd0f8e4d8ff0a37d1a337f160eeae642a2f07d6 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 12:51:36 +0200
Subject: [PATCH 01/20] load $a->config from db
---
index.php | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/index.php b/index.php
index 534cb93f7..9bca1527b 100644
--- a/index.php
+++ b/index.php
@@ -29,7 +29,6 @@ $install = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? false
@include(".htconfig.php");
-
$lang = get_language();
load_translation_table($lang);
@@ -45,6 +44,20 @@ $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
unset($db_host, $db_user, $db_pass, $db_data);
+/**
+ * Load configs from db. Overwrite configs from .htconfig.php
+ */
+$r = q("SELECT * FROM `config` WHERE `cat` IN ('system', 'config')");
+foreach ($r as $c) {
+ if ($c['cat']=='config') {
+ $a->config[$c['k']] = $c['v'];
+ } else {
+ $a->config[$c['cat']][$c['k']] = $c['v'];
+ }
+}
+unset($r);
+
+
/**
*
* Important stuff we always need to do.
From 3364c2a2d8ab88703c5566a39df13ef1042f8644 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 12:52:29 +0200
Subject: [PATCH 02/20] Initial admin page
---
mod/admin.php | 105 +++++++++++++++++++++++++++++++++++++++++
view/admin_aside.tpl | 20 ++++++++
view/admin_summary.tpl | 33 +++++++++++++
3 files changed, 158 insertions(+)
create mode 100644 mod/admin.php
create mode 100644 view/admin_aside.tpl
create mode 100644 view/admin_summary.tpl
diff --git a/mod/admin.php b/mod/admin.php
new file mode 100644
index 000000000..13131f013
--- /dev/null
+++ b/mod/admin.php
@@ -0,0 +1,105 @@
+ Array($a->get_baseurl()."/admin/site/", t("Site") , "site"),
+ 'users' => Array($a->get_baseurl()."/admin/users/", t("Users") , "users"),
+ 'plugins'=> Array($a->get_baseurl()."/admin/plugins/", t("Plugins") , "plugins")
+ );
+
+ /* get plugins admin page */
+
+ $r = q("SELECT * FROM `hook` WHERE `hook`='plugin_admin'");
+ $aside['plugins_admin']=Array();
+ foreach ($r as $h){
+ $plugin = explode("/",$h['file']); $plugin = $plugin[1];
+ $aside['plugins_admin'][] = Array($a->get_baseurl()."/admin/plugins/".$plugin, $plugin, "plugin");
+ }
+
+ $aside['logs'] = Array($a->get_baseurl()."/admin/logs/", t("Logs"), "logs");
+
+ $t = get_markup_template("admin_aside.tpl");
+ $a->page['aside'] = replace_macros( $t, array('$admin' => $aside) );
+
+
+
+ /**
+ * Page content
+ */
+ $o = '';
+
+ // urls
+ if ($a->argc > 1){
+ switch ($a->argv[1]){
+ case 'site': {
+ $o = admin_page_site($a);
+ break;
+ }
+ default:
+ notice( t("Item not found.") );
+ }
+ } else {
+ $o = admin_page_summary($a);
+ }
+ return $o;
+}
+
+
+/**
+ * Admin Summary Page
+ */
+function admin_page_summary(&$a) {
+ $r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
+ $accounts = Array(
+ Array( t('Normal Account'), 0),
+ Array( t('Soapbox Account'), 0),
+ Array( t('Community/Celebrity Account'), 0),
+ Array( t('Automatic Friend Account'), 0)
+ );
+ $users=0;
+ foreach ($r as $u){ $accounts[$u['page-flags']][1] = $u['count']; $users+=$u['count']; }
+
+ //echo ""; var_dump($a->plugins); die(" ");
+
+
+ $r = q("SELECT COUNT(id) as `count` FROM `register`");
+ $pending = $r[0]['count'];
+
+
+
+
+
+ $t = get_markup_template("admin_summary.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Summary'),
+ '$users' => Array( t('Registered users'), $users),
+ '$accounts' => $accounts,
+ '$pending' => Array( t('Pending registrations'), $pending),
+ '$version' => Array( t('Version'), FRIENDIKA_VERSION),
+ '$build' => get_config('system','build'),
+ '$plugins' => Array( t('Active plugins'), $a->plugins )
+ ));
+}
diff --git a/view/admin_aside.tpl b/view/admin_aside.tpl
new file mode 100644
index 000000000..24aafa775
--- /dev/null
+++ b/view/admin_aside.tpl
@@ -0,0 +1,20 @@
+Admin
+
+
+
+{{ if $admin.plugins_admin }}Plugins {{ endif }}
+
+ {{ for $admin.plugins_admin as $l }}
+ $l.1
+ {{ endfor }}
+
+
+
+Logs
+
diff --git a/view/admin_summary.tpl b/view/admin_summary.tpl
new file mode 100644
index 000000000..cbd659d07
--- /dev/null
+++ b/view/admin_summary.tpl
@@ -0,0 +1,33 @@
+$title - $page
+
+
+ $users.0
+ $users.1
+
+{{ for $accounts as $p }}
+
+ $p.0
+ $p.1
+
+{{ endfor }}
+
+
+ $pending.0
+ $pending.1
+
+
+
+ $version.0
+ $version.1 - $build
+
+
+
+
+
+ $plugins.0
+
+ {{ for $plugins.1 as $p }}
+ $p
+ {{ endfor }}
+
+
From 494288ab9f9370bdf4f7b4ab9990b64f05adbd9d Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 12:52:52 +0200
Subject: [PATCH 03/20] Add admin page in nav
---
include/nav.php | 9 +++++++--
view/nav.tpl | 2 ++
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/include/nav.php b/include/nav.php
index 66fdbc49b..5e50a8b79 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -107,10 +107,15 @@ function nav(&$a) {
$nav['settings'] = array('settings', t('Settings'),"");
$nav['profiles'] = array('profiles', t('Profiles'),"");
$nav['contacts'] = array('contacts', t('Contacts'),"");
-
-
}
+ /**
+ * Admin page
+ */
+ if (is_site_admin()){
+ $nav['admin'] = array('admin/', t('Admin'), "");
+ }
+
/**
*
diff --git a/view/nav.tpl b/view/nav.tpl
index 7e76811d9..79114749a 100644
--- a/view/nav.tpl
+++ b/view/nav.tpl
@@ -16,6 +16,8 @@ $langselector
$nav.search.1
$nav.directory.1
+{{ if $nav.admin }}$nav.admin.1 {{ endif }}
+
{{ if $nav.network }}
$nav.network.1
From a1c59d6011138ca2a0d366d1ea6f6369e679df81 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 12:53:03 +0200
Subject: [PATCH 04/20] Fix it strings
---
view/it/strings.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/view/it/strings.php b/view/it/strings.php
index 75459e23a..32092a3f1 100644
--- a/view/it/strings.php
+++ b/view/it/strings.php
@@ -123,7 +123,7 @@ $a->strings["Administrator"] = "Amministratore";
$a->strings["Friend/Connection Request"] = "Richieste di Amicizia/Connessione";
$a->strings["Examples: jojo@demo.friendika.com, http://demo.friendika.com/profile/jojo, testuser@identi.ca"] = "Esempi: jojo@demo.friendika.com, http://demo.friendika.com/profile/jojo, testuser@identi.ca";
$a->strings["Please answer the following:"] = "Rispondi al seguente:";
-$a->strings["Does \$name know you?"] = "$name ti conosce?";
+$a->strings["Does \$name know you?"] = "\$name ti conosce?";
$a->strings["Yes"] = "Si";
$a->strings["No"] = "No";
$a->strings["Add a personal note:"] = "Aggiungi una nota personale:";
From e14d5851a76e73675800787dcbcc7582b4dbd5ed Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 12:53:41 +0200
Subject: [PATCH 05/20] fix template's {{ for }} variable lookup
---
include/template_processor.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/template_processor.php b/include/template_processor.php
index d8dfbaedb..3dc249c40 100644
--- a/include/template_processor.php
+++ b/include/template_processor.php
@@ -58,7 +58,8 @@
list($keyname, $varname) = explode("=>",$m[1]);
if (is_null($varname)) { $varname=$keyname; $keyname=""; }
if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ;
- $vals = $this->r[$m[0]];
+ //$vals = $this->r[$m[0]];
+ $vals = $this->_get_var($m[0]);
$ret="";
if (!is_array($vals)) return $ret;
foreach ($vals as $k=>$v){
From f80521923d35d15dfd2f0ea24359a08a02638845 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 18:02:40 +0200
Subject: [PATCH 06/20] Add {{ if a==b }} and {{ if a!=b }} to templates
---
include/template_processor.php | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/template_processor.php b/include/template_processor.php
index 3dc249c40..a2c24b00b 100644
--- a/include/template_processor.php
+++ b/include/template_processor.php
@@ -41,9 +41,24 @@
* IF node
*
* {{ if <$var> }}...{{ endif }}
+ * {{ if <$var>== }}...{{ endif }}
+ * {{ if <$var>!= }}...{{ endif }}
*/
private function _replcb_if($args){
- $val = $this->_get_var($args[2]);
+
+ if (strpos($args[2],"==")>0){
+ list($a,$b) = array_map("trim",explode("==",$args[2]));
+ $a = $this->_get_var($a);
+ if ($b[0]=="$") $b = $this->_get_var($b);
+ $val = ($a == $b);
+ } else if (strpos($args[2],"!=")>0){
+ list($a,$b) = explode("!=",$args[2]);
+ $a = $this->_get_var($a);
+ if ($b[0]=="$") $b = $this->_get_var($b);
+ $val = ($a != $b);
+ } else {
+ $val = $this->_get_var($args[2]);
+ }
return ($val?$args[3]:"");
}
From ab27f1393e72e8fa6c05db5948413beef9e0367f Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Mon, 13 Jun 2011 18:03:06 +0200
Subject: [PATCH 07/20] Admin site page
---
mod/admin.php | 191 +++++++++++++++++++++++++++++-
view/admin_aside.tpl | 2 +-
view/admin_site.tpl | 45 +++++++
view/admin_summary.tpl | 59 ++++-----
view/field.tpl | 4 +
view/field_checkbox.tpl | 6 +
view/field_input.tpl | 6 +
view/field_select.tpl | 8 ++
view/field_textarea.tpl | 6 +
view/theme/duepuntozero/style.css | 52 ++++++++
10 files changed, 347 insertions(+), 32 deletions(-)
create mode 100644 view/admin_site.tpl
create mode 100644 view/field.tpl
create mode 100644 view/field_checkbox.tpl
create mode 100644 view/field_input.tpl
create mode 100644 view/field_select.tpl
create mode 100644 view/field_textarea.tpl
diff --git a/mod/admin.php b/mod/admin.php
index 13131f013..70720f5d8 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -11,6 +11,24 @@ function admin_init(&$a) {
}
}
+function admin_post(&$a){
+ if(!is_site_admin()) {
+ return login(false);
+ }
+
+ // urls
+ if ($a->argc > 1){
+ switch ($a->argv[1]){
+ case 'site': {
+ admin_page_site_post($a);
+ break;
+ }
+ }
+ }
+
+ goaway($a->get_baseurl() . '/admin' );
+ return; // NOTREACHED
+}
function admin_content(&$a) {
@@ -41,7 +59,10 @@ function admin_content(&$a) {
$aside['logs'] = Array($a->get_baseurl()."/admin/logs/", t("Logs"), "logs");
$t = get_markup_template("admin_aside.tpl");
- $a->page['aside'] = replace_macros( $t, array('$admin' => $aside) );
+ $a->page['aside'] = replace_macros( $t, array(
+ '$admin' => $aside,
+ '$admurl'=> $a->get_baseurl()."/admin/"
+ ));
@@ -81,8 +102,6 @@ function admin_page_summary(&$a) {
$users=0;
foreach ($r as $u){ $accounts[$u['page-flags']][1] = $u['count']; $users+=$u['count']; }
- //echo ""; var_dump($a->plugins); die(" ");
-
$r = q("SELECT COUNT(id) as `count` FROM `register`");
$pending = $r[0]['count'];
@@ -103,3 +122,169 @@ function admin_page_summary(&$a) {
'$plugins' => Array( t('Active plugins'), $a->plugins )
));
}
+
+
+/**
+ * Admin Site Page
+ */
+function admin_page_site_post(&$a){
+ if (!x($_POST,"page_site")){
+ return;
+ }
+
+
+ $sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : '');
+ $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false);
+ $language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : '');
+ $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
+ $maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0);
+ $allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : '');
+ $allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
+ $block_public = ((x($_POST,'block_public')) ? True : False);
+ $force_publish = ((x($_POST,'publish_all')) ? True : False);
+ $global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
+ $global_search_url = ((x($_POST,'directory_search_url'))? notags(trim($_POST['directory_search_url'])) : '');
+ $no_multi_reg = ((x($_POST,'no_multi_reg')) ? True : False);
+ $no_openid = ((x($_POST,'no_openid')) ? True : False);
+ $no_gravatar = ((x($_POST,'no_gravatar')) ? True : False);
+ $no_regfullname = ((x($_POST,'no_regfullname')) ? True : False);
+ $no_utf = ((x($_POST,'no_utf')) ? True : False);
+ $rino_enc = ((x($_POST,'rino_enc')) ? True : False);
+ $verifyssl = ((x($_POST,'verifyssl')) ? True : False);
+ $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['global_search_url'])) : '');
+ $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['global_search_url'])) : '');
+ $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['maximagesize'])) : 60);
+
+
+ $a->config['sitename'] = $sitename;
+ if ($banner==""){
+ // don't know why, but del_config doesn't work...
+ q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
+ dbesc("system"),
+ dbesc("banner")
+ );
+ } else {
+ set_config('system','banner', $banner);
+ }
+ set_config('system','language', $language);
+ set_config('system','theme', $theme);
+ set_config('system','maximagesize', $maximagesize);
+ set_config('system','allowed_sites', $allowed_sites);
+ set_config('system','allowed_email', $allowed_email);
+ set_config('system','block_public', $block_public);
+ set_config('system','publish_all', $force_publish);
+ if ($global_directory==""){
+ // don't know why, but del_config doesn't work...
+ q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
+ dbesc("system"),
+ dbesc("directory_submit_url")
+ );
+ } else {
+ set_config('system','directory_submit_url', $global_directory);
+ }
+ set_config('system','directory_search_url', $global_search_url);
+ set_config('system','block_extended_register', $no_multi_reg);
+ set_config('system','no_openid', $no_openid);
+ set_config('system','no_gravatar', $no_gravatar);
+ set_config('system','no_regfullname', $no_regfullname);
+ set_config('system','proxy', $no_utf);
+ set_config('system','rino_encrypt', $rino_enc);
+ set_config('system','verifyssl', $verifyssl);
+ set_config('system','proxyuser', $proxyuser);
+ set_config('system','proxy', $proxy);
+ set_config('system','curl_timeout', $timeout);
+
+ $r = q("SELECT * FROM `config` WHERE `cat`='config' AND `k`='sitename'");
+ if (count($r)>0){
+ q("UPDATE `config` SET `v`='%s' WHERE `cat`='config' AND `k`='sitename'",
+ dbesc($a->config['sitename'])
+ );
+ } else {
+ q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( 'config', 'sitename', '%s' )",
+ dbesc($a->config['sitename'])
+ );
+ }
+
+
+
+ goaway($a->get_baseurl() . '/admin/site' );
+ return; // NOTREACHED
+
+}
+
+function admin_page_site(&$a) {
+
+ /* Installed langs */
+ $lang_choices = array();
+ $langs = glob('view/*/strings.php');
+
+ if(is_array($langs) && count($langs)) {
+ if(! in_array('view/en/strings.php',$langs))
+ $langs[] = 'view/en/';
+ asort($langs);
+ foreach($langs as $l) {
+ $t = explode("/",$l);
+ $lang_choices[$t[1]] = $t[1];
+ }
+ }
+
+ /* Installed themes */
+ $theme_choices = array();
+ $files = glob('view/theme/*');
+ if($files) {
+ foreach($files as $file) {
+ $f = basename($file);
+ $theme_name = ((file_exists($file . '/experimental')) ? sprintf("%s - \x28Experimental\x29", $f) : $f);
+ $theme_choices[$f] = $theme_name;
+ }
+ }
+
+
+ /* Banner */
+ $banner = get_config('system','banner');
+ if($banner == false)
+ $banner = htmlspecialchars('Friendika ');
+
+ //echo ""; var_dump($lang_choices); die(" ");
+
+
+
+ $t = get_markup_template("admin_site.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Site'),
+ '$submit' => t('Submit'),
+ '$baseurl' => $a->get_baseurl(),
+
+ // name, label, value, help string, extra data...
+ '$sitename' => array('sitename', t("Site name"), $a->config['sitename'], ""),
+ '$banner' => array('banner', t("Banner/Logo"), $banner, ""),
+ '$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
+ '$theme' => array('theme', t("System theme"), get_config('system','theme'), "Default system theme (which may be over-ridden by user profiles)", $theme_choices),
+
+ '$maximagesize' => array('maximagesize', t("Maximum image size"), get_config('system','maximagesize'), "Maximum size in bytes of uploaded images. Default is 0, which means no limits."),
+
+ '$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), "Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains"),
+ '$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), "Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains"),
+ '$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), "Check to block public access to all otherwise public personal pages on this site unless you are currently logged in."),
+ '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), "Check to force all profiles on this site to be listed in the site directory."),
+ '$global_directory' => array('directory_submit_url', t("Global directory update URL"), get_config('system','directory_submit_url'), "URL to update the global directory. If this is not set, the global directory is completely unavailable to the application."),
+ '$global_search_url'=> array('directory_search_url', t("Global directory search URL"), get_config('system','directory_search_url'), ""),
+
+
+ '$no_multi_reg' => array('no_multi_reg', t("Block multiple registrations"), get_config('system','block_extended_register'), "Disallow users to register additional accounts for use as pages."),
+ '$no_openid' => array('no_openid', t("No OpenID support"), get_config('system','no_openid'), "Disable OpenID support for registration and logins."),
+ '$no_gravatar' => array('no_gravatar', t("No Gravatar support"), get_config('system','no_gravatar'), ""),
+ '$no_regfullname' => array('no_regfullname', t("No fullname check"), get_config('system','no_regfullname'), "If unchecked, force users to registrate with a space between his firsname and lastname in Full name, as an antispam measure"),
+ '$no_utf' => array('no_utf', t("No UTF-8 Regular expressions"), get_config('system','proxy'), "Default is false (meaning UTF8 regular expressions are supported and working)"),
+
+ '$rino_enc' => array('rino_enc', t("Enable Rino encrypt"), get_config('system','rino_encrypt'),""),
+ '$verifyssl' => array('verifyssl', t("Verify SSL"), get_config('system','verifyssl'), "If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites."),
+ '$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
+ '$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
+ '$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), "Value is in seconds. Set to 0 for unlimited (not recommended)."),
+
+
+ ));
+
+}
diff --git a/view/admin_aside.tpl b/view/admin_aside.tpl
index 24aafa775..dd81a6fee 100644
--- a/view/admin_aside.tpl
+++ b/view/admin_aside.tpl
@@ -1,4 +1,4 @@
-Admin
+
$admin.site.1
$admin.users.1
diff --git a/view/admin_site.tpl b/view/admin_site.tpl
new file mode 100644
index 000000000..f120461aa
--- /dev/null
+++ b/view/admin_site.tpl
@@ -0,0 +1,45 @@
+
diff --git a/view/admin_summary.tpl b/view/admin_summary.tpl
index cbd659d07..59428986a 100644
--- a/view/admin_summary.tpl
+++ b/view/admin_summary.tpl
@@ -1,33 +1,36 @@
-$title - $page
+
+
$title - $page
-
- $users.0
- $users.1
-
-{{ for $accounts as $p }}
- $p.0
- $p.1
+ $pending.0
+ $pending.1
-{{ endfor }}
-
- $pending.0
- $pending.1
-
-
-
- $version.0
- $version.1 - $build
-
-
-
-
-
- $plugins.0
-
- {{ for $plugins.1 as $p }}
- $p
+
+ $users.0
+ $users.1
+
+ {{ for $accounts as $p }}
+
+ $p.0
+ $p.1
+
{{ endfor }}
-
-
+
+
+
+ $plugins.0
+
+ {{ for $plugins.1 as $p }}
+ $p
+ {{ endfor }}
+
+
+
+
+ $version.0
+ $version.1 - $build
+
+
+
+
diff --git a/view/field.tpl b/view/field.tpl
new file mode 100644
index 000000000..35f5afd39
--- /dev/null
+++ b/view/field.tpl
@@ -0,0 +1,4 @@
+
+ {{ if $field.0==select }}
+ {{ inc field_select.tpl }}{{ endinc }}
+ {{ endif }}
diff --git a/view/field_checkbox.tpl b/view/field_checkbox.tpl
new file mode 100644
index 000000000..4a86da7ea
--- /dev/null
+++ b/view/field_checkbox.tpl
@@ -0,0 +1,6 @@
+
+
+ $field.1
+
+ $field.3
+
diff --git a/view/field_input.tpl b/view/field_input.tpl
new file mode 100644
index 000000000..748d93f3e
--- /dev/null
+++ b/view/field_input.tpl
@@ -0,0 +1,6 @@
+
+
+ $field.1
+
+ $field.3
+
diff --git a/view/field_select.tpl b/view/field_select.tpl
new file mode 100644
index 000000000..d79eb48e0
--- /dev/null
+++ b/view/field_select.tpl
@@ -0,0 +1,8 @@
+
+
+ $field.1
+
+ {{ for $field.4 as $opt=>$val }}$val {{ endfor }}
+
+ $field.3
+
diff --git a/view/field_textarea.tpl b/view/field_textarea.tpl
new file mode 100644
index 000000000..2425cdd3b
--- /dev/null
+++ b/view/field_textarea.tpl
@@ -0,0 +1,6 @@
+
+
+ $field.1
+
+ $field.3
+
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index 892814804..294a86690 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -2468,6 +2468,58 @@ a.mail-list-link {
filter:alpha(opacity=100);
}
+/**
+ * ADMIN
+ */
+
+#adminpage dl {
+ clear: left;
+ margin-bottom: 2px;
+ padding-bottom: 2px;
+ border-bottom: 1px solid black;
+}
+#adminpage dt {
+ width: 200px;
+ float: left;
+ font-weight: bold;
+}
+#adminpage dd {
+ margin-left: 200px;
+}
+
+#adminpage .field {
+ clear: left;
+ margin-bottom: 5px;
+ padding-bottom: 5px;
+}
+
+#adminpage .field label {
+ float: left;
+ width: 200px;
+ font-weight: bold;
+}
+
+#adminpage .field input,
+#adminpage .field textarea {
+ width: 400px;
+}
+#adminpage .field textarea { height: 100px; }
+#adminpage .field_help {
+ display: block;
+ margin-left: 200px;
+ color: #666666;
+
+}
+
+#adminpage h3 {
+ border-bottom: 1px solid #cccccc;
+}
+
+#adminpage .submit {
+ clear:left;
+ text-align: right;
+}
+
/**
* ICONS
From 4ba23df20a46bec640177df0555b5d98486c8540 Mon Sep 17 00:00:00 2001
From: fabrixxm
Date: Mon, 13 Jun 2011 18:29:14 +0200
Subject: [PATCH 08/20] fix a typo in site settings page
---
mod/admin.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mod/admin.php b/mod/admin.php
index 70720f5d8..73da3814b 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -153,7 +153,7 @@ function admin_page_site_post(&$a){
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['global_search_url'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['global_search_url'])) : '');
- $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['maximagesize'])) : 60);
+ $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
$a->config['sitename'] = $sitename;
From 5882d8d022c14a12ba7b314c96289061bd195ed4 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Tue, 14 Jun 2011 10:35:56 +0200
Subject: [PATCH 09/20] Initial plugins admin page
---
mod/admin.php | 51 +++++++++++++++++++++++++++++--
view/admin_plugins.tpl | 14 +++++++++
view/theme/duepuntozero/style.css | 18 ++++++++++-
3 files changed, 80 insertions(+), 3 deletions(-)
create mode 100644 view/admin_plugins.tpl
diff --git a/mod/admin.php b/mod/admin.php
index 73da3814b..f9d248210 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -74,10 +74,15 @@ function admin_content(&$a) {
// urls
if ($a->argc > 1){
switch ($a->argv[1]){
- case 'site': {
+ case 'site':
$o = admin_page_site($a);
break;
- }
+ case 'users':
+ $o = admin_page_users($a);
+ break;
+ case 'plugins':
+ $o = admin_page_plugins($a);
+ break;
default:
notice( t("Item not found.") );
}
@@ -288,3 +293,45 @@ function admin_page_site(&$a) {
));
}
+
+
+/**
+ * Users admin page
+ */
+
+function admin_page_users(&$a){
+ return ":)";
+}
+
+
+/*
+ * Plugins admin page
+ */
+
+function admin_page_plugins(&$a){
+
+ /* all plugins */
+ $plugins = array();
+ $files = glob("addon/*/");
+ if($files) {
+ foreach($files as $file) {
+ if (is_dir($file)){
+ list($tmp, $id)=array_map("trim", explode("/",$file));
+ // TODO: plugins info
+ $name=$author=$description=$homepage="";
+ $plugins[] = array( $id, (in_array($id, $a->plugins)?"on":"off") , $name, $author, $description, $homepage);
+ }
+ }
+ }
+
+ $t = get_markup_template("admin_plugins.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Plugins'),
+ '$submit' => t('Submit'),
+ '$baseurl' => $a->get_baseurl(),
+
+ '$plugins' => $plugins
+ ));
+}
+
diff --git a/view/admin_plugins.tpl b/view/admin_plugins.tpl
new file mode 100644
index 000000000..d29665a06
--- /dev/null
+++ b/view/admin_plugins.tpl
@@ -0,0 +1,14 @@
+
+
$title - $page
+
+
+ {{ for $plugins as $p }}
+
+
+
+ $p.0
+
+
+ {{ endfor }}
+
+
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index 294a86690..8799726c7 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -2520,6 +2520,21 @@ a.mail-list-link {
text-align: right;
}
+#adminpage #pluginslist {
+ margin: 0px; padding: 0px;
+}
+#adminpage .plugin {
+ list-style: none;
+ display: block;
+ border: 1px solid #888888;
+ padding: 1em;
+ margin-bottom: 5px;
+ clear: left;
+}
+#adminpage .plugin .toggle {
+ float:left;
+ margin-right: 1em;
+}
/**
* ICONS
@@ -2557,7 +2572,8 @@ a.mail-list-link {
.youtube { background-position: -64px -32px;}
.attach { background-position: -80px -32px; }
.language { background-position: -96px -32px; }
-
+.on { background-position: -112px -32px; }
+.off { background-position: -128px -32px; }
.attachtype {
display: block; width: 20px; height: 23px;
From 5dc8fbccb29169601ad5fed2b5289631e32e5ac5 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Tue, 14 Jun 2011 11:16:27 +0200
Subject: [PATCH 10/20] enable/disable plugins from admin page
---
boot.php | 54 +++++++++++++++++++++++++++++------------------
images/icons.png | Bin 10126 -> 10702 bytes
mod/admin.php | 53 +++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 85 insertions(+), 22 deletions(-)
diff --git a/boot.php b/boot.php
index 8edc74910..42b0ca41e 100644
--- a/boot.php
+++ b/boot.php
@@ -453,6 +453,37 @@ function system_unavailable() {
killme();
}}
+
+// install and uninstall plugin
+if (! function_exists('uninstall_plugin')){
+function uninstall_plugin($plugin){
+ logger("Addons: uninstalling " . $plugin);
+ q("DELETE FROM `addon` WHERE `name` = '%s' LIMIT 1",
+ dbesc($plugin)
+ );
+
+ @include_once('addon/' . $plugin . '/' . $plugin . '.php');
+ if(function_exists($plugin . '_uninstall')) {
+ $func = $plugin . '_uninstall';
+ $func();
+ }
+}}
+
+if (! function_exists('install_plugin')){
+function install_plugin($plugin){
+ logger("Addons: installing " . $plugin);
+ $t = filemtime('addon/' . $plugin . '/' . $plugin . '.php');
+ @include_once('addon/' . $plugin . '/' . $plugin . '.php');
+ if(function_exists($plugin . '_install')) {
+ $func = $plugin . '_install';
+ $func();
+ $r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`) VALUES ( '%s', 1, %d ) ",
+ dbesc($plugin),
+ intval($t)
+ );
+ }
+}}
+
// Primarily involved with database upgrade, but also sets the
// base url for use in cmdline programs which don't have
// $_SERVER variables, and synchronising the state of installed plugins.
@@ -538,16 +569,7 @@ function check_config(&$a) {
if(count($installed)) {
foreach($installed as $i) {
if(! in_array($i['name'],$plugins_arr)) {
- logger("Addons: uninstalling " . $i['name']);
- q("DELETE FROM `addon` WHERE `id` = %d LIMIT 1",
- intval($i['id'])
- );
-
- @include_once('addon/' . $i['name'] . '/' . $i['name'] . '.php');
- if(function_exists($i['name'] . '_uninstall')) {
- $func = $i['name'] . '_uninstall';
- $func();
- }
+ uninstall_plugin($i['name']);
}
else
$installed_arr[] = $i['name'];
@@ -557,17 +579,7 @@ function check_config(&$a) {
if(count($plugins_arr)) {
foreach($plugins_arr as $p) {
if(! in_array($p,$installed_arr)) {
- logger("Addons: installing " . $p);
- $t = filemtime('addon/' . $p . '/' . $p . '.php');
- @include_once('addon/' . $p . '/' . $p . '.php');
- if(function_exists($p . '_install')) {
- $func = $p . '_install';
- $func();
- $r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`) VALUES ( '%s', 1, %d ) ",
- dbesc($p),
- intval($t)
- );
- }
+ install_plugin($p);
}
}
}
diff --git a/images/icons.png b/images/icons.png
index 4c4c00b8a5e2065d3c88408157b526bcdff06402..fee7781c84240db21d26cd62837a82fb0b99a1ea 100644
GIT binary patch
literal 10702
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
vaVS2{fX_kep4-*FmH=5vutd3-LE!%Y`u4?=
literal 10126
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
diff --git a/mod/admin.php b/mod/admin.php
index f9d248210..054b49a21 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -310,7 +310,58 @@ function admin_page_users(&$a){
function admin_page_plugins(&$a){
- /* all plugins */
+ /**
+ * Single plugin
+ */
+ if ($a->argc == 3){
+ $plugin = $a->argv[2];
+ if (!is_file("addon/$plugin/$plugin.php")){
+ notice( t("Item not found.") );
+ return;
+ }
+
+ if (x($_GET,"a") && $_GET['a']=="t"){
+ // Toggle plugin status
+ $idx = array_search($plugin, $a->plugins);
+ if ($idx){
+ unset($a->plugins[$idx]);
+ uninstall_plugin($plugin);
+ } else {
+ $a->plugins[] = $plugin;
+ install_plugin($plugin);
+ }
+ set_config("system","addon", implode(", ",$a->plugins));
+ goaway($a->get_baseurl() . '/admin/plugins' );
+ return; // NOTREACHED
+ }
+ // display plugin details
+
+
+ if (in_array($plugin, $a->plugins)){
+ $status="on"; $action= t("Disable");
+ } else {
+ $status="off"; $action= t("Enable");
+ }
+
+ $t = get_markup_template("admin_plugins_details.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Plugins'),
+ '$toggle' => t('Toggle'),
+ '$baseurl' => $a->get_baseurl(),
+
+ '$plugin' => $plugin,
+ '$status' => $status,
+ '$action' => $action
+ ));
+ }
+
+
+
+ /**
+ * List plugins
+ */
+
$plugins = array();
$files = glob("addon/*/");
if($files) {
From 25d1637ec4b980d6ac8daf2f028f0ff579d5c977 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Tue, 14 Jun 2011 11:54:14 +0200
Subject: [PATCH 11/20] simple plugin details and log view in admin
---
mod/admin.php | 58 ++++++++++++++++++++++++++++++++--
view/admin_logs.tpl | 17 ++++++++++
view/admin_plugins_details.tpl | 7 ++++
3 files changed, 80 insertions(+), 2 deletions(-)
create mode 100644 view/admin_logs.tpl
create mode 100644 view/admin_plugins_details.tpl
diff --git a/mod/admin.php b/mod/admin.php
index 054b49a21..e40c50396 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -19,10 +19,12 @@ function admin_post(&$a){
// urls
if ($a->argc > 1){
switch ($a->argv[1]){
- case 'site': {
+ case 'site':
admin_page_site_post($a);
break;
- }
+ case 'logs':
+ admin_page_logs_post($a);
+ break;
}
}
@@ -83,6 +85,9 @@ function admin_content(&$a) {
case 'plugins':
$o = admin_page_plugins($a);
break;
+ case 'logs':
+ $o = admin_page_logs($a);
+ break;
default:
notice( t("Item not found.") );
}
@@ -386,3 +391,52 @@ function admin_page_plugins(&$a){
));
}
+
+/**
+ * Logs admin page
+ */
+
+function admin_page_logs_post(&$a) {
+ if (x($_POST,"page_logs")) {
+
+ $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : '');
+ $debugging = ((x($_POST,'debugging')) ? true : false);
+ $loglevel = ((x($_POST,'loglevel')) ? intval(trim($_POST['loglevel'])) : 0);
+
+ set_config('system','logfile', $logfile);
+ set_config('system','debugging', $debugging);
+ set_config('system','loglevel', $loglevel);
+
+
+ }
+
+ goaway($a->get_baseurl() . '/admin/logs' );
+ return; // NOTREACHED
+}
+
+function admin_page_logs(&$a){
+
+ $log_choices = Array(
+ LOGGER_NORMAL => 'Normal',
+ LOGGER_TRACE => 'Trace',
+ LOGGER_DEBUG => 'Debug',
+ LOGGER_DATA => 'Data',
+ LOGGER_ALL => 'All'
+ );
+
+ $t = get_markup_template("admin_logs.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Logs'),
+ '$submit' => t('Submit'),
+ '$clear' => t('Clear'),
+ '$baseurl' => $a->get_baseurl(),
+ '$logname' => get_config('system','logfile'),
+
+ // name, label, value, help string, extra data...
+ '$debugging' => array('debugging', t("Debugging"),get_config('system','debugging'), ""),
+ '$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), "Must be writable by web server. Relative to your Friendika index.php."),
+ '$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
+ ));
+}
+
diff --git a/view/admin_logs.tpl b/view/admin_logs.tpl
new file mode 100644
index 000000000..f2939a7ac
--- /dev/null
+++ b/view/admin_logs.tpl
@@ -0,0 +1,17 @@
+
+
$title - $page
+
+
+
+
$logname
+
+
+
diff --git a/view/admin_plugins_details.tpl b/view/admin_plugins_details.tpl
new file mode 100644
index 000000000..7e2e95521
--- /dev/null
+++ b/view/admin_plugins_details.tpl
@@ -0,0 +1,7 @@
+
+
$title - $page
+
+
$plugin
+
+
$action
+
From 283160901fcb5670b48c7897ccce615872cb956e Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Tue, 14 Jun 2011 14:21:00 +0200
Subject: [PATCH 12/20] update styles
---
view/theme/duepuntozero/style.css | 3 +-
view/theme/loozah/style.css | 70 +++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index 563234238..c2fb9700c 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -2545,7 +2545,8 @@ a.mail-list-link {
margin-bottom: 5px;
clear: left;
}
-#adminpage .plugin .toggle {
+#adminpage .plugin .desc { margin-left: 2.5em;}
+#adminpage .toggleplugin {
float:left;
margin-right: 1em;
}
diff --git a/view/theme/loozah/style.css b/view/theme/loozah/style.css
index a566acadc..db53cb678 100644
--- a/view/theme/loozah/style.css
+++ b/view/theme/loozah/style.css
@@ -2497,6 +2497,73 @@ a.mail-list-link {
top: 0px;
}
+/**
+ * ADMIN
+ */
+
+#adminpage dl {
+ clear: left;
+ margin-bottom: 2px;
+ padding-bottom: 2px;
+ border-bottom: 1px solid black;
+}
+#adminpage dt {
+ width: 200px;
+ float: left;
+ font-weight: bold;
+}
+#adminpage dd {
+ margin-left: 200px;
+}
+
+#adminpage .field {
+ clear: left;
+ margin-bottom: 5px;
+ padding-bottom: 5px;
+}
+
+#adminpage .field label {
+ float: left;
+ width: 200px;
+ font-weight: bold;
+}
+
+#adminpage .field input,
+#adminpage .field textarea {
+ width: 400px;
+}
+#adminpage .field textarea { height: 100px; }
+#adminpage .field_help {
+ display: block;
+ margin-left: 200px;
+ color: #666666;
+
+}
+
+#adminpage h3 {
+ border-bottom: 1px solid #cccccc;
+}
+
+#adminpage .submit {
+ clear:left;
+}
+
+#adminpage #pluginslist {
+ margin: 0px; padding: 0px;
+}
+#adminpage .plugin {
+ list-style: none;
+ display: block;
+ border: 1px solid #888888;
+ padding: 1em;
+ margin-bottom: 5px;
+ clear: left;
+}
+#adminpage .plugin .toggle {
+ float:left;
+ margin-right: 1em;
+}
+
/**
* ICONS
*/
@@ -2535,6 +2602,9 @@ a.mail-list-link {
.language { background-position: -96px -32px; }
.prev { background-position: -112px -32px; }
.next { background-position: -128px -32px; }
+.on { background-position: -144px -32px; }
+
+.off { background-position: 0px -48px; }
.attachtype {
display: block; width: 20px; height: 23px;
From 00e142e4f753005a8b4003585c6a88548f006315 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Tue, 14 Jun 2011 14:21:43 +0200
Subject: [PATCH 13/20] Load plugin info from plugin file. Show README.md or
README from plugin dir in plugin details page
---
addon/oembed/oembed.php | 9 +++---
boot.php | 52 ++++++++++++++++++++++++++++++++++
mod/admin.php | 20 +++++++++----
view/admin_plugins.tpl | 7 ++---
view/admin_plugins_details.tpl | 16 +++++++++--
5 files changed, 88 insertions(+), 16 deletions(-)
diff --git a/addon/oembed/oembed.php b/addon/oembed/oembed.php
index a0a0239aa..f5be44194 100644
--- a/addon/oembed/oembed.php
+++ b/addon/oembed/oembed.php
@@ -1,10 +1,9 @@
*/
require_once('include/oembed.php');
diff --git a/boot.php b/boot.php
index 42b0ca41e..5d45de36f 100644
--- a/boot.php
+++ b/boot.php
@@ -2828,3 +2828,55 @@ function is_site_admin() {
return false;
}}
+/*
+ * parse plugin comment in search of plugin infos.
+ * like
+ *
+ * * Name: Plugin
+ * * Description: A plugin which plugs in
+ * * Version: 1.2.3
+ * * Author: John
+ * * Author: Jane
+ * *
+ */
+
+if (! function_exists('get_plugin_info')){
+function get_plugin_info($plugin){
+ if (!is_file("addon/$plugin/$plugin.php")) return false;
+
+ $f = file_get_contents("addon/$plugin/$plugin.php");
+ $r = preg_match("|/\*.*\*/|msU", $f, $m);
+
+ $info=Array(
+ 'name' => $plugin,
+ 'description' => "",
+ 'author' => array(),
+ 'version' => ""
+ );
+
+ if ($r){
+ $ll = explode("\n", $m[0]);
+ foreach( $ll as $l ) {
+ $l = trim($l,"\t\n\r */");
+ if ($l!=""){
+ list($k,$v) = array_map("trim", explode(":",$l,2));
+ $k= strtolower($k);
+ if ($k=="author"){
+ $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
+ if ($r) {
+ $info['author'][] = array('name'=>$m[1], 'link'=>$m[2]);
+ } else {
+ $info['author'][] = array('name'=>$v);
+ }
+ } else {
+ if (array_key_exists($k,$info)){
+ $info[$k]=$v;
+ }
+ }
+
+ }
+ }
+
+ }
+ return $info;
+}}
diff --git a/mod/admin.php b/mod/admin.php
index e40c50396..6386e6ebc 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -340,7 +340,7 @@ function admin_page_plugins(&$a){
return; // NOTREACHED
}
// display plugin details
-
+ require_once('library/markdown.php');
if (in_array($plugin, $a->plugins)){
$status="on"; $action= t("Disable");
@@ -348,6 +348,14 @@ function admin_page_plugins(&$a){
$status="off"; $action= t("Enable");
}
+ $readme=Null;
+ if (is_file("addon/$plugin/README.md")){
+ $readme = file_get_contents("addon/$plugin/README.md");
+ $readme = Markdown($readme);
+ } else if (is_file("addon/$plugin/README")){
+ $readme = "". file_get_contents("addon/$plugin/README") ." ";
+ }
+
$t = get_markup_template("admin_plugins_details.tpl");
return replace_macros($t, array(
'$title' => t('Administration'),
@@ -357,7 +365,10 @@ function admin_page_plugins(&$a){
'$plugin' => $plugin,
'$status' => $status,
- '$action' => $action
+ '$action' => $action,
+ '$info' => get_plugin_info($plugin),
+
+ '$readme' => $readme
));
}
@@ -373,9 +384,8 @@ function admin_page_plugins(&$a){
foreach($files as $file) {
if (is_dir($file)){
list($tmp, $id)=array_map("trim", explode("/",$file));
- // TODO: plugins info
- $name=$author=$description=$homepage="";
- $plugins[] = array( $id, (in_array($id, $a->plugins)?"on":"off") , $name, $author, $description, $homepage);
+ $info = get_plugin_info($id);
+ $plugins[] = array( $id, (in_array($id, $a->plugins)?"on":"off") , $info);
}
}
}
diff --git a/view/admin_plugins.tpl b/view/admin_plugins.tpl
index d29665a06..ee0fa67e6 100644
--- a/view/admin_plugins.tpl
+++ b/view/admin_plugins.tpl
@@ -4,10 +4,9 @@
{{ for $plugins as $p }}
-
-
- $p.0
-
+
+ $p.2.name - $p.2.version
+ $p.2.description
{{ endfor }}
diff --git a/view/admin_plugins_details.tpl b/view/admin_plugins_details.tpl
index 7e2e95521..acb3d2862 100644
--- a/view/admin_plugins_details.tpl
+++ b/view/admin_plugins_details.tpl
@@ -1,7 +1,19 @@
$title - $page
-
$plugin
+
$info.name - $info.version : $action
+
$info.description
+
+ {{ for $info.author as $a }}
+ $a.name
+ {{ endfor }}
+
-
$action
+
+ {{ if $readme }}
+
Readme
+
+ $readme
+
+ {{ endif }}
From b7dc9f8867e783a0db109cce4cb0db90500129eb Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Tue, 14 Jun 2011 15:08:03 +0200
Subject: [PATCH 14/20] Update info comments in all plugins
---
addon/calc/calc.php | 7 +++++++
addon/convert/convert.php | 7 ++++++-
addon/facebook/README | 33 +++++++++++++++++++++++++++++++
addon/facebook/facebook.php | 5 +++++
addon/fortunate/fortunate.php | 9 ++++++---
addon/java_upload/java_upload.php | 9 ++++++++-
addon/js_upload/js_upload.php | 7 +++++++
addon/ldapauth/README | 17 ++++++++++++++++
addon/ldapauth/ldapauth.php | 8 +++++++-
addon/piwik/piwik.php | 7 +++++++
addon/poormancron/poormancron.php | 8 ++++----
addon/randplace/randplace.php | 17 ++++++++--------
addon/sniper/sniper.php | 8 +++++++-
addon/statusnet/statusnet.php | 7 ++++++-
addon/tictac/tictac.php | 6 ++++++
addon/twitter/twitter.php | 6 ++++++
addon/widgets/widgets.php | 13 ++++++------
view/admin_plugins_details.tpl | 6 +++---
view/theme/duepuntozero/style.css | 1 +
19 files changed, 151 insertions(+), 30 deletions(-)
create mode 100644 addon/facebook/README
create mode 100644 addon/ldapauth/README
diff --git a/addon/calc/calc.php b/addon/calc/calc.php
index a095e3960..8c079dc7a 100644
--- a/addon/calc/calc.php
+++ b/addon/calc/calc.php
@@ -1,4 +1,11 @@
+ */
+
function calc_install() {
register_hook('app_menu', 'addon/calc/calc.php', 'calc_app_menu');
diff --git a/addon/convert/convert.php b/addon/convert/convert.php
index a3448ce01..7a4c90a53 100644
--- a/addon/convert/convert.php
+++ b/addon/convert/convert.php
@@ -1,5 +1,10 @@
+ */
function convert_install() {
register_hook('app_menu', 'addon/convert/convert.php', 'convert_app_menu');
diff --git a/addon/facebook/README b/addon/facebook/README
new file mode 100644
index 000000000..42ec01383
--- /dev/null
+++ b/addon/facebook/README
@@ -0,0 +1,33 @@
+Installing the Friendika/Facebook connector
+
+1. register an API key for your site from developer.facebook.com
+ a. We'd be very happy if you include "Friendika" in the application name
+ to increase name recognition. The Friendika icons are also present
+ in the images directory and may be uploaded as a Facebook app icon.
+ Use images/friendika-16.jpg for the Icon and images/friendika-128.jpg for the Logo.
+ b. The url should be your site URL with a trailing slash.
+ You may use http://portal.friendika.com/privacy as the privacy policy
+ URL unless your site has different requirements, and
+ http://portal.friendika.com as the Terms of Service URL unless
+ you have different requirements. (Friendika is a software application
+ and does not require Terms of Service, though your installation of it might).
+ c. Set the following values in your .htconfig.php file
+ $a->config['facebook']['appid'] = 'xxxxxxxxxxx';
+ $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx';
+ Replace with the settings Facebook gives you.
+2. Enable the facebook plugin by including it in .htconfig.php - e.g.
+ $a->config['system']['addon'] = 'plugin1,plugin2,facebook';
+3. Visit the Facebook Settings section of the "Settings->Plugin Settings" page.
+ and click 'Install Facebook Connector'.
+4. This will ask you to login to Facebook and grant permission to the
+ plugin to do its stuff. Allow it to do so.
+5. You're done. To turn it off visit the Plugin Settings page again and
+ 'Remove Facebook posting'.
+
+Vidoes and embeds will not be posted if there is no other content. Links
+and images will be converted to a format suitable for the Facebook API and
+long posts truncated - with a link to view the full post.
+
+Facebook contacts will not be able to view private photos, as they are not able to
+authenticate to your site to establish identity. We will address this
+in a future release.
diff --git a/addon/facebook/facebook.php b/addon/facebook/facebook.php
index 545779cd5..5d86c66c2 100644
--- a/addon/facebook/facebook.php
+++ b/addon/facebook/facebook.php
@@ -1,4 +1,9 @@
+ */
/**
* Installing the Friendika/Facebook connector
diff --git a/addon/fortunate/fortunate.php b/addon/fortunate/fortunate.php
index b91080f51..5a6302e58 100644
--- a/addon/fortunate/fortunate.php
+++ b/addon/fortunate/fortunate.php
@@ -1,7 +1,10 @@
+ */
function fortunate_install() {
diff --git a/addon/java_upload/java_upload.php b/addon/java_upload/java_upload.php
index 8b8a57604..09e321f0a 100644
--- a/addon/java_upload/java_upload.php
+++ b/addon/java_upload/java_upload.php
@@ -1,5 +1,12 @@
+ */
+
/**
*
* Java photo uploader, uses Jumploader
@@ -93,4 +100,4 @@ function java_upload_photo_post_end(&$a,&$b) {
if(x($a->data,'java_upload') && $a->data['java_upload'])
killme();
-}
\ No newline at end of file
+}
diff --git a/addon/js_upload/js_upload.php b/addon/js_upload/js_upload.php
index 9f3fa9600..042e9a988 100644
--- a/addon/js_upload/js_upload.php
+++ b/addon/js_upload/js_upload.php
@@ -1,5 +1,12 @@
+ */
+
/**
*
* JavaScript Photo/Image Uploader
diff --git a/addon/ldapauth/README b/addon/ldapauth/README
new file mode 100644
index 000000000..cf28ef1e0
--- /dev/null
+++ b/addon/ldapauth/README
@@ -0,0 +1,17 @@
+Authenticate a user against an LDAP directory
+Useful for Windows Active Directory and other LDAP-based organisations
+to maintain a single password across the organisation.
+
+Optionally authenticates only if a member of a given group in the directory.
+
+The person must have registered with Friendika using the normal registration
+procedures in order to have a Friendika user record, contact, and profile.
+
+Note when using with Windows Active Directory: you may need to set TLS_CACERT in your site
+ldap.conf file to the signing cert for your LDAP server.
+
+The required configuration options for this module may be set in the .htconfig.php file
+e.g.:
+
+$a->config['ldapauth']['ldap_server'] = 'host.example.com';
+...etc.
diff --git a/addon/ldapauth/ldapauth.php b/addon/ldapauth/ldapauth.php
index 2ec30caad..7230302e9 100644
--- a/addon/ldapauth/ldapauth.php
+++ b/addon/ldapauth/ldapauth.php
@@ -1,5 +1,11 @@
+ */
+
/**
* Friendika addon
*
diff --git a/addon/piwik/piwik.php b/addon/piwik/piwik.php
index 52bdaeb0d..032f84f4b 100644
--- a/addon/piwik/piwik.php
+++ b/addon/piwik/piwik.php
@@ -1,4 +1,11 @@
+ */
+
/* Piwik Analytics Plugin for Friendika
*
diff --git a/addon/poormancron/poormancron.php b/addon/poormancron/poormancron.php
index 830c10ddf..9a8dc1e33 100644
--- a/addon/poormancron/poormancron.php
+++ b/addon/poormancron/poormancron.php
@@ -1,9 +1,9 @@
*/
function poormancron_install() {
diff --git a/addon/randplace/randplace.php b/addon/randplace/randplace.php
index fa38de377..bae8e7c69 100644
--- a/addon/randplace/randplace.php
+++ b/addon/randplace/randplace.php
@@ -1,13 +1,12 @@
+ *
+ *
+ *
*
* Addons are registered with the system in the
* .htconfig.php file.
@@ -178,4 +177,4 @@ function randplace_settings(&$a,&$s) {
$s .= '
';
-}
\ No newline at end of file
+}
diff --git a/addon/sniper/sniper.php b/addon/sniper/sniper.php
index 79d7daad2..bb4eace30 100644
--- a/addon/sniper/sniper.php
+++ b/addon/sniper/sniper.php
@@ -1,4 +1,10 @@
+ */
function sniper_install() {
register_hook('app_menu', 'addon/sniper/sniper.php', 'sniper_app_menu');
@@ -28,4 +34,4 @@ $o .= <<< EOT
EOT;
return $o;
-}
\ No newline at end of file
+}
diff --git a/addon/statusnet/statusnet.php b/addon/statusnet/statusnet.php
index 39df7d962..e24ebc1ee 100644
--- a/addon/statusnet/statusnet.php
+++ b/addon/statusnet/statusnet.php
@@ -1,5 +1,10 @@
+ */
+
/* StatusNet Plugin for Friendika
*
* Author: Tobias Diekershoff
diff --git a/addon/tictac/tictac.php b/addon/tictac/tictac.php
index a69cda132..d6cec08a0 100644
--- a/addon/tictac/tictac.php
+++ b/addon/tictac/tictac.php
@@ -1,4 +1,10 @@
+ */
function tictac_install() {
diff --git a/addon/twitter/twitter.php b/addon/twitter/twitter.php
index c59d1b9e5..fef6583f6 100644
--- a/addon/twitter/twitter.php
+++ b/addon/twitter/twitter.php
@@ -1,4 +1,10 @@
+ */
+
/* Twitter Plugin for Friendika
*
diff --git a/addon/widgets/widgets.php b/addon/widgets/widgets.php
index af17d9e9a..f5f868222 100644
--- a/addon/widgets/widgets.php
+++ b/addon/widgets/widgets.php
@@ -1,10 +1,11 @@
+ */
+
function widgets_install() {
register_hook('plugin_settings', 'addon/widgets/widgets.php', 'widgets_settings');
diff --git a/view/admin_plugins_details.tpl b/view/admin_plugins_details.tpl
index acb3d2862..85ee8dfb4 100644
--- a/view/admin_plugins_details.tpl
+++ b/view/admin_plugins_details.tpl
@@ -3,11 +3,11 @@
$info.name - $info.version : $action
$info.description
-
+
{{ for $info.author as $a }}
- $a.name
+
{{ if $a.link }} {{ endif }}$a.name
{{ endfor }}
-
+
{{ if $readme }}
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index c2fb9700c..78e02681a 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -2550,6 +2550,7 @@ a.mail-list-link {
float:left;
margin-right: 1em;
}
+#adminpage .author .icon { float: left;}
/**
* ICONS
From 63390aa8001a9d8f28f66c8e8686f406b28d6cbc Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Thu, 16 Jun 2011 12:02:05 +0200
Subject: [PATCH 15/20] {{ if }} {{ else }} support in templates
---
include/template_processor.php | 39 ++++++++++++++++++++++++++++------
1 file changed, 32 insertions(+), 7 deletions(-)
diff --git a/include/template_processor.php b/include/template_processor.php
index a2c24b00b..be40a31ab 100644
--- a/include/template_processor.php
+++ b/include/template_processor.php
@@ -8,6 +8,18 @@
var $nodes = array();
var $done = false;
+ private function _preg_error(){
+ switch(preg_last_error()){
+ case PREG_INTERNAL_ERROR: die('PREG_INTERNAL_ERROR'); break;
+ case PREG_BACKTRACK_LIMIT_ERROR: die('PREG_BACKTRACK_LIMIT_ERROR'); break;
+ case PREG_RECURSION_LIMIT_ERROR: die('PREG_RECURSION_LIMIT_ERROR'); break;
+ case PREG_BAD_UTF8_ERROR: die('PREG_BAD_UTF8_ERROR'); break;
+ case PREG_BAD_UTF8_OFFSET_ERROR: die('PREG_BAD_UTF8_OFFSET_ERROR'); break;
+ default:
+ die("Unknown preg error.");
+ }
+ }
+
private function _build_replace($r, $prefix){
if(is_array($r) && count($r)) {
@@ -40,9 +52,9 @@
/**
* IF node
*
- * {{ if <$var> }}...{{ endif }}
- * {{ if <$var>== }}...{{ endif }}
- * {{ if <$var>!= }}...{{ endif }}
+ * {{ if <$var> }}...[{{ else }} ...] {{ endif }}
+ * {{ if <$var>== }}...[{{ else }} ...]{{ endif }}
+ * {{ if <$var>!= }}...[{{ else }} ...]{{ endif }}
*/
private function _replcb_if($args){
@@ -59,7 +71,13 @@
} else {
$val = $this->_get_var($args[2]);
}
- return ($val?$args[3]:"");
+ if (isset($args[4])) {
+ list($strue, $sfalse)= explode($args[4], $args[3]);
+ } else {
+ $strue = $args[3]; $sfalse = "";
+ }
+
+ return ($val?$strue:$sfalse);
}
/**
@@ -112,13 +130,17 @@
private function _replcb_node($m) {
$node = $this->nodes[$m[1]];
if (method_exists($this, "_replcb_".$node[1])){
- return call_user_func(array($this, "_replcb_".$node[1]), $node);
+ $s = call_user_func(array($this, "_replcb_".$node[1]), $node);
} else {
- return "";
+ $s = "";
}
+ $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
+ if ($s==Null) $this->_preg_error()
+ return $s;
}
private function _replcb($m){
+ //var_dump(array_map('htmlspecialchars', $m));
$this->done = false;
$this->nodes[] = (array) $m;
return "||". (count($this->nodes)-1) ."||";
@@ -128,8 +150,10 @@
$this->done = false;
while (!$this->done){
$this->done=true;
- $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*){{ *end\1 *}}|', array($this, "_replcb"), $s);
+ $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s);
+ if ($s==Null) $this->_preg_error();
}
+ //({{ *else *}}[^{]*)?
krsort($this->nodes);
return $s;
}
@@ -144,6 +168,7 @@
#$s = str_replace(array("\n","\r"),array("§n§","§r§"),$s);
$s = $this->_build_nodes($s);
$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
+ if ($s==Null) $this->_preg_error()
$s = str_replace($this->search,$this->replace, $s);
return $s;
From ffee5dd69e424f33c0ceb9cf8b0cfe78e4025794 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Thu, 16 Jun 2011 12:04:27 +0200
Subject: [PATCH 16/20] ping updates trigger 'nav-update' custom event from
---
include/main.js | 44 ++++++++++++++++++++++++++------------------
1 file changed, 26 insertions(+), 18 deletions(-)
diff --git a/include/main.js b/include/main.js
index 34045f57f..31b441afb 100644
--- a/include/main.js
+++ b/include/main.js
@@ -29,10 +29,33 @@
var langSelect = false;
var commentBusy = false;
- $(document).ready(function() {
+ $(function() {
$.ajaxSetup({cache: false});
msie = $.browser.msie ;
+
+
+ /* nav update event */
+ $('nav').bind('nav-update', function(e,data){;
+ var net = $(data).find('net').text();
+ if(net == 0) { net = ''; $('#net-update').hide() } else { $('#net-update').show() }
+ $('#net-update').html(net);
+ var home = $(data).find('home').text();
+ if(home == 0) { home = ''; $('#home-update').hide() } else { $('#home-update').show() }
+ $('#home-update').html(home);
+ var mail = $(data).find('mail').text();
+ if(mail == 0) { mail = ''; $('#mail-update').hide() } else { $('#mail-update').show() }
+ $('#mail-update').html(mail);
+ var intro = $(data).find('intro').text();
+ var register = $(data).find('register').text();
+ if(intro == 0) { intro = ''; }
+ if(register != 0 && intro != '') { intro = intro+'/'+register; }
+ if(register != 0 && intro == '') { intro = '0/'+register; }
+ if (intro == '') { $('#notify-update').hide() } else { $('#notify-update').show() }
+ $('#notify-update').html(intro);
+ });
+
+
NavUpdate();
// Allow folks to stop the ajax page updates with the pause/break key
$(document).keypress(function(event) {
@@ -90,23 +113,8 @@
if(! stopped) {
$.get("ping",function(data) {
$(data).find('result').each(function() {
- var net = $(this).find('net').text();
- if(net == 0) { net = ''; $('#net-update').hide() } else { $('#net-update').show() }
- $('#net-update').html(net);
- var home = $(this).find('home').text();
- if(home == 0) { home = ''; $('#home-update').hide() } else { $('#home-update').show() }
- $('#home-update').html(home);
- var mail = $(this).find('mail').text();
- if(mail == 0) { mail = ''; $('#mail-update').hide() } else { $('#mail-update').show() }
- $('#mail-update').html(mail);
- var intro = $(this).find('intro').text();
- var register = $(this).find('register').text();
- if(intro == 0) { intro = ''; }
- if(register != 0 && intro != '') { intro = intro+'/'+register; }
- if(register != 0 && intro == '') { intro = '0/'+register; }
- if (intro == '') { $('#notify-update').hide() } else { $('#notify-update').show() }
- $('#notify-update').html(intro);
-
+ // send nav-update event
+ $('nav').trigger('nav-update', this);
});
}) ;
}
From 5f583fb8d6b71f63bf240729c00f9fd2009afd93 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Thu, 16 Jun 2011 12:05:35 +0200
Subject: [PATCH 17/20] Admin: register policy in site page, initial users
page. Aside 'Users' link show pending registrations.
---
mod/admin.php | 71 ++++++++++++++++++++++++-------
view/admin_aside.tpl | 15 ++++++-
view/admin_site.tpl | 21 +++++----
view/theme/duepuntozero/style.css | 15 ++++++-
4 files changed, 95 insertions(+), 27 deletions(-)
diff --git a/mod/admin.php b/mod/admin.php
index 6386e6ebc..d5f27a44a 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -63,6 +63,7 @@ function admin_content(&$a) {
$t = get_markup_template("admin_aside.tpl");
$a->page['aside'] = replace_macros( $t, array(
'$admin' => $aside,
+ '$h_pending' => t('User registrations waiting for confirm'),
'$admurl'=> $a->get_baseurl()."/admin/"
));
@@ -148,6 +149,11 @@ function admin_page_site_post(&$a){
$language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : '');
$theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
$maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0);
+
+
+ $register_policy = ((x($_POST,'register_policy')) ? intval(trim($_POST['register_policy'])) : 0);
+ $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : '');
+
$allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : '');
$allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
$block_public = ((x($_POST,'block_public')) ? True : False);
@@ -166,7 +172,7 @@ function admin_page_site_post(&$a){
$timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
- $a->config['sitename'] = $sitename;
+ set_config('config','sitename',$sitename);
if ($banner==""){
// don't know why, but del_config doesn't work...
q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
@@ -179,6 +185,9 @@ function admin_page_site_post(&$a){
set_config('system','language', $language);
set_config('system','theme', $theme);
set_config('system','maximagesize', $maximagesize);
+
+ set_config('config','register_policy', $register_policy);
+ set_config('config','register_text', $register_text);
set_config('system','allowed_sites', $allowed_sites);
set_config('system','allowed_email', $allowed_email);
set_config('system','block_public', $block_public);
@@ -204,18 +213,6 @@ function admin_page_site_post(&$a){
set_config('system','proxy', $proxy);
set_config('system','curl_timeout', $timeout);
- $r = q("SELECT * FROM `config` WHERE `cat`='config' AND `k`='sitename'");
- if (count($r)>0){
- q("UPDATE `config` SET `v`='%s' WHERE `cat`='config' AND `k`='sitename'",
- dbesc($a->config['sitename'])
- );
- } else {
- q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( 'config', 'sitename', '%s' )",
- dbesc($a->config['sitename'])
- );
- }
-
-
goaway($a->get_baseurl() . '/admin/site' );
return; // NOTREACHED
@@ -257,7 +254,12 @@ function admin_page_site(&$a) {
//echo ""; var_dump($lang_choices); die(" ");
-
+ /* Register policy */
+ $register_choices = Array(
+ REGISTER_CLOSED => t("Closed"),
+ REGISTER_APPROVE => t("Need approvation"),
+ REGISTER_OPEN => t("Open")
+ );
$t = get_markup_template("admin_site.tpl");
return replace_macros($t, array(
@@ -274,6 +276,8 @@ function admin_page_site(&$a) {
'$maximagesize' => array('maximagesize', t("Maximum image size"), get_config('system','maximagesize'), "Maximum size in bytes of uploaded images. Default is 0, which means no limits."),
+ '$register_policy' => array('register_policy', t("Register policy"), $a->config['register_policy'], "", $register_choices),
+ '$register_text' => array('register_text', t("Register text"), $a->config['register_text'], "Will be displayed prominently on the registration page."),
'$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), "Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains"),
'$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), "Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains"),
'$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), "Check to block public access to all otherwise public personal pages on this site unless you are currently logged in."),
@@ -305,7 +309,44 @@ function admin_page_site(&$a) {
*/
function admin_page_users(&$a){
- return ":)";
+ /* get pending */
+ $pending = q("SELECT `register`.*, `contact`.`name`, `user`.`email`
+ FROM `register`
+ LEFT JOIN `contact` ON `register`.`uid` = `contact`.`uid`
+ LEFT JOIN `user` ON `register`.`uid` = `user`.`uid`;");
+
+ /* get users */
+ $users = q("SELECT `user`.*, `contact`.`name` FROM `user`
+ LEFT JOIN `contact` ON `user`.`uid` = `contact`.`uid`
+ WHERE `user`.`verified`=1 AND `contact`.`self`=1
+ ORDER BY `contact`.`name`");
+
+
+ $t = get_markup_template("admin_users.tpl");
+ return replace_macros($t, array(
+ // strings //
+ '$title' => t('Administration'),
+ '$page' => t('Users'),
+ '$submit' => t('Submit'),
+ '$select_all' => t('select all'),
+ '$h_pending' => t('User registrations waiting for confirm'),
+ '$th_pending' => array( t('Request date'), t('Name'), t('Email') ),
+ '$no_pending' => t('No registrations.'),
+ '$approve' => t('Approve'),
+ '$deny' => t('Deny'),
+ '$delete' => t('Delete'),
+ '$block' => t('Block'),
+
+ '$h_users' => t('Users'),
+ '$th_users' => array( t('Name'), t('Nickname'), t('Email'), t('Register date'), t('Last login') ),
+
+ // values //
+ '$baseurl' => $a->get_baseurl(),
+
+ '$pending' => $pending,
+ '$users' => $users,
+ ));
+
}
diff --git a/view/admin_aside.tpl b/view/admin_aside.tpl
index dd81a6fee..ade0c473b 100644
--- a/view/admin_aside.tpl
+++ b/view/admin_aside.tpl
@@ -1,7 +1,20 @@
+
diff --git a/view/admin_site.tpl b/view/admin_site.tpl
index f120461aa..dba29f11c 100644
--- a/view/admin_site.tpl
+++ b/view/admin_site.tpl
@@ -10,6 +10,18 @@
+ Registration
+ {{ inc field_input.tpl with $field=$register_text }}{{ endinc }}
+ {{ inc field_select.tpl with $field=$register_policy }}{{ endinc }}
+
+ {{ inc field_checkbox.tpl with $field=$no_multi_reg }}{{ endinc }}
+ {{ inc field_checkbox.tpl with $field=$no_openid }}{{ endinc }}
+ {{ inc field_checkbox.tpl with $field=$no_gravatar }}{{ endinc }}
+ {{ inc field_checkbox.tpl with $field=$no_regfullname }}{{ endinc }}
+ {{ inc field_checkbox.tpl with $field=$no_utf }}{{ endinc }}
+
+
+
Upload
{{ inc field_input.tpl with $field=$maximagesize }}{{ endinc }}
@@ -23,15 +35,6 @@
- Registration
- {{ inc field_checkbox.tpl with $field=$no_multi_reg }}{{ endinc }}
- {{ inc field_checkbox.tpl with $field=$no_openid }}{{ endinc }}
- {{ inc field_checkbox.tpl with $field=$no_gravatar }}{{ endinc }}
- {{ inc field_checkbox.tpl with $field=$no_regfullname }}{{ endinc }}
- {{ inc field_checkbox.tpl with $field=$no_utf }}{{ endinc }}
-
-
-
Advanced
{{ inc field_checkbox.tpl with $field=$rino_enc }}{{ endinc }}
{{ inc field_checkbox.tpl with $field=$verifyssl }}{{ endinc }}
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index 78e02681a..206074c92 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -2485,7 +2485,14 @@ a.mail-list-link {
/**
* ADMIN
*/
-
+#pending-update {
+ float:right;
+ color: #ffffff;
+ font-weight: bold;
+ background-color: #FF0000;
+ padding: 0em 0.3em;
+
+}
#adminpage dl {
clear: left;
margin-bottom: 2px;
@@ -2551,7 +2558,9 @@ a.mail-list-link {
margin-right: 1em;
}
#adminpage .author .icon { float: left;}
-
+#adminpage table {width:100%; border-bottom: 1p solid #000000; margin: 5px 0px;}
+#adminpage table th { text-align: left;}
+#adminpage td .icon { float: left;}
/**
* ICONS
*/
@@ -2594,6 +2603,8 @@ a.mail-list-link {
.off { background-position: 0px -48px; }
+.icon.dim { opacity: 0.3;filter:alpha(opacity=30); }
+
.attachtype {
display: block; width: 20px; height: 23px;
float: left;
From c94b809634cd92c69be3483c935e6741b7d0c090 Mon Sep 17 00:00:00 2001
From: Fabio Comuni
Date: Thu, 16 Jun 2011 12:14:04 +0200
Subject: [PATCH 18/20] fix a small php notice.
---
boot.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/boot.php b/boot.php
index 5d45de36f..ff4224cfc 100644
--- a/boot.php
+++ b/boot.php
@@ -2779,7 +2779,7 @@ function unamp($s) {
if(! function_exists('lang_selector')) {
function lang_selector() {
global $lang;
- $o .= '
';
+ $o = '
';
$o .= '