diff --git a/.htaccess b/.htaccess
index 7f3935117..5f6414882 100644
--- a/.htaccess
+++ b/.htaccess
@@ -28,3 +28,4 @@ AddType audio/ogg .oga
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
+
diff --git a/Zotlabs/Identity/BasicId.php b/Zotlabs/Identity/BasicId.php
new file mode 100644
index 000000000..3c149808f
--- /dev/null
+++ b/Zotlabs/Identity/BasicId.php
@@ -0,0 +1,18 @@
+test = ((array_key_exists('test',$req)) ? intval($req['test']) : 0);
+ $this->test_results = array('success' => false);
+ $this->debug_msg = '';
+
+ $this->success = false;
+ $this->address = $req['auth'];
+ $this->desturl = $req['dest'];
+ $this->sec = $req['sec'];
+ $this->version = $req['version'];
+ $this->delegate = $req['delegate'];
+
+ $c = get_sys_channel();
+ if(! $c) {
+ logger('unable to obtain response (sys) channel');
+ $this->Debug('no local channels found.');
+ $this->Finalise();
+ }
+
+ $x = $this->GetHublocs($this->address);
+
+ if($x) {
+ foreach($x as $xx) {
+ if($this->Verify($c,$xx))
+ break;
+ }
+ }
+
+ /**
+ * @FIXME we really want to save the return_url in the session before we
+ * visit rmagic. This does however prevent a recursion if you visit
+ * rmagic directly, as it would otherwise send you back here again.
+ * But z_root() probably isn't where you really want to go.
+ */
+
+ if(strstr($this->desturl,z_root() . '/rmagic'))
+ goaway(z_root());
+
+ $this->Finalise();
+
+ }
+
+ function GetHublocs($address) {
+
+ // Try and find a hubloc for the person attempting to auth.
+ // Since we're matching by address, we have to return all entries
+ // some of which may be from re-installed hubs; and we'll need to
+ // try each sequentially to see if one can pass the test
+
+ $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
+ where hubloc_addr = '%s' order by hubloc_id desc",
+ dbesc($address)
+ );
+
+ if(! $x) {
+ // finger them if they can't be found.
+ $ret = zot_finger($address, null);
+ if ($ret['success']) {
+ $j = json_decode($ret['body'], true);
+ if($j)
+ import_xchan($j);
+ $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
+ where hubloc_addr = '%s' order by hubloc_id desc",
+ dbesc($address)
+ );
+ }
+ }
+ if(! $x) {
+ logger('mod_zot: auth: unable to finger ' . $address);
+ $this->Debug('no hubloc found for ' . $address . ' and probing failed.');
+ $this->Finalise();
+ }
+
+ return $x;
+ }
+
+
+ function Verify($channel,$hubloc) {
+
+ logger('auth request received from ' . $hubloc['hubloc_addr'] );
+
+ $this->remote = remote_channel();
+ $this->remote_service_class = '';
+ $this->remote_level = 0;
+ $this->remote_hub = $hubloc['hubloc_url'];
+ $this->dnt = 0;
+
+ // check credentials and access
+
+ // If they are already authenticated and haven't changed credentials,
+ // we can save an expensive network round trip and improve performance.
+
+ // Also check that they are coming from the same site as they authenticated with originally.
+
+ $already_authed = (((remote_channel()) && ($hubloc['hubloc_hash'] == remote_channel())
+ && ($hubloc['hubloc_url'] === $_SESSION['remote_hub'])) ? true : false);
+
+ if($this->delegate && $this->delegate !== $_SESSION['delegate_channel'])
+ $already_authed = false;
+
+ if($already_authed)
+ return true;
+
+ if(local_channel()) {
+
+ // tell them to logout if they're logged in locally as anything but the target remote account
+ // in which case just shut up because they don't need to be doing this at all.
+
+ if (get_app()->channel['channel_hash'] == $hubloc['xchan_hash']) {
+ return true;
+ }
+ else {
+ logger('already authenticated locally as somebody else.');
+ notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry.') . EOL);
+ if($this->test) {
+ $this->Debug('already logged in locally with a conflicting identity.');
+ return false;
+ }
+ }
+ return false;
+ }
+
+ // Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the
+ // site private key
+ // The actual channel sending the packet ($c[0]) is not important, but this provides a
+ // generic zot packet with a sender which can be verified
+
+ $p = zot_build_packet($channel,$type = 'auth_check',
+ array(array('guid' => $hubloc['hubloc_guid'],'guid_sig' => $hubloc['hubloc_guid_sig'])),
+ $hubloc['hubloc_sitekey'], $this->sec);
+
+ $this->Debug('auth check packet created using sitekey ' . $hubloc['hubloc_sitekey']);
+ $this->Debug('packet contents: ' . $p);
+
+ $result = zot_zot($hubloc['hubloc_callback'],$p);
+ if(! $result['success']) {
+ logger('auth_check callback failed.');
+ if($this->test)
+ $this->Debug('auth check request to your site returned .' . print_r($result, true));
+ return false;
+ }
+
+ $j = json_decode($result['body'], true);
+ if(! $j) {
+ logger('auth_check json data malformed.');
+ if($this->test)
+ $this->Debug('json malformed: ' . $result['body']);
+ return false;
+ }
+
+ $this->Debug('auth check request returned .' . print_r($j, true));
+
+ if(! $j['success'])
+ return false;
+
+ // legit response, but we do need to check that this wasn't answered by a man-in-middle
+
+ if (! rsa_verify($this->sec . $hubloc['xchan_hash'],base64url_decode($j['confirm']),$hubloc['xchan_pubkey'])) {
+ logger('final confirmation failed.');
+ if($this->test)
+ $this->Debug('final confirmation failed. ' . $sec . print_r($j,true) . print_r($hubloc,true));
+ return false;
+ }
+
+ if (array_key_exists('service_class',$j))
+ $this->remote_service_class = $j['service_class'];
+ if (array_key_exists('level',$j))
+ $this->remote_level = $j['level'];
+ if (array_key_exists('DNT',$j))
+ $this->dnt = $j['DNT'];
+
+
+ // log them in
+
+ if ($this->test) {
+ // testing only - return the success result
+ $this->test_results['success'] = true;
+ $this->Debug('Authentication Success!');
+ $this->Finalise();
+ }
+
+ $_SESSION['authenticated'] = 1;
+
+ // check for delegation and if all is well, log them in locally with delegation restrictions
+
+ $this->delegate_success = false;
+
+ if($this->delegate) {
+ $r = q("select * from channel left join xchan on channel_hash = xchan_hash where xchan_addr = '%s' limit 1",
+ dbesc($this->delegate)
+ );
+ if ($r && intval($r[0]['channel_id'])) {
+ $allowed = perm_is_allowed($r[0]['channel_id'],$hubloc['xchan_hash'],'delegate');
+ if($allowed) {
+ $_SESSION['delegate_channel'] = $r[0]['channel_id'];
+ $_SESSION['delegate'] = $hubloc['xchan_hash'];
+ $_SESSION['account_id'] = intval($r[0]['channel_account_id']);
+ require_once('include/security.php');
+ // this will set the local_channel authentication in the session
+ change_channel($r[0]['channel_id']);
+ $this->delegate_success = true;
+ }
+ }
+ }
+
+ if (! $this->delegate_success) {
+ // normal visitor (remote_channel) login session credentials
+ $_SESSION['visitor_id'] = $hubloc['xchan_hash'];
+ $_SESSION['my_url'] = $hubloc['xchan_url'];
+ $_SESSION['my_address'] = $this->address;
+ $_SESSION['remote_service_class'] = $this->remote_service_class;
+ $_SESSION['remote_level'] = $this->remote_level;
+ $_SESSION['remote_hub'] = $this->remote_hub;
+ $_SESSION['DNT'] = $this->dnt;
+ }
+
+ $arr = array('xchan' => $hubloc, 'url' => $this->desturl, 'session' => $_SESSION);
+ call_hooks('magic_auth_success',$arr);
+ get_app()->set_observer($hubloc);
+ require_once('include/security.php');
+ get_app()->set_groups(init_groups_visitor($_SESSION['visitor_id']));
+ info(sprintf( t('Welcome %s. Remote authentication successful.'),$hubloc['xchan_name']));
+ logger('mod_zot: auth success from ' . $hubloc['xchan_addr']);
+ $this->success = true;
+ return true;
+ }
+
+ function Debug($msg) {
+ $this->debug_msg .= $msg . EOL;
+ }
+
+
+ function Finalise() {
+
+ if($this->test) {
+ $this->test_results['message'] = $this->debug_msg;
+ json_return_and_die($this->test_results);
+ }
+
+ goaway($this->desturl);
+ }
+
+}
+
+
+/**
+ *
+ * Magic Auth
+ * ==========
+ *
+ * So-called "magic auth" takes place by a special exchange. On the site where the "channel to be authenticated" lives (e.g. $mysite),
+ * a redirection is made via $mysite/magic to the zot endpoint of the remote site ($remotesite) with special GET parameters.
+ *
+ * The endpoint is typically https://$remotesite/post - or whatever was specified as the callback url in prior communications
+ * (we will bootstrap an address and fetch a zot info packet if possible where no prior communications exist)
+ *
+ * Five GET parameters are supplied:
+ * * auth => the urlencoded webbie (channel@host.domain) of the channel requesting access
+ * * dest => the desired destination URL (urlencoded)
+ * * sec => a random string which is also stored on $mysite for use during the verification phase.
+ * * version => the zot revision
+ * * delegate => optional urlencoded webbie of a local channel to invoke delegation rights for
+ *
+ * * test => (optional 1 or 0 - debugs the authentication exchange and returns a json response instead of redirecting the browser session)
+ *
+ * When this packet is received, an "auth-check" zot message is sent to $mysite.
+ * (e.g. if $_GET['auth'] is foobar@podunk.edu, a zot packet is sent to the podunk.edu zot endpoint, which is typically /post)
+ * If no information has been recorded about the requesting identity a zot information packet will be retrieved before
+ * continuing.
+ *
+ * The sender of this packet is an arbitrary/random site channel. The recipients will be a single recipient corresponding
+ * to the guid and guid_sig we have associated with the requesting auth identity
+ *
+ * \code{.json}
+ * {
+ * "type":"auth_check",
+ * "sender":{
+ * "guid":"kgVFf_...",
+ * "guid_sig":"PT9-TApz...",
+ * "url":"http:\/\/podunk.edu",
+ * "url_sig":"T8Bp7j...",
+ * "sitekey":"aMtgKTiirXrICP..."
+ * },
+ * "recipients":{
+ * {
+ * "guid":"ZHSqb...",
+ * "guid_sig":"JsAAXi..."
+ * }
+ * }
+ * "callback":"\/post",
+ * "version":1,
+ * "secret":"1eaa661",
+ * "secret_sig":"eKV968b1..."
+ * }
+ * \endcode
+ *
+ * auth_check messages MUST use encapsulated encryption. This message is sent to the origination site, which checks the 'secret' to see
+ * if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the
+ * destination channel's private key and base64url encoded. If everything checks out, a json packet is returned:
+ *
+ * \code{.json}
+ * {
+ * "success":1,
+ * "confirm":"q0Ysovd1u...",
+ * "service_class":(optional)
+ * "level":(optional)
+ * "DNT": (optional do-not-track - 1 or 0)
+ * }
+ * \endcode
+ *
+ * 'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the
+ * base64url encoded whirlpool hash of the requestor's guid and guid_sig; signed with the source channel private key.
+ * This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful
+ * verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login.
+ * Service_class can be used by cooperating sites to provide different access rights based on account rights and subscription plans. It is
+ * a string whose contents are not defined by protocol. Example: "basic" or "gold".
+ *
+ * @param[in,out] App &$a
+ */
diff --git a/Zotlabs/Zot/IHandler.php b/Zotlabs/Zot/IHandler.php
new file mode 100644
index 000000000..eeca1555c
--- /dev/null
+++ b/Zotlabs/Zot/IHandler.php
@@ -0,0 +1,22 @@
+error = false;
+ $this->validated = false;
+ $this->messagetype = '';
+ $this->response = array('success' => false);
+
+ $this->handler = $handler;
+
+ if(! is_array($data))
+ $data = json_decode($data,true);
+
+ if($data && is_array($data)) {
+ $this->encrypted = ((array_key_exists('iv',$data)) ? true : false);
+
+ if($this->encrypted) {
+ $this->data = @json_decode(@crypto_unencapsulate($data,$prvkey),true);
+ }
+ if(! $this->data)
+ $this->data = $data;
+
+ if($this->data && is_array($this->data) && array_key_exists('type',$this->data))
+ $this->messagetype = $this->data['type'];
+ }
+ if(! $this->messagetype)
+ $this->error = true;
+
+ $this->sender = ((array_key_exists('sender',$this->data)) ? $this->data['sender'] : null);
+ $this->recipients = ((array_key_exists('recipients',$this->data)) ? $this->data['recipients'] : null);
+
+
+ if($this->sender)
+ $this->ValidateSender();
+
+ $this->Dispatch();
+ }
+
+ function ValidateSender() {
+ $hubs = zot_gethub($this->sender,true);
+ if (! $hubs) {
+
+ /* Have never seen this guid or this guid coming from this location. Check it and register it. */
+ /* (!!) this will validate the sender. */
+
+ $result = zot_register_hub($this->sender);
+
+ if ((! $result['success']) || (! ($hubs = zot_gethub($this->sender,true)))) {
+ $this->response['message'] = 'Hub not available.';
+ json_return_and_die($this->response);
+ }
+ }
+ foreach($hubs as $hub) {
+ update_hub_connected($hub,((array_key_exists('sitekey',$this->sender)) ? $this->sender['sitekey'] : ''));
+ }
+ $this->validated = true;
+ }
+
+
+ function Dispatch() {
+
+ /* Handle tasks which don't require sender validation */
+
+ switch($this->messagetype) {
+ case 'ping':
+ /* no validation needed */
+ $this->handler->Ping();
+ break;
+ case 'pickup':
+ /* perform site validation, as opposed to sender validation */
+ $this->handler->Pickup($this->data);
+ break;
+
+ default:
+ if(! $this->validated) {
+ $this->response['message'] = 'Sender not valid';
+ json_return_and_die($this->response);
+ }
+ break;
+ }
+
+ /* Now handle tasks which require sender validation */
+
+ switch($this->messagetype) {
+
+ case 'auth_check':
+ $this->handler->AuthCheck($this->data,$this->encrypted);
+ break;
+
+ case 'request':
+ $this->handler->Request($this->data);
+ break;
+
+ case 'purge':
+ $this->handler->Purge($this->sender,$this->recipients);
+ break;
+
+ case 'refresh':
+ case 'force_refresh':
+ $this->handler->Refresh($this->sender,$this->recipients);
+ break;
+
+ case 'notify':
+ $this->handler->Notify($this->data);
+ break;
+
+ default:
+ $this->response['message'] = 'Not implemented';
+ json_return_and_die($this->response);
+ break;
+ }
+
+ }
+}
+
+
+
+/**
+ * @brief zot communications and messaging.
+ *
+ * Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet.
+ * This packet is optionally encrypted, which we will discover if the json has an 'iv' element.
+ * $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data);
+ * $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded.
+ * Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate.
+ *
+ * Once decrypted, one will find the normal json_encoded zot message packet.
+ *
+ * Defined packet types are: notify, purge, refresh, force_refresh, auth_check, ping, and pickup
+ *
+ * Standard packet: (used by notify, purge, refresh, force_refresh, and auth_check)
+ * \code{.json}
+ * {
+ * "type": "notify",
+ * "sender":{
+ * "guid":"kgVFf_1...",
+ * "guid_sig":"PT9-TApzp...",
+ * "url":"http:\/\/podunk.edu",
+ * "url_sig":"T8Bp7j5...",
+ * },
+ * "recipients": { optional recipient array },
+ * "callback":"\/post",
+ * "version":1,
+ * "secret":"1eaa...",
+ * "secret_sig": "df89025470fac8..."
+ * }
+ * \endcode
+ *
+ * Signature fields are all signed with the sender channel private key and base64url encoded.
+ * Recipients are arrays of guid and guid_sig, which were previously signed with the recipients private
+ * key and base64url encoded and later obtained via channel discovery. Absence of recipients indicates
+ * a public message or visible to all potential listeners on this site.
+ *
+ * "pickup" packet:
+ * The pickup packet is sent in response to a notify packet from another site
+ * \code{.json}
+ * {
+ * "type":"pickup",
+ * "url":"http:\/\/example.com",
+ * "callback":"http:\/\/example.com\/post",
+ * "callback_sig":"teE1_fLI...",
+ * "secret":"1eaa...",
+ * "secret_sig":"O7nB4_..."
+ * }
+ * \endcode
+ *
+ * In the pickup packet, the sig fields correspond to the respective data
+ * element signed with this site's system private key and then base64url encoded.
+ * The "secret" is the same as the original secret from the notify packet.
+ *
+ * If verification is successful, a json structure is returned containing a
+ * success indicator and an array of type 'pickup'.
+ * Each pickup element contains the original notify request and a message field
+ * whose contents are dependent on the message type.
+ *
+ * This JSON array is AES encapsulated using the site public key of the site
+ * that sent the initial zot pickup packet.
+ * Using the above example, this would be example.com.
+ *
+ * \code{.json}
+ * {
+ * "success":1,
+ * "pickup":{
+ * "notify":{
+ * "type":"notify",
+ * "sender":{
+ * "guid":"kgVFf_...",
+ * "guid_sig":"PT9-TApz...",
+ * "url":"http:\/\/z.podunk.edu",
+ * "url_sig":"T8Bp7j5D..."
+ * },
+ * "callback":"\/post",
+ * "version":1,
+ * "secret":"1eaa661..."
+ * },
+ * "message":{
+ * "type":"activity",
+ * "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu",
+ * "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu",
+ * "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu",
+ * "created":"2012-11-20 04:04:16",
+ * "edited":"2012-11-20 04:04:16",
+ * "title":"",
+ * "body":"Hi Nickordo",
+ * "app":"",
+ * "verb":"post",
+ * "object_type":"",
+ * "target_type":"",
+ * "permalink":"",
+ * "location":"",
+ * "longlat":"",
+ * "owner":{
+ * "name":"Indigo",
+ * "address":"indigo@podunk.edu",
+ * "url":"http:\/\/podunk.edu",
+ * "photo":{
+ * "mimetype":"image\/jpeg",
+ * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5"
+ * },
+ * "guid":"kgVFf_...",
+ * "guid_sig":"PT9-TAp...",
+ * },
+ * "author":{
+ * "name":"Indigo",
+ * "address":"indigo@podunk.edu",
+ * "url":"http:\/\/podunk.edu",
+ * "photo":{
+ * "mimetype":"image\/jpeg",
+ * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5"
+ * },
+ * "guid":"kgVFf_...",
+ * "guid_sig":"PT9-TAp..."
+ * }
+ * }
+ * }
+ * }
+ * \endcode
+ *
+ * Currently defined message types are 'activity', 'mail', 'profile', 'location'
+ * and 'channel_sync', which each have different content schemas.
+ *
+ * Ping packet:
+ * A ping packet does not require any parameters except the type. It may or may
+ * not be encrypted.
+ *
+ * \code{.json}
+ * {
+ * "type": "ping"
+ * }
+ * \endcode
+ *
+ * On receipt of a ping packet a ping response will be returned:
+ *
+ * \code{.json}
+ * {
+ * "success" : 1,
+ * "site" {
+ * "url": "http:\/\/podunk.edu",
+ * "url_sig": "T8Bp7j5...",
+ * "sitekey": "-----BEGIN PUBLIC KEY-----
+ * MIICIjANBgkqhkiG9w0BAQE..."
+ * }
+ * }
+ * \endcode
+ *
+ * The ping packet can be used to verify that a site has not been re-installed, and to
+ * initiate corrective action if it has. The url_sig is signed with the site private key
+ * and base64url encoded - and this should verify with the enclosed sitekey. Failure to
+ * verify indicates the site is corrupt or otherwise unable to communicate using zot.
+ * This return packet is not otherwise verified, so should be compared with other
+ * results obtained from this site which were verified prior to taking action. For instance
+ * if you have one verified result with this signature and key, and other records for this
+ * url which have different signatures and keys, it indicates that the site was re-installed
+ * and corrective action may commence (remove or mark invalid any entries with different
+ * signatures).
+ * If you have no records which match this url_sig and key - no corrective action should
+ * be taken as this packet may have been returned by an imposter.
+ *
+ * @param[in,out] App &$a
+ */
+
diff --git a/Zotlabs/Zot/ZotHandler.php b/Zotlabs/Zot/ZotHandler.php
new file mode 100644
index 000000000..f9bb05410
--- /dev/null
+++ b/Zotlabs/Zot/ZotHandler.php
@@ -0,0 +1,38 @@
+page['htmlhead'] .= replace_macros(get_markup_template("login_head.tpl"), array(
-// '$baseurl' => $a->get_baseurl(true)
-// ));
-
$tpl = get_markup_template("login.tpl");
if(strlen($a->query_string))
$_SESSION['login_return_url'] = $a->query_string;
diff --git a/doc/Hubzilla_on_OpenShift.bb b/doc/Hubzilla_on_OpenShift.bb
index 9b2c539dc..9ccd66284 100644
--- a/doc/Hubzilla_on_OpenShift.bb
+++ b/doc/Hubzilla_on_OpenShift.bb
@@ -8,7 +8,7 @@ Create an account on OpenShift, then use the registration e-mail and password to
[code]rhc app-create your_app_name php-5.4 mysql-5.5 cron phpmyadmin --namespace your_domain --from-code https://github.com/redmatrix/hubzilla.git -l your@email.address -p your_account_password
[/code]
-Make a note of the database username and password OpenShift creates for your instance, and use these at [url=https://your_app_name-your_domain.rhcloud.com/]https://your_app_name-your_domain.rhcloud.com/[/url] to complete the setup.
+Make a note of the database username and password OpenShift creates for your instance, and use these at [url=https://your_app_name-your_domain.rhcloud.com/]https://your_app_name-your_domain.rhcloud.com/[/url] to complete the setup. You MUST change server address from 127.0.0.1 to localhost.
NOTE: PostgreSQL is NOT supported by the deploy script yet, see [zrl=https://zot-mor.rhcloud.com/display/3c7035f2a6febf87057d84ea0ae511223e9b38dc27913177bc0df053edecac7c@zot-mor.rhcloud.com?zid=haakon%40zot-mor.rhcloud.com]this thread[/zrl].
diff --git a/doc/database/db_abook.bb b/doc/database/db_abook.bb
index 2e4b9c4a7..364429884 100644
--- a/doc/database/db_abook.bb
+++ b/doc/database/db_abook.bb
@@ -39,8 +39,9 @@
[tr][td]abook_unconnected[/td][td]currently unused. Projected usage is to indicate "one-way" connections which were insitgated on this end but are still pending on the remote end. [/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
[tr][td]abook_self[/td][td]is a special case where the owner is the target. Every channel has one abook entry with abook_self and with a target abook_xchan set to channel.channel_hash . When this flag is present, abook_my_perms is the default permissions granted to all new connections and several other fields are unused.[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
[tr][td]abook_feed[/td][td]indicates this connection is an RSS/Atom feed and may trigger special handling.[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
-[tr][td]abook_incl[/td][td]connection filter allow rules separated by LF[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
-[tr][td]abook_excl[/td][td]connection filter deny rules separated by LF[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
+[tr][td]abook_incl[/td][td]connection filter allow rules separated by LF[/td][td]text[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
+[tr][td]abook_excl[/td][td]connection filter deny rules separated by LF[/td][td]text[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
+[tr][td]abook_instance[/td][td]comma separated list of site urls of all channel clones that this connection is connected with (used only for singleton networks which don't support cloning)[/td][td]text[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
[/table]
diff --git a/doc/hidden_configs.bb b/doc/hidden_configs.bb
index 1323730aa..8a02a23f2 100644
--- a/doc/hidden_configs.bb
+++ b/doc/hidden_configs.bb
@@ -65,7 +65,7 @@ This document assumes you're an administrator.
this website. Can be overwritten by user settings.
[b]system > projecthome[/b]
Set the project homepage as the homepage of your hub.
- [b]system > workflowchannelnext[/b]
+ [b]system > workflow_channel_next[/b]
The page to direct users to immediately after creating a channel.
[b]system > max_daily_registrations[/b]
Set the maximum number of new registrations allowed on any day.
@@ -154,6 +154,8 @@ This document assumes you're an administrator.
Needed in some Windows installations to locate the openssl configuration file on the system.
[b]system > hide_help[/b]
Don't display help documentation link in nav bar
+ [b]system > expire_delivery_reports[/b]
+ Expiration in days for delivery reports - default 30
[b]Directory config[/b]
[b]Directory search defaults[/b]
diff --git a/doc/hook/check_channelallowed.bb b/doc/hook/check_channelallowed.bb
new file mode 100644
index 000000000..e7559c92f
--- /dev/null
+++ b/doc/hook/check_channelallowed.bb
@@ -0,0 +1,11 @@
+[h2]check_channelallowed[/h2]
+
+Called when checking the channel (xchan) black and white lists to see if a channel is blocked.
+
+Hook data
+
+ array('hash' => xchan_hash of xchan to check);
+
+ create and set array element 'allowed' to true or false to override the system checks
+
+
diff --git a/doc/hook/check_siteallowed.bb b/doc/hook/check_siteallowed.bb
new file mode 100644
index 000000000..28134cbd2
--- /dev/null
+++ b/doc/hook/check_siteallowed.bb
@@ -0,0 +1,10 @@
+[h2]check_siteallowed[/h2]
+
+Called when checking the site black and white lists to see if a site is blocked.
+
+Hook data
+
+ array('url' => URL of site to check);
+
+ create and set array element 'allowed' to true or false to override the system checks
+
diff --git a/doc/hooklist.bb b/doc/hooklist.bb
index 45a4861d9..9172628a0 100644
--- a/doc/hooklist.bb
+++ b/doc/hooklist.bb
@@ -82,6 +82,12 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/check_account_password]check_account_password[/zrl]
Used to provide policy control over account passwords (minimum length, character set inclusion, etc.)
+[zrl=[baseurl]/help/hook/check_channelallowed]check_channelallowed[/zrl]
+ Used to over-ride or bypass the channel black/white block lists
+
+[zrl=[baseurl]/help/hook/check_siteallowed]check_siteallowed[/zrl]
+ Used to over-ride or bypass the site black/white block lists
+
[zrl=[baseurl]/help/hook/connect_premium]connect_premium[/zrl]
Called when connecting to a premium channel
diff --git a/include/RedDAV/RedBrowser.php b/include/RedDAV/RedBrowser.php
index efea5d92f..1aa5f435e 100644
--- a/include/RedDAV/RedBrowser.php
+++ b/include/RedDAV/RedBrowser.php
@@ -188,7 +188,7 @@ class RedBrowser extends DAV\Browser\Plugin {
$parentHash = '';
$owner = $this->auth->owner_id;
- $splitPath = split('/', $fullPath);
+ $splitPath = explode('/', $fullPath);
if (count($splitPath) > 3) {
for ($i = 3; $i < count($splitPath); $i++) {
$attachName = urldecode($splitPath[$i]);
diff --git a/include/account.php b/include/account.php
index b3a520fd4..e448bdcc6 100644
--- a/include/account.php
+++ b/include/account.php
@@ -67,7 +67,7 @@ function check_account_invite($invite_code) {
$result['message'] .= t('An invitation is required.') . EOL;
}
$r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_code));
- if(! results($r)) {
+ if(! $r) {
$result['message'] .= t('Invitation could not be verified.') . EOL;
}
}
@@ -718,4 +718,4 @@ function upgrade_message($bbcode = false) {
function upgrade_bool_message($bbcode = false) {
$x = upgrade_link($bbcode);
return t('This action is not available under your subscription plan.') . (($x) ? ' ' . $x : '') ;
-}
\ No newline at end of file
+}
diff --git a/include/api.php b/include/api.php
index f279b2aa3..4ad915c03 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1,10 +1,10 @@
$usercache[$nick],
+ 'id' => $nick,
'name' => $name,
'screen_name' => $nick,
'location' => '', //$uinfo[0]['default-location'],
@@ -2299,12 +2298,11 @@ require_once('include/api_auth.php');
api_register_func('api/direct_messages','api_direct_messages_inbox',true);
-
function api_oauth_request_token(&$a, $type){
try{
- $oauth = new FKOAuth1();
+ $oauth = new ZotOAuth1();
$req = OAuthRequest::from_request();
-logger('Req: ' . var_export($req,true));
+ logger('Req: ' . var_export($req,true),LOGGER_DATA);
$r = $oauth->fetch_request_token($req);
}catch(Exception $e){
logger('oauth_exception: ' . print_r($e->getMessage(),true));
@@ -2314,9 +2312,10 @@ logger('Req: ' . var_export($req,true));
echo $r;
killme();
}
+
function api_oauth_access_token(&$a, $type){
try{
- $oauth = new FKOAuth1();
+ $oauth = new ZotOAuth1();
$req = OAuthRequest::from_request();
$r = $oauth->fetch_access_token($req);
}catch(Exception $e){
diff --git a/include/api_auth.php b/include/api_auth.php
index ee9db3f55..c9978c99d 100644
--- a/include/api_auth.php
+++ b/include/api_auth.php
@@ -1,16 +1,18 @@
verify_request($req);
@@ -23,16 +25,14 @@ function api_login(&$a){
call_hooks('logged_in', $a->user);
return;
}
- echo __file__.__line__.__function__."
';
}
$o .= '';
}
@@ -1147,6 +1159,8 @@ function widget_forums($arr) {
function widget_tasklist($arr) {
+ if (! local_channel())
+ return;
require_once('include/event.php');
$o .= '';
@@ -1285,7 +1299,6 @@ function widget_album($args) {
//edit album name
$album_edit = null;
-
$photos = array();
if($r) {
$twist = 'rotright';
@@ -1324,6 +1337,7 @@ function widget_album($args) {
$o .= replace_macros($tpl, array(
'$photos' => $photos,
'$album' => (($title) ? $title : $album),
+ '$album_id' => rand(),
'$album_edit' => array(t('Edit Album'), $album_edit),
'$can_post' => false,
'$upload' => array(t('Upload'), z_root() . '/photos/' . get_app()->profile['channel_address'] . '/upload/' . bin2hex($album)),
diff --git a/include/zot.php b/include/zot.php
index c0d537eb9..390407e4e 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -554,18 +554,8 @@ function zot_gethub($arr,$multiple = false) {
if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) {
- $blacklisted = false;
- $bl1 = get_config('system','blacklisted_sites');
- if(is_array($bl1) && $bl1) {
- foreach($bl1 as $bl) {
- if($bl && strpos($arr['url'],$bl) !== false) {
- $blacklisted = true;
- break;
- }
- }
- }
- if($blacklisted) {
- logger('zot_gethub: blacklisted site: ' . $arr['url']);
+ if(! check_siteallowed($arr['url'])) {
+ logger('blacklisted site: ' . $arr['url']);
return null;
}
@@ -1246,6 +1236,10 @@ function zot_import($arr, $sender_url) {
$no_dups = array();
if($deliveries) {
foreach($deliveries as $d) {
+ if(! is_array($d)) {
+ logger('Delivery hash array is not an array: ' . print_r($d,true));
+ continue;
+ }
if(! in_array($d['hash'],$no_dups))
$no_dups[] = $d['hash'];
}
@@ -1617,6 +1611,14 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
$channel = $r[0];
$DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ /* blacklisted channels get a permission denied, no special message to tip them off */
+
+ if(! check_channelallowed($sender['hash'])) {
+ $DR->update('permission denied');
+ $result[] = $DR->get();
+ continue;
+ }
+
/**
* @FIXME: Somehow we need to block normal message delivery from our clones, as the delivered
* message doesn't have ACL information in it as the cloned copy does. That copy
@@ -2088,6 +2090,14 @@ function process_mail_delivery($sender, $arr, $deliveries) {
$channel = $r[0];
$DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ /* blacklisted channels get a permission denied, no special message to tip them off */
+
+ if(! check_channelallowed($sender['hash'])) {
+ $DR->update('permission denied');
+ $result[] = $DR->get();
+ continue;
+ }
+
if(! perm_is_allowed($channel['channel_id'],$sender['hash'],'post_mail')) {
logger("permission denied for mail delivery {$channel['channel_id']}");
$DR->update('permission denied');
@@ -3484,13 +3494,13 @@ function import_author_zot($x) {
* @param array $data
* @return array
*/
-function zot_process_message_request($data) {
+function zot_reply_message_request($data) {
$ret = array('success' => false);
if (! $data['message_id']) {
$ret['message'] = 'no message_id';
logger('no message_id');
- return $ret;
+ json_return_and_die($ret);
}
$sender = $data['sender'];
@@ -3508,7 +3518,7 @@ function zot_process_message_request($data) {
if (! $c) {
logger('recipient channel not found.');
$ret['message'] .= 'recipient not found.' . EOL;
- return $ret;
+ json_return_and_die($ret);
}
/*
@@ -3526,7 +3536,7 @@ function zot_process_message_request($data) {
);
if (! $r) {
logger('no hubs');
- return $ret;
+ json_return_and_die($ret);
}
$hubs = $r;
@@ -3567,8 +3577,7 @@ function zot_process_message_request($data) {
}
}
$ret['success'] = true;
-
- return $ret;
+ json_return_and_die($ret);
}
@@ -3789,6 +3798,7 @@ function zotinfo($arr) {
$ret['site'] = array();
$ret['site']['url'] = z_root();
$ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey']));
+ $ret['site']['zot_auth'] = z_root() . '/magic';
$dirmode = get_config('system','directory_mode');
if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL))
@@ -3979,3 +3989,421 @@ function delivery_report_is_storable($dr) {
}
+
+function update_hub_connected($hub,$sitekey = '') {
+
+ if($sitekey) {
+
+ /*
+ * This hub has now been proven to be valid.
+ * Any hub with the same URL and a different sitekey cannot be valid.
+ * Get rid of them (mark them deleted). There's a good chance they were re-installs.
+ */
+
+ q("update hubloc set hubloc_deleted = 1, hubloc_error = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' ",
+ dbesc($hub['hubloc_url']),
+ dbesc($sitekey)
+ );
+
+ }
+ else {
+ $sitekey = $hub['sitekey'];
+ }
+
+ // $sender['sitekey'] is a new addition to the protcol to distinguish
+ // hublocs coming from re-installed sites. Older sites will not provide
+ // this field and we have to still mark them valid, since we can't tell
+ // if this hubloc has the same sitekey as the packet we received.
+
+
+ // Update our DB to show when we last communicated successfully with this hub
+ // This will allow us to prune dead hubs from using up resources
+
+ $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_sitekey = '%s' ",
+ dbesc(datetime_convert()),
+ intval($hub['hubloc_id']),
+ dbesc($sitekey)
+ );
+
+ // a dead hub came back to life - reset any tombstones we might have
+
+ if(intval($hub['hubloc_error'])) {
+ q("update hubloc set hubloc_error = 0 where hubloc_id = %d and hubloc_sitekey = '%s' ",
+ intval($hub['hubloc_id']),
+ dbesc($sitekey)
+ );
+ if(intval($r[0]['hubloc_orphancheck'])) {
+ q("update hubloc set hubloc_orhpancheck = 0 where hubloc_id = %d and hubloc_sitekey = '%s' ",
+ intval($hub['hubloc_id']),
+ dbesc($sitekey)
+ );
+ }
+ q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'",
+ dbesc($hub['hubloc_hash'])
+ );
+ }
+
+ return $hub['hubloc_url'];
+}
+
+
+function zot_reply_ping() {
+
+ $ret = array('success'=> false);
+
+ // Useful to get a health check on a remote site.
+ // This will let us know if any important communication details
+ // that we may have stored are no longer valid, regardless of xchan details.
+ logger('POST: got ping send pong now back: ' . z_root() , LOGGER_DEBUG );
+
+ $ret['success'] = true;
+ $ret['site'] = array();
+ $ret['site']['url'] = z_root();
+ $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),get_config('system','prvkey')));
+ $ret['site']['sitekey'] = get_config('system','pubkey');
+ json_return_and_die($ret);
+}
+
+function zot_reply_pickup($data) {
+
+ $ret = array('success'=> false);
+
+ /*
+ * The 'pickup' message arrives with a tracking ID which is associated with a particular outq_hash
+ * First verify that that the returned signatures verify, then check that we have an outbound queue item
+ * with the correct hash.
+ * If everything verifies, find any/all outbound messages in the queue for this hubloc and send them back
+ */
+
+ if((! $data['secret']) || (! $data['secret_sig'])) {
+ $ret['message'] = 'no verification signature';
+ logger('mod_zot: pickup: ' . $ret['message'], LOGGER_DEBUG);
+ json_return_and_die($ret);
+ }
+
+ $r = q("select distinct hubloc_sitekey from hubloc where hubloc_url = '%s' and hubloc_callback = '%s' and hubloc_sitekey != '' group by hubloc_sitekey ",
+ dbesc($data['url']),
+ dbesc($data['callback'])
+ );
+ if(! $r) {
+ $ret['message'] = 'site not found';
+ logger('mod_zot: pickup: ' . $ret['message']);
+ json_return_and_die($ret);
+ }
+
+ foreach ($r as $hubsite) {
+
+ // verify the url_sig
+ // If the server was re-installed at some point, there could be multiple hubs with the same url and callback.
+ // Only one will have a valid key.
+
+ $forgery = true;
+ $secret_fail = true;
+
+ $sitekey = $hubsite['hubloc_sitekey'];
+
+ logger('mod_zot: Checking sitekey: ' . $sitekey, LOGGER_DATA);
+
+ if(rsa_verify($data['callback'],base64url_decode($data['callback_sig']),$sitekey)) {
+ $forgery = false;
+ }
+ if(rsa_verify($data['secret'],base64url_decode($data['secret_sig']),$sitekey)) {
+ $secret_fail = false;
+ }
+ if((! $forgery) && (! $secret_fail))
+ break;
+ }
+
+ if($forgery) {
+ $ret['message'] = 'possible site forgery';
+ logger('mod_zot: pickup: ' . $ret['message']);
+ json_return_and_die($ret);
+ }
+
+ if($secret_fail) {
+ $ret['message'] = 'secret validation failed';
+ logger('mod_zot: pickup: ' . $ret['message']);
+ json_return_and_die($ret);
+ }
+
+ /*
+ * If we made it to here, the signatures verify, but we still don't know if the tracking ID is valid.
+ * It wouldn't be an error if the tracking ID isn't found, because we may have sent this particular
+ * queue item with another pickup (after the tracking ID for the other pickup was verified).
+ */
+
+ $r = q("select outq_posturl from outq where outq_hash = '%s' and outq_posturl = '%s' limit 1",
+ dbesc($data['secret']),
+ dbesc($data['callback'])
+ );
+ if(! $r) {
+ $ret['message'] = 'nothing to pick up';
+ logger('mod_zot: pickup: ' . $ret['message']);
+ json_return_and_die($ret);
+ }
+
+ /*
+ * Everything is good if we made it here, so find all messages that are going to this location
+ * and send them all.
+ */
+
+ $r = q("select * from outq where outq_posturl = '%s'",
+ dbesc($data['callback'])
+ );
+ if($r) {
+ logger('mod_zot: successful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG);
+
+ $ret['success'] = true;
+ $ret['pickup'] = array();
+ foreach($r as $rr) {
+ if($rr['outq_msg']) {
+ $x = json_decode($rr['outq_msg'],true);
+
+ if(! $x)
+ continue;
+
+ if(array_key_exists('message_list',$x)) {
+ foreach($x['message_list'] as $xx) {
+ $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => $xx);
+ }
+ }
+ else
+ $ret['pickup'][] = array('notify' => json_decode($rr['outq_notify'],true),'message' => $x);
+ $x = q("delete from outq where outq_hash = '%s'",
+ dbesc($rr['outq_hash'])
+ );
+ }
+ }
+ }
+
+ $encrypted = crypto_encapsulate(json_encode($ret),$sitekey);
+ json_return_and_die($encrypted);
+
+ /* pickup: end */
+}
+
+
+
+function zot_reply_auth_check($data,$encrypted_packet) {
+
+ $ret = array('success' => false);
+
+ /*
+ * Requestor visits /magic/?dest=somewhere on their own site with a browser
+ * magic redirects them to $destsite/post [with auth args....]
+ * $destsite sends an auth_check packet to originator site
+ * The auth_check packet is handled here by the originator's site
+ * - the browser session is still waiting
+ * inside $destsite/post for everything to verify
+ * If everything checks out we'll return a token to $destsite
+ * and then $destsite will verify the token, authenticate the browser
+ * session and then redirect to the original destination.
+ * If authentication fails, the redirection to the original destination
+ * will still take place but without authentication.
+ */
+ logger('mod_zot: auth_check', LOGGER_DEBUG);
+
+ if (! $encrypted_packet) {
+ logger('mod_zot: auth_check packet was not encrypted.');
+ $ret['message'] .= 'no packet encryption' . EOL;
+ json_return_and_die($ret);
+ }
+
+ $arr = $data['sender'];
+ $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']);
+
+ // garbage collect any old unused notifications
+
+ // This was and should be 10 minutes but my hosting provider has time lag between the DB and
+ // the web server. We should probably convert this to webserver time rather than DB time so
+ // that the different clocks won't affect it and allow us to keep the time short.
+
+ q("delete from verify where type = 'auth' and created < %s - INTERVAL %s",
+ db_utcnow(), db_quoteinterval('30 MINUTE')
+ );
+
+ $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
+ dbesc($sender_hash)
+ );
+
+ // We created a unique hash in mod/magic.php when we invoked remote auth, and stored it in
+ // the verify table. It is now coming back to us as 'secret' and is signed by a channel at the other end.
+ // First verify their signature. We will have obtained a zot-info packet from them as part of the sender
+ // verification.
+
+ if ((! $y) || (! rsa_verify($data['secret'], base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) {
+ logger('mod_zot: auth_check: sender not found or secret_sig invalid.');
+ $ret['message'] .= 'sender not found or sig invalid ' . print_r($y,true) . EOL;
+ json_return_and_die($ret);
+ }
+
+ // There should be exactly one recipient, the original auth requestor
+
+ $ret['message'] .= 'recipients ' . print_r($recipients,true) . EOL;
+
+ if ($data['recipients']) {
+
+ $arr = $data['recipients'][0];
+ $recip_hash = make_xchan_hash($arr['guid'], $arr['guid_sig']);
+ $c = q("select channel_id, channel_account_id, channel_prvkey from channel where channel_hash = '%s' limit 1",
+ dbesc($recip_hash)
+ );
+ if (! $c) {
+ logger('mod_zot: auth_check: recipient channel not found.');
+ $ret['message'] .= 'recipient not found.' . EOL;
+ json_return_and_die($ret);
+ }
+
+ $confirm = base64url_encode(rsa_sign($data['secret'] . $recip_hash,$c[0]['channel_prvkey']));
+
+ // This additionally checks for forged sites since we already stored the expected result in meta
+ // and we've already verified that this is them via zot_gethub() and that their key signed our token
+
+ $z = q("select id from verify where channel = %d and type = 'auth' and token = '%s' and meta = '%s' limit 1",
+ intval($c[0]['channel_id']),
+ dbesc($data['secret']),
+ dbesc($data['sender']['url'])
+ );
+ if (! $z) {
+ logger('mod_zot: auth_check: verification key not found.');
+ $ret['message'] .= 'verification key not found' . EOL;
+ json_return_and_die($ret);
+ }
+ $r = q("delete from verify where id = %d",
+ intval($z[0]['id'])
+ );
+
+ $u = q("select account_service_class from account where account_id = %d limit 1",
+ intval($c[0]['channel_account_id'])
+ );
+
+ logger('mod_zot: auth_check: success', LOGGER_DEBUG);
+ $ret['success'] = true;
+ $ret['confirm'] = $confirm;
+ if ($u && $u[0]['account_service_class'])
+ $ret['service_class'] = $u[0]['account_service_class'];
+
+ // Set "do not track" flag if this site or this channel's profile is restricted
+ // in some way
+
+ if (intval(get_config('system','block_public')))
+ $ret['DNT'] = true;
+ if (! perm_is_allowed($c[0]['channel_id'],'','view_profile'))
+ $ret['DNT'] = true;
+ if (get_pconfig($c[0]['channel_id'],'system','do_not_track'))
+ $ret['DNT'] = true;
+ if (get_pconfig($c[0]['channel_id'],'system','hide_online_status'))
+ $ret['DNT'] = true;
+
+ json_return_and_die($ret);
+ }
+ json_return_and_die($ret);
+}
+
+
+function zot_reply_purge($sender,$recipients) {
+
+ $ret = array('success' => false);
+
+ if ($recipients) {
+ // basically this means "unfriend"
+ foreach ($recipients as $recip) {
+ $r = q("select channel.*,xchan.* from channel
+ left join xchan on channel_hash = xchan_hash
+ where channel_guid = '%s' and channel_guid_sig = '%s' limit 1",
+ dbesc($recip['guid']),
+ dbesc($recip['guid_sig'])
+ );
+ if ($r) {
+ $r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1",
+ intval($r[0]['channel_id']),
+ dbesc(make_xchan_hash($sender['guid'],$sender['guid_sig']))
+ );
+ if ($r) {
+ contact_remove($r[0]['channel_id'],$r[0]['abook_id']);
+ }
+ }
+ }
+ $ret['success'] = true;
+ }
+ else {
+ // Unfriend everybody - basically this means the channel has committed suicide
+ $arr = $sender;
+ $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']);
+
+ require_once('include/Contact.php');
+ remove_all_xchan_resources($sender_hash);
+
+ $ret['success'] = true;
+ }
+
+ json_return_and_die($ret);
+}
+
+
+function zot_reply_refresh($sender,$recipients) {
+
+ $ret = array('success' => false);
+
+ // remote channel info (such as permissions or photo or something)
+ // has been updated. Grab a fresh copy and sync it.
+ // The difference between refresh and force_refresh is that
+ // force_refresh unconditionally creates a directory update record,
+ // even if no changes were detected upon processing.
+
+ if($recipients) {
+
+ // This would be a permissions update, typically for one connection
+
+ foreach ($recipients as $recip) {
+ $r = q("select channel.*,xchan.* from channel
+ left join xchan on channel_hash = xchan_hash
+ where channel_guid = '%s' and channel_guid_sig = '%s' limit 1",
+ dbesc($recip['guid']),
+ dbesc($recip['guid_sig'])
+ );
+
+ $x = zot_refresh(array(
+ 'xchan_guid' => $sender['guid'],
+ 'xchan_guid_sig' => $sender['guid_sig'],
+ 'hubloc_url' => $sender['url']
+ ), $r[0], (($msgtype === 'force_refresh') ? true : false));
+ }
+ }
+ else {
+ // system wide refresh
+
+ $x = zot_refresh(array(
+ 'xchan_guid' => $sender['guid'],
+ 'xchan_guid_sig' => $sender['guid_sig'],
+ 'hubloc_url' => $sender['url']
+ ), null, (($msgtype === 'force_refresh') ? true : false));
+ }
+
+ $ret['success'] = true;
+ json_return_and_die($ret);
+
+}
+
+
+function zot_reply_notify($data) {
+
+ $ret = array('success' => false);
+
+ logger('notify received from ' . $data['sender']['url']);
+
+ $async = get_config('system','queued_fetch');
+
+ if($async) {
+ // add to receive queue
+ // qreceive_add($data);
+ }
+ else {
+ $x = zot_fetch($data);
+ $ret['delivery_report'] = $x;
+ }
+
+ $ret['success'] = true;
+ json_return_and_die($ret);
+
+}
\ No newline at end of file
diff --git a/install/schema_mysql.sql b/install/schema_mysql.sql
index 3dab6c822..9c24cbd94 100644
--- a/install/schema_mysql.sql
+++ b/install/schema_mysql.sql
@@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS `abook` (
`abook_profile` char(64) NOT NULL DEFAULT '',
`abook_incl` TEXT NOT NULL DEFAULT '',
`abook_excl` TEXT NOT NULL DEFAULT '',
+ `abook_instance` TEXT NOT NULL DEFAULT '',
PRIMARY KEY (`abook_id`),
KEY `abook_account` (`abook_account`),
KEY `abook_channel` (`abook_channel`),
diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql
index 95ed9acb7..0214c0c2a 100644
--- a/install/schema_postgres.sql
+++ b/install/schema_postgres.sql
@@ -22,6 +22,7 @@ CREATE TABLE "abook" (
"abook_profile" char(64) NOT NULL DEFAULT '',
"abook_incl" TEXT NOT NULL DEFAULT '',
"abook_excl" TEXT NOT NULL DEFAULT '',
+ "abook_instance" TEXT NOT NULL DEFAULT '',
PRIMARY KEY ("abook_id")
);
create index "abook_account" on abook ("abook_account");
diff --git a/install/update.php b/install/update.php
index 10ae6725e..24f4f21d5 100644
--- a/install/update.php
+++ b/install/update.php
@@ -1,6 +1,6 @@
registerFilter(). It can be used to unregister a filter by name.
+ - $smarty->registerFilter('output', $callback, 'name');
+ $smarty->unregister('output', 'name');
+
+ Closures
+ $smarty->registerFilter() does now accept closures.
+ - $smarty->registerFilter('pre', function($source) {return $source;});
+ If no optional filter name was specified it gets the default name 'closure'.
+ If you register multiple closures register each with a unique filter name.
+ - $smarty->registerFilter('pre', function($source) {return $source;}, 'clousre_1');
+ - $smarty->registerFilter('pre', function($source) {return $source;}, 'clousre_2');
+
+
+Smarty 3.1.22
+
+ Namespace support within templates
+ ==================================
+ Within templates you can now use namespace specifications on:
+ - Constants like foo\bar\FOO
+ - Class names like foo\bar\Baz::FOO, foo\bar\Baz::$foo, foo\bar\Baz::foo()
+ - PHP function names like foo\bar\baz()
+
+ Security
+ ========
+ - disable special $smarty variable -
+ The Smarty_Security class has the new property $disabled_special_smarty_vars.
+ It's an array which can be loaded with the $smarty special variable names like
+ 'template_object', 'template', 'current_dir' and others which will be disabled.
+ Note: That this security check is performed at compile time.
+
+ - limit template nesting -
+ Property $max_template_nesting of Smarty_Security does set the maximum template nesting level.
+ The main template is level 1. The nesting level is checked at run time. When the maximum will be exceeded
+ an Exception will be thrown. The default setting is 0 which does disable this check.
+
+ - trusted static methods -
+ The Smarty_Security class has the new property $trusted_static_methods to restrict access to static methods.
+ It's an nested array of trusted class and method names.
+ Format:
+ array (
+ 'class_1' => array('method_1', 'method_2'), // allowed methods
+ 'class_2' => array(), // all methods of class allowed
+ )
+ To disable access for all methods of all classes set $trusted_static_methods = null;
+ The default value is an empty array() which does enables all methods of all classes, but for backward compatibility
+ the setting of $static_classes will be checked.
+ Note: That this security check is performed at compile time.
+
+ - trusted static properties -
+ The Smarty_Security class has the new property $trusted_static_properties to restrict access to static properties.
+ It's an nested array of trusted class and property names.
+ Format:
+ array (
+ 'class_1' => array('prop_1', 'prop_2'), // allowed properties listed
+ 'class_2' => array(), // all properties of class allowed
+ }
+ To disable access for all properties of all classes set $trusted_static_properties = null;
+ The default value is an empty array() which does enables all properties of all classes, but for backward compatibility
+ the setting of $static_classes will be checked.
+ Note: That this security check is performed at compile time.
+
+ - trusted constants .
+ The Smarty_Security class has the new property $trusted_constants to restrict access to constants.
+ It's an array of trusted constant names.
+ Format:
+ array (
+ 'SMARTY_DIR' , // allowed constant
+ }
+ If the array is empty (default) the usage of constants can be controlled with the
+ Smarty_Security::$allow_constants property (default true)
+
+
+
+ Compiled Templates
+ ==================
+ Smarty does now automatically detects a change of the $merge_compiled_includes and $escape_html
+ property and creates different compiled templates files depending on the setting.
+
+ Same applies to config files and the $config_overwrite, $config_booleanize and
+ $config_read_hidden properties.
+
+ Debugging
+ =========
+ The layout of the debug window has been changed for better readability
+
+ New class constants
+ Smarty::DEBUG_OFF
+ Smarty::DEBUG_ON
+ Smarty::DEBUG_INDIVIDUAL
+ have been introduced for setting the $debugging property.
+
+ Smarty::DEBUG_INDIVIDUAL will create for each display() and fetch() call an individual debug window.
+
+ .
+
\ No newline at end of file
diff --git a/library/Smarty/README b/library/Smarty/README
index 6367f030e..08b397c3f 100644
--- a/library/Smarty/README
+++ b/library/Smarty/README
@@ -1,4 +1,4 @@
-Smarty 3.1.21
+Smarty 3.x
Author: Monte Ohrt
Author: Uwe Tews
@@ -460,12 +460,13 @@ included template.
PLUGINS
=======
-Smarty3 are following the same coding rules as in Smarty2.
-The only difference is that the template object is passed as additional third parameter.
+Smarty 3 plugins follow the same coding rules as in Smarty 2.
+The main difference is that the template object is now passed in place of the smarty object.
+The smarty object can be still be accessed through $template->smarty.
-smarty_plugintype_name (array $params, object $smarty, object $template)
+smarty_plugintype_name (array $params, Smarty_Internal_Template $template)
-The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty2 internals.
+The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty 2 internals.
TEMPLATE INHERITANCE:
diff --git a/library/Smarty/SMARTY_2_BC_NOTES.txt b/library/Smarty/SMARTY_2_BC_NOTES.txt
deleted file mode 100644
index 79a2cb1b6..000000000
--- a/library/Smarty/SMARTY_2_BC_NOTES.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-= Known incompatibilities with Smarty 2 =
-
-== Syntax ==
-
-Smarty 3 API has a new syntax. Much of the Smarty 2 syntax is supported
-by a wrapper but deprecated. See the README that comes with Smarty 3 for more
-information.
-
-The {$array|@mod} syntax has always been a bit confusing, where an "@" is required
-to apply a modifier to an array instead of the individual elements. Normally you
-always want the modifier to apply to the variable regardless of its type. In Smarty 3,
-{$array|mod} and {$array|@mod} behave identical. It is safe to drop the "@" and the
-modifier will still apply to the array. If you really want the modifier to apply to
-each array element, you must loop the array in-template, or use a custom modifier that
-supports array iteration. Most smarty functions already escape values where necessary
-such as {html_options}
-
-== PHP Version ==
-Smarty 3 is PHP 5 only. It will not work with PHP 4.
-
-== {php} Tag ==
-The {php} tag is disabled by default. The use of {php} tags is
-deprecated. It can be enabled with $smarty->allow_php_tag=true.
-
-But if you scatter PHP code which belongs together into several
-{php} tags it may not work any longer.
-
-== Delimiters and whitespace ==
-Delimiters surrounded by whitespace are no longer treated as Smarty tags.
-Therefore, { foo } will not compile as a tag, you must use {foo}. This change
-Makes Javascript/CSS easier to work with, eliminating the need for {literal}.
-This can be disabled by setting $smarty->auto_literal = false;
-
-== Unquoted Strings ==
-Smarty 2 was a bit more forgiving (and ambiguous) when it comes to unquoted strings
-in parameters. Smarty3 is more restrictive. You can still pass strings without quotes
-so long as they contain no special characters. (anything outside of A-Za-z0-9_)
-
-For example filename strings must be quoted
-
-{include file='path/foo.tpl'}
-
-
-== Extending the Smarty class ==
-Smarty 3 makes use of the __construct method for initialization. If you are extending
-the Smarty class, its constructor is not called implicitly if the your child class defines
-its own constructor. In order to run Smarty's constructor, a call to parent::__construct()
-within your child constructor is required.
-
-
-class MySmarty extends Smarty {
- function __construct() {
- parent::__construct();
-
- // your initialization code goes here
-
- }
-}
-
-
-== Autoloader ==
-Smarty 3 does register its own autoloader with spl_autoload_register. If your code has
-an existing __autoload function then this function must be explicitly registered on
-the __autoload stack. See http://us3.php.net/manual/en/function.spl-autoload-register.php
-for further details.
-
-== Plugin Filenames ==
-Smarty 3 optionally supports the PHP spl_autoloader. The autoloader requires filenames
-to be lower case. Because of this, Smarty plugin file names must also be lowercase.
-In Smarty 2, mixed case file names did work.
-
-== Scope of Special Smarty Variables ==
-In Smarty 2 the special Smarty variables $smarty.section... and $smarty.foreach...
-had global scope. If you had loops with the same name in subtemplates you could accidentally
-overwrite values of parent template.
-
-In Smarty 3 these special Smarty variable have only local scope in the template which
-is defining the loop. If you need their value in a subtemplate you have to pass them
-as parameter.
-
-{include file='path/foo.tpl' index=$smarty.section.foo.index}
-
-
-== SMARTY_RESOURCE_CHAR_SET ==
-Smarty 3 sets the constant SMARTY_RESOURCE_CHAR_SET to utf-8 as default template charset.
-This is now used also on modifiers like escape as default charset. If your templates use
-other charsets make sure that you define the constant accordingly. Otherwise you may not
-get any output.
-
-== newline at {if} tags ==
-A \n was added to the compiled code of the {if},{else},{elseif},{/if} tags to get output of newlines as expected by the template source.
-If one of the {if} tags is at the line end you will now get a newline in the HTML output.
-
-== trigger_error() ==
-The API function trigger_error() has been removed because it did just map to PHP trigger_error.
-However it's still included in the Smarty2 API wrapper.
-
-== Smarty constants ==
-The constants
-SMARTY_PHP_PASSTHRU
-SMARTY_PHP_QUOTE
-SMARTY_PHP_REMOVE
-SMARTY_PHP_ALLOW
-have been replaced with class constants
-Smarty::PHP_PASSTHRU
-Smarty::PHP_QUOTE
-Smarty::PHP_REMOVE
-Smarty::PHP_ALLOW
-
diff --git a/library/Smarty/SMARTY_3.0_BC_NOTES.txt b/library/Smarty/SMARTY_3.0_BC_NOTES.txt
deleted file mode 100644
index fd8b540c2..000000000
--- a/library/Smarty/SMARTY_3.0_BC_NOTES.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-== Smarty2 backward compatibility ==
-All Smarty2 specific API functions and deprecated functionallity has been moved
-to the SmartyBC class.
-
-== {php} Tag ==
-The {php} tag is no longer available in the standard Smarty calls.
-The use of {php} tags is deprecated and only available in the SmartyBC class.
-
-== {include_php} Tag ==
-The {include_php} tag is no longer available in the standard Smarty calls.
-The use of {include_php} tags is deprecated and only available in the SmartyBC class.
-
-== php template resource ==
-The support of the php template resource is removed.
-
-== $cache_dir, $compile_dir, $config_dir, $template_dir access ==
-The mentioned properties can't be accessed directly any longer. You must use
-corresponding getter/setters like addConfigDir(), setConfigDir(), getConfigDir()
-
-== obsolete Smarty class properties ==
-The following no longer used properties are removed:
-$allow_php_tag
-$allow_php_template
-$deprecation_notices
\ No newline at end of file
diff --git a/library/Smarty/SMARTY_3.1_NOTES.txt b/library/Smarty/SMARTY_3.1_NOTES.txt
deleted file mode 100644
index 57709f0d7..000000000
--- a/library/Smarty/SMARTY_3.1_NOTES.txt
+++ /dev/null
@@ -1,306 +0,0 @@
-Smarty 3.1 Notes
-================
-
-Smarty 3.1 is a departure from 2.0 compatibility. Most notably, all
-backward compatibility has been moved to a separate class file named
-SmartyBC.class.php. If you require compatibility with 2.0, you will
-need to use this class.
-
-Some differences from 3.0 are also present. 3.1 begins the journey of
-requiring setters/getters for property access. So far this is only
-implemented on the five directory properties: template_dir,
-plugins_dir, configs_dir, compile_dir and cache_dir. These properties
-are now protected, it is required to use the setters/getters instead.
-That said, direct property access will still work, however slightly
-slower since they will now fall through __set() and __get() and in
-turn passed through the setter/getter methods. 3.2 will exhibit a full
-list of setter/getter methods for all (currently) public properties,
-so code-completion in your IDE will work as expected.
-
-There is absolutely no PHP allowed in templates any more. All
-deprecated features of Smarty 2.0 are gone. Again, use the SmartyBC
-class if you need any backward compatibility.
-
-Internal Changes
-
- Full UTF-8 Compatibility
-
-The plugins shipped with Smarty 3.1 have been rewritten to fully
-support UTF-8 strings if Multibyte String is available. Without
-MBString UTF-8 cannot be handled properly. For those rare cases where
-templates themselves have to juggle encodings, the new modifiers
-to_charset and from_charset may come in handy.
-
- Plugin API and Performance
-
-All Plugins (modifiers, functions, blocks, resources,
-default_template_handlers, etc) are now receiving the
-Smarty_Internal_Template instance, where they were supplied with the
-Smarty instance in Smarty 3.0. *. As The Smarty_Internal_Template
-mimics the behavior of Smarty, this API simplification should not
-require any changes to custom plugins.
-
-The plugins shipped with Smarty 3.1 have been rewritten for better
-performance. Most notably {html_select_date} and {html_select_time}
-have been improved vastly. Performance aside, plugins have also been
-reviewed and generalized in their API. {html_select_date} and
-{html_select_time} now share almost all available options.
-
-The escape modifier now knows the $double_encode option, which will
-prevent entities from being encoded again.
-
-The capitalize modifier now know the $lc_rest option, which makes sure
-all letters following a captial letter are lower-cased.
-
-The count_sentences modifier now accepts (.?!) as
-legitimate endings of a sentence - previously only (.) was
-accepted
-
-The new unescape modifier is there to reverse the effects of the
-escape modifier. This applies to the escape formats html, htmlall and
-entity.
-
- default_template_handler_func
-
-The invocation of $smarty->$default_template_handler_func had to be
-altered. Instead of a Smarty_Internal_Template, the fifth argument is
-now provided with the Smarty instance. New footprint:
-
-
-/**
- * Default Template Handler
- *
- * called when Smarty's file: resource is unable to load a requested file
- *
- * @param string $type resource type (e.g. "file", "string", "eval", "resource")
- * @param string $name resource name (e.g. "foo/bar.tpl")
- * @param string &$content template's content
- * @param integer &$modified template's modification time
- * @param Smarty $smarty Smarty instance
- * @return string|boolean path to file or boolean true if $content and $modified
- * have been filled, boolean false if no default template
- * could be loaded
- */
-function default_template_handler_func($type, $name, &$content, &$modified, Smarty $smarty) {
- if (false) {
- // return corrected filepath
- return "/tmp/some/foobar.tpl";
- } elseif (false) {
- // return a template directly
- $content = "the template source";
- $modified = time();
- return true;
- } else {
- // tell smarty that we failed
- return false;
- }
-}
-
- Stuff done to the compiler
-
-Many performance improvements have happened internally. One notable
-improvement is that all compiled templates are now handled as PHP
-functions. This speeds up repeated templates tremendously, as each one
-calls an (in-memory) PHP function instead of performing another file
-include/scan.
-
-New Features
-
- Template syntax
-
- {block}..{/block}
-
-The {block} tag has a new hide option flag. It does suppress the block
-content if no corresponding child block exists.
-EXAMPLE:
-parent.tpl
-{block name=body hide} child content "{$smarty.block.child}" was
-inserted {block}
-In the above example the whole block will be suppressed if no child
-block "body" is existing.
-
- {setfilter}..{/setfilter}
-
-The new {setfilter} block tag allows the definition of filters which
-run on variable output.
-SYNTAX:
-{setfilter filter1|filter2|filter3....}
-Smarty3 will lookup up matching filters in the following search order:
-1. varibale filter plugin in plugins_dir.
-2. a valid modifier. A modifier specification will also accept
-additional parameter like filter2:'foo'
-3. a PHP function
-{/setfilter} will turn previous filter setting off again.
-{setfilter} tags can be nested.
-EXAMPLE:
-{setfilter filter1}
- {$foo}
- {setfilter filter2}
- {$bar}
- {/setfilter}
- {$buh}
-{/setfilter}
-{$blar}
-In the above example filter1 will run on the output of $foo, filter2
-on $bar, filter1 again on $buh and no filter on $blar.
-NOTES:
-- {$foo nofilter} will suppress the filters
-- These filters will run in addition to filters defined by
-registerFilter('variable',...), autoLoadFilter('variable',...) and
-defined default modifier.
-- {setfilter} will effect only the current template, not included
-subtemplates.
-
- Resource API
-
-Smarty 3.1 features a new approach to resource management. The
-Smarty_Resource API allows simple, yet powerful integration of custom
-resources for templates and configuration files. It offers simple
-functions for loading data from a custom resource (e.g. database) as
-well as define new template types adhering to the special
-non-compiling (e,g, plain php) and non-compile-caching (e.g. eval:
-resource type) resources.
-
-See demo/plugins/resource.mysql.php for an example custom database
-resource.
-
-Note that old-fashioned registration of callbacks for resource
-management has been deprecated but is still possible with SmartyBC.
-
- CacheResource API
-
-In line with the Resource API, the CacheResource API offers a more
-comfortable handling of output-cache data. With the
-Smarty_CacheResource_Custom accessing databases is made simple. With
-the introduction of Smarty_CacheResource_KeyValueStore the
-implementation of resources like memcache or APC became a no-brainer;
-simple hash-based storage systems are now supporting hierarchical
-output-caches.
-
-See demo/plugins/cacheresource.mysql.php for an example custom
-database CacheResource.
-See demo/plugins/cacheresource.memcache.php for an example custom
-memcache CacheResource using the KeyValueStore helper.
-
-Note that old-fashioned registration of $cache_handler is not possible
-anymore. As the functionality had not been ported to Smarty 3.0.x
-properly, it has been dropped from 3.1 completely.
-
-Locking facilities have been implemented to avoid concurrent cache
-generation. Enable cache locking by setting
-$smarty->cache_locking = true;
-
- Relative Paths in Templates (File-Resource)
-
-As of Smarty 3.1 {include file="../foo.tpl"} and {include
-file="./foo.tpl"} will resolve relative to the template they're in.
-Relative paths are available with {include file="..."} and
-{extends file="..."}. As $smarty->fetch('../foo.tpl') and
-$smarty->fetch('./foo.tpl') cannot be relative to a template, an
-exception is thrown.
-
- Addressing a specific $template_dir
-
-Smarty 3.1 introduces the $template_dir index notation.
-$smarty->fetch('[foo]bar.tpl') and {include file="[foo]bar.tpl"}
-require the template bar.tpl to be loaded from $template_dir['foo'];
-Smarty::setTemplateDir() and Smarty::addTemplateDir() offer ways to
-define indexes along with the actual directories.
-
- Mixing Resources in extends-Resource
-
-Taking the php extends: template resource one step further, it is now
-possible to mix resources within an extends: call like
-$smarty->fetch("extends:file:foo.tpl|db:bar.tpl");
-
-To make eval: and string: resources available to the inheritance
-chain, eval:base64:TPL_STRING and eval:urlencode:TPL_STRING have been
-introduced. Supplying the base64 or urlencode flags will trigger
-decoding the TPL_STRING in with either base64_decode() or urldecode().
-
- extends-Resource in template inheritance
-
-Template based inheritance may now inherit from php's extends:
-resource like {extends file="extends:foo.tpl|db:bar.tpl"}.
-
- New Smarty property escape_html
-
-$smarty->escape_html = true will autoescape all template variable
-output by calling htmlspecialchars({$output}, ENT_QUOTES,
-SMARTY_RESOURCE_CHAR_SET).
-NOTE:
-This is a compile time option. If you change the setting you must make
-sure that the templates get recompiled.
-
- New option at Smarty property compile_check
-
-The automatic recompilation of modified templates can now be
-controlled by the following settings:
-$smarty->compile_check = COMPILECHECK_OFF (false) - template files
-will not be checked
-$smarty->compile_check = COMPILECHECK_ON (true) - template files will
-always be checked
-$smarty->compile_check = COMPILECHECK_CACHEMISS - template files will
-be checked if caching is enabled and there is no existing cache file
-or it has expired
-
- Automatic recompilation on Smarty version change
-
-Templates will now be automatically recompiled on Smarty version
-changes to avoide incompatibillities in the compiled code. Compiled
-template checked against the current setting of the SMARTY_VERSION
-constant.
-
- default_config_handler_func()
-
-Analogous to the default_template_handler_func()
-default_config_handler_func() has been introduced.
-
- default_plugin_handler_func()
-
-An optional default_plugin_handler_func() can be defined which gets called
-by the compiler on tags which can't be resolved internally or by plugins.
-The default_plugin_handler() can map tags to plugins on the fly.
-
-New getters/setters
-
-The following setters/getters will be part of the official
-documentation, and will be strongly recommended. Direct property
-access will still work for the foreseeable future... it will be
-transparently routed through the setters/getters, and consequently a
-bit slower.
-
-array|string getTemplateDir( [string $index] )
-replaces $smarty->template_dir; and $smarty->template_dir[$index];
-Smarty setTemplateDir( array|string $path )
-replaces $smarty->template_dir = "foo"; and $smarty->template_dir =
-array("foo", "bar");
-Smarty addTemplateDir( array|string $path, [string $index])
-replaces $smarty->template_dir[] = "bar"; and
-$smarty->template_dir[$index] = "bar";
-
-array|string getConfigDir( [string $index] )
-replaces $smarty->config_dir; and $smarty->config_dir[$index];
-Smarty setConfigDir( array|string $path )
-replaces $smarty->config_dir = "foo"; and $smarty->config_dir =
-array("foo", "bar");
-Smarty addConfigDir( array|string $path, [string $index])
-replaces $smarty->config_dir[] = "bar"; and
-$smarty->config_dir[$index] = "bar";
-
-array getPluginsDir()
-replaces $smarty->plugins_dir;
-Smarty setPluginsDir( array|string $path )
-replaces $smarty->plugins_dir = "foo";
-Smarty addPluginsDir( array|string $path )
-replaces $smarty->plugins_dir[] = "bar";
-
-string getCompileDir()
-replaces $smarty->compile_dir;
-Smarty setCompileDir( string $path )
-replaces $smarty->compile_dir = "foo";
-
-string getCacheDir()
-replaces $smarty->cache_dir;
-Smarty setCacheDir( string $path )
-replaces $smarty->cache_dir;
diff --git a/library/Smarty/change_log.txt b/library/Smarty/change_log.txt
index a0161659d..2bcdfd024 100644
--- a/library/Smarty/change_log.txt
+++ b/library/Smarty/change_log.txt
@@ -1,8 +1,407 @@
- ===== 3.1.22-dev ===== (xx.xx.2014)
+ ===== 3.1.28-dev===== (xx.xx.2015)
+ 05.12.2015
+ -bugfix {strip} should insert a single space https://github.com/smarty-php/smarty/issues/111
+
+ 25.11.2015
+ -bugfix a left delimter like '[%' did fail on [%$var_[%$variable%]%] (forum topic 25798)
+
+ 02.11.2015
+ - bugfix {include} with variable file name like {include file="foo_`$bar`.tpl"} did fail in 3.1.28-dev https://github.com/smarty-php/smarty/issues/102
+
+ 01.11.2015
+ - update config file processing
+
+ 31.10.2015
+ - bugfix add missing $trusted_dir property to SmartyBC class (forum topic 25751)
+
+ 29.10.2015
+ - improve template scope handling
+
+ 24.10.2015
+ - more optimizations of template processing
+ - bugfix Error when using {include} within {capture} https://github.com/smarty-php/smarty/issues/100
+
+ 21.10.2015
+ - move some code into runtime extensions
+
+ 18.10.2015
+ - optimize filepath normalization
+ - rework of template inheritance
+ - speed and size optimizations
+ - bugfix under HHVM temporary cache file must only be created when caches template was updated
+ - fix compiled code for new {block} assign attribute
+ - update code generated by template function call handler
+
+ 18.09.2015
+ - bugfix {if $foo instanceof $bar} failed to compile if 2nd value is a variable https://github.com/smarty-php/smarty/issues/92
+
+ 17.09.2015
+ - bugfix {foreach} first attribute was not correctly reset since commit 05a8fa2 of 02.08.2015 https://github.com/smarty-php/smarty/issues/90
+
+ 16.09.2015
+ - update compiler by moving no longer needed properties, code optimizations and other
+
+ 14.09.2015
+ - optimize autoloader
+ - optimize subtemplate handling
+ - update template inheritance processing
+ - move code of {call} processing back into Smarty_Internal_Template class
+ - improvement invalidate OPCACHE for cleared compiled and cached template files (forum topic 25557)
+ - bugfix unintended multiple debug windows (forum topic 25699)
+
+ 30.08.2015
+ - size optimization move some runtime functions into extension
+ - optimize inline template processing
+ - optimization merge inheritance child and parent templates into one compiled template file
+
+ 29.08.2015
+ - improvement convert template inheritance into runtime processing
+ - bugfix {$smarty.block.parent} did always reference the root parent block https://github.com/smarty-php/smarty/issues/68
+
+ 23.08.2015
+ - introduce Smarty::$resource_cache_mode and cache template object of {include} inside loop
+ - load seldom used Smarty API methods dynamically to reduce memory footprint
+ - cache template object of {include} if same template is included several times
+ - convert debug console processing to object
+ - use output buffers for better performance and less memory usage
+ - optimize nocache hash processing
+ - remove not really needed properties
+ - optimize rendering
+ - move caching to Smarty::_cache
+ - remove properties with redundant content
+ - optimize Smarty::templateExists()
+ - optimize use_include_path processing
+ - relocate properties for size optimization
+ - remove redundant code
+ - bugfix compiling super globals like {$smarty.get.foo} did fail in the master branch https://github.com/smarty-php/smarty/issues/77
+
+ 06.08.2015
+ - avoid possible circular object references caused by parser/lexer objects
+ - rewrite compileAll... utility methods
+ - commit several internal improvements
+ - bugfix Smarty failed when compile_id did contain "|"
+
+ 03.08.2015
+ - rework clear cache methods
+ - bugfix compileAllConfig() was broken since 3.1.22 because of the changes in config file processing
+ - improve getIncludePath() to return directory if no file was given
+
+ 02.08.2015
+ - optimization and code cleanup of {foreach} and {section} compiler
+ - rework {capture} compiler
+
+ 01.08.2015
+ - update DateTime object can be instance of DateTimeImmutable since PHP5.5 https://github.com/smarty-php/smarty/pull/75
+ - improvement show resource type and start of template source instead of uid on eval: and string: resource (forum topic 25630)
+
+ 31.07.2015
+ - optimize {foreach} and {section} compiler
+
+ 29.07.2015
+ - optimize {section} compiler for speed and size of compiled code
+
+ 28.07.2015
+ - update for PHP 7 compatibility
+
+ 26.07.2015
+ - improvement impement workaround for HHVM PHP incompatibillity https://github.com/facebook/hhvm/issues/4797
+
+ 25.07.2015
+ - bugfix parser did hang on text starting fetch('foo.tpl') https://github.com/smarty-php/smarty/issues/70
+ - improvement Added $limit parameter to regex_replace modifier #71
+ - new feature multiple indices on file: resource
+
+ 06.07.2015
+ - optimize {block} compilation
+ - optimization get rid of __get and __set in source object
+
+ 01.07.2015
+ - optimize compile check handling
+ - update {foreach} compiler
+ - bugfix debugging console did not display string values containing \n, \r or \t correctly https://github.com/smarty-php/smarty/issues/66
+ - optimize source resources
+
+ 28.06.2015
+ - move $smarty->enableSecurity() into Smarty_Security class
+ - optimize security isTrustedResourceDir()
+ - move auto load filter methods into extension
+ - move $smarty->getTemplateVars() into extension
+ - move getStreamVariable() into extension
+ - move $smarty->append() and $smarty->appendByRef() into extension
+ - optimize autoloader
+ - optimize file path normalization
+ - bugfix PATH_SEPARATOR was replaced by mistake in autoloader
+ - remove redundant code
+
+ 27.06.2015
+ - bugfix resolve naming conflict between custom Smarty delimiter '<%' and PHP ASP tags https://github.com/smarty-php/smarty/issues/64
+ - update $smarty->_realpath for relative path not starting with './'
+ - update Smarty security with new realpath handling
+ - update {include_php} with new realpath handling
+ - move $smarty->loadPlugin() into extension
+ - minor compiler optimizations
+ - bugfix allow function plugins with name ending with 'close' https://github.com/smarty-php/smarty/issues/52
+ - rework of $smarty->clearCompiledTemplate() and move it to its own extension
+
+ 19.06.2015
+ - improvement allow closures as callback at $smarty->registerFilter() https://github.com/smarty-php/smarty/issues/59
+
+ ===== 3.1.27===== (18.06.2015)
+ 18.06.2015
+ - bugfix another update on file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56
+
+ ===== 3.1.26===== (18.06.2015)
+ 18.06.2015
+ - bugfix file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56
+
+ 17.06.2015
+ - bugfix calling a plugin with nocache option but no other attributes like {foo nocache} caused call to undefined function https://github.com/smarty-php/smarty/issues/55
+
+ ===== 3.1.25===== (15.06.2015)
+ 15.06.2015
+ - optimization of smarty_cachereource_keyvaluestore.php code
+
+ 14.06.2015
+ - bugfix a relative sub template path could fail if template_dir path did contain /../ https://github.com/smarty-php/smarty/issues/50
+ - optimization rework of path normalization
+ - bugfix an output tag with variable, modifier followed by an operator like {$foo|modifier+1} did fail https://github.com/smarty-php/smarty/issues/53
+
+ 13.06.2015
+ - bugfix a custom cache resource using smarty_cachereource_keyvaluestore.php did fail if php.ini mbstring.func_overload = 2 (forum topic 25568)
+
+ 11.06.2015
+ - bugfix the lexer could hang on very large quoted strings (forum topic 25570)
+
+ 08.06.2015
+ - bugfix using {$foo} as array index like $bar.{$foo} or in double quoted string like "some {$foo} thing" failed https://github.com/smarty-php/smarty/issues/49
+
+ 04.06.2015
+ - bugfix possible error message on unset() while compiling {block} tags https://github.com/smarty-php/smarty/issues/46
+
+ 01.06.2015
+ - bugfix including template variables broken since 3.1.22 https://github.com/smarty-php/smarty/issues/47
+
+ 27.05.2015
+ - bugfix {include} with variable file name must not create by default individual cache file (since 3.1.22) https://github.com/smarty-php/smarty/issues/43
+
+ 24.05.2015
+ - bugfix if condition string 'neq' broken due to a typo https://github.com/smarty-php/smarty/issues/42
+
+ ===== 3.1.24===== (23.05.2015)
+ 23.05.2015
+ - improvement on php_handling to allow very large PHP sections, better error handling
+ - improvement allow extreme large comment sections (forum 25538)
+
+ 21.05.2015
+ - bugfix broken PHP 5.2 compatibility when compiling 1 did compile into wrong code https://github.com/smarty-php/smarty/issues/41
+
+ 19.05.2015
+ - bugfix compiler did overwrite existing variable value when setting the nocache attribute https://github.com/smarty-php/smarty/issues/39
+ - bugfix output filter trimwhitespace could run into the pcre.backtrack_limit on large output (code.google issue 220)
+ - bugfix compiler could run into the pcre.backtrack_limit on larger comment or {php} tag sections (forum 25538)
+
+ 18.05.2015
+ - improvement introduce shortcuts in lexer/parser rules for most frequent terms for higher
+ compilation speed
+
+ 16.05.2015
+ - bugfix {php}{/php} did work just for single lines https://github.com/smarty-php/smarty/issues/33
+ - improvement remove not needed ?> handling from parser to new compiler module
+
+ 05.05.2015
+ - bugfix code could be messed up when {tags} are used in multiple attributes https://github.com/smarty-php/smarty/issues/23
+
+ 04.05.2015
+ - bugfix Smarty_Resource::parseResourceName incompatible with Google AppEngine (https://github.com/smarty-php/smarty/issues/22)
+ - improvement use is_file() checks to avoid errors suppressed by @ which could still cause problems (https://github.com/smarty-php/smarty/issues/24)
+
+ 28.04.2015
+ - bugfix plugins of merged subtemplates not loaded in 3.1.22-dev (forum topic 25508) 2nd fix
+
+ 28.04.2015
+ - bugfix plugins of merged subtemplates not loaded in 3.1.22-dev (forum topic 25508)
+
+ 23.04.2015
+ - bugfix a nocache template variable used as parameter at {insert} was by mistake cached
+
+ 20.04.2015
+ - bugfix at a template function containing nocache code a parmeter could overwrite a template variable of same name
+
+ 27.03.2015
+ - bugfix Smarty_Security->allow_constants=false; did also disable true, false and null (change of 16.03.2015)
+ - improvement added a whitelist for trusted constants to security Smarty_Security::$trusted_constants (forum topic 25471)
+
+ 20.03.2015
+ - bugfix make sure that function properties get saved only in compiled files containing the fuction definition {forum topic 25452}
+ - bugfix correct update of global variable values on exit of template functions. (reported under Smarty Developers)
+
+ 16.03.2015
+ - bugfix problems with {function}{/function} and {call} tags in different subtemplate cache files {forum topic 25452}
+ - bugfix Smarty_Security->allow_constants=false; did not disallow direct usage of defined constants like {SMARTY_DIR} {forum topic 25457}
+ - bugfix {block}{/block} tags did not work inside double quoted strings https://github.com/smarty-php/smarty/issues/18
+
+
+ 15.03.2015
+ - bugfix $smarty->compile_check must be restored before rendering of a just updated cache file {forum 25452}
+
+ 14.03.2015
+ - bugfix {nocache} {/nocache} tags corrupted code when used within a nocache section caused by a nocache template variable.
+
+ - bugfix template functions defined with {function} in an included subtemplate could not be called in nocache
+ mode with {call... nocache} if the subtemplate had it's own cache file {forum 25452}
+
+ 10.03.2015
+ - bugfix {include ... nocache} whith variable file or compile_id attribute was not executed in nocache mode.
+
+ 12.02.2015
+ - bugfix multiple Smarty::fetch() of same template when $smarty->merge_compiled_includes = true; could cause function already defined error
+
+ 11.02.2015
+ - bugfix recursive {includes} did create E_NOTICE message when $smarty->merge_compiled_includes = true; (github issue #16)
+
+ 22.01.2015
+ - new feature security can now control access to static methods and properties
+ see also NEW_FEATURES.txt
+
+ 21.01.2015
+ - bugfix clearCompiledTemplates(), clearAll() and clear() could try to delete whole drive at wrong path permissions because realpath() fail (forum 25397)
+ - bugfix 'self::' and 'parent::' was interpreted in template syntax as static class
+
+ 04.01.2015
+ - push last weeks changes to github
+
+ - different optimizations
+ - improvement automatically create different versions of compiled templates and config files depending
+ on property settings.
+ - optimization restructure template processing by moving code into classes it better belongs to
+ - optimization restructure config file processing
+
+ 31.12.2014
+ - bugfix use function_exists('mb_get_info') for setting Smarty::$_MBSTRING.
+ Function mb_split could be overloaded depending on php.ini mbstring.func_overload
+
+
+ 29.12.2014
+ - new feature security can now limit the template nesting level by property $max_template_nesting
+ see also NEW_FEATURES.txt (forum 25370)
+
+ 29.12.2014
+ - new feature security can now disable special $smarty variables listed in property $disabled_special_smarty_vars
+ see also NEW_FEATURES.txt (forum 25370)
+
+ 27.12.2014
+ - bugfix clear internal _is_file_cache when plugins_dir was modified
+
+ 13.12.2014
+ - improvement optimization of lexer and parser resulting in a up to 30% higher compiling speed
+
+ 11.12.2014
+ - bugfix resolve parser ambiguity between constant print tag {CONST} and other smarty tags after change of 09.12.2014
+
+ 09.12.2014
+ - bugfix variables $null, $true and $false did not work after the change of 12.11.2014 (forum 25342)
+ - bugfix call of template function by a variable name did not work after latest changes (forum 25342)
+
+ 23.11.2014
+ - bugfix a plugin with attached modifier could fail if the tag was immediately followed by another Smarty tag (since 3.1.21) (forum 25326)
+
+ 13.11.2014
+ - improvement move autoload code into Autoloader.php. Use Composer autoloader when possible
+
+ 12.11.2014
+ - new feature added support of namespaces to template code
+
+ 08.11.2014 - 10.11.2014
+ - bugfix subtemplate called in nocache mode could be called with wrong compile_id when it did change on one of the calling templates
+ - improvement add code of template functions called in nocache mode dynamically to cache file (related to bugfix of 01.11.2014)
+ - bugfix Debug Console did not include all data from merged compiled subtemplates
+
+ 04.11.2014
+ - new feature $smarty->debugging = true; => overwrite existing Debug Console window (old behaviour)
+ $smarty->debugging = 2; => individual Debug Console window by template name
+
+ 03.11.2014
+ - bugfix Debug Console did not show included subtemplates since 3.1.17 (forum 25301)
+ - bugfix Modifier debug_print_var did not limit recursion or prevent recursive object display at Debug Console
+ (ATTENTION: parameter order has changed to be able to specify maximum recursion)
+ - bugfix Debug consol did not include subtemplate information with $smarty->merge_compiled_includes = true
+ - improvement The template variables are no longer displayed as objects on the Debug Console
+ - improvement $smarty->createData($parent = null, $name = null) new optional name parameter for display at Debug Console
+ - addition of some hooks for future extension of Debug Console
+
+ 01.11.2014
+ - bugfix and enhancement on subtemplate {include} and template {function} tags.
+ * Calling a template which has a nocache section could fail if it was called from a cached and a not cached subtemplate.
+ * Calling the same subtemplate cached and not cached with the $smarty->merge_compiled_includes enabled could cause problems
+ * Many smaller related changes
+
+ 30.10.2014
+ - bugfix access to class constant by object like {$object::CONST} or variable class name {$class::CONST} did not work (forum 25301)
+
+ 26.10.2014
+ - bugfix E_NOTICE message was created during compilation when ASP tags '<%' or '%>' are in template source text
+ - bugfix merge_compiled_includes option failed when caching enables and same subtemplate was included cached and not cached
+
===== 3.1.21 ===== (18.10.2014)
18.10.2014
- - composer moved to github
- - add COMPOSER_RELEASE_NOTES
+ - composer moved to github
17.10.2014
- bugfix on $php_handling security and optimization of smarty_internal_parsetree (Thue Kristensen)
@@ -43,7 +442,7 @@
04.07.2014
- bugfix the bufix of 02.06.2014 broke correct handling of child templates with same name but different template folders in extends resource (issue 194 and topic 25099)
- ===== 3.1.19 ===== (06.30.2014)
+ ===== 3.1.19 ===== (30.06.2014)
20.06.2014
- bugfix template variables could not be passed as parameter in {include} when the include was in a {nocache} section (topic 25131)
@@ -732,7 +1131,7 @@
15/07/2011
- bugfix individual cache_lifetime of {include} did not work correctly inside {block} tags
-- added caches for Smarty_Template_Source and Smarty_Template_Compiled to reduce I/O for multiple cache_id rendering
+- added caches for Smarty_Internal_TemplateSource and Smarty_Internal_TemplateCompiled to reduce I/O for multiple cache_id rendering
14/07/2011
- made Smarty::loadPlugin() respect the include_path if required
diff --git a/library/Smarty/demo/configs/test.conf b/library/Smarty/demo/configs/test.conf
deleted file mode 100644
index 5eac748ec..000000000
--- a/library/Smarty/demo/configs/test.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-title = Welcome to Smarty!
-cutoff_size = 40
-
-[setup]
-bold = true
diff --git a/library/Smarty/demo/index.php b/library/Smarty/demo/index.php
deleted file mode 100644
index 33f3035c5..000000000
--- a/library/Smarty/demo/index.php
+++ /dev/null
@@ -1,30 +0,0 @@
-force_compile = true;
-$smarty->debugging = true;
-$smarty->caching = true;
-$smarty->cache_lifetime = 120;
-
-$smarty->assign("Name", "Fred Irving Johnathan Bradley Peppergill", true);
-$smarty->assign("FirstName", array("John", "Mary", "James", "Henry"));
-$smarty->assign("LastName", array("Doe", "Smith", "Johnson", "Case"));
-$smarty->assign("Class", array(array("A", "B", "C", "D"), array("E", "F", "G", "H"),
- array("I", "J", "K", "L"), array("M", "N", "O", "P")));
-
-$smarty->assign("contacts", array(array("phone" => "1", "fax" => "2", "cell" => "3"),
- array("phone" => "555-4444", "fax" => "555-3333", "cell" => "760-1234")));
-
-$smarty->assign("option_values", array("NY", "NE", "KS", "IA", "OK", "TX"));
-$smarty->assign("option_output", array("New York", "Nebraska", "Kansas", "Iowa", "Oklahoma", "Texas"));
-$smarty->assign("option_selected", "NE");
-
-$smarty->display('index.tpl');
diff --git a/library/Smarty/demo/plugins/cacheresource.apc.php b/library/Smarty/demo/plugins/cacheresource.apc.php
deleted file mode 100644
index d7336f2bf..000000000
--- a/library/Smarty/demo/plugins/cacheresource.apc.php
+++ /dev/null
@@ -1,83 +0,0 @@
- $v) {
- $_res[$k] = $v;
- }
-
- return $_res;
- }
-
- /**
- * Save values for a set of keys to cache
- *
- * @param array $keys list of values to save
- * @param int $expire expiration time
- *
- * @return boolean true on success, false on failure
- */
- protected function write(array $keys, $expire = null)
- {
- foreach ($keys as $k => $v) {
- apc_store($k, $v, $expire);
- }
-
- return true;
- }
-
- /**
- * Remove values from cache
- *
- * @param array $keys list of keys to delete
- *
- * @return boolean true on success, false on failure
- */
- protected function delete(array $keys)
- {
- foreach ($keys as $k) {
- apc_delete($k);
- }
-
- return true;
- }
-
- /**
- * Remove *all* values from cache
- *
- * @return boolean true on success, false on failure
- */
- protected function purge()
- {
- return apc_clear_cache('user');
- }
-}
diff --git a/library/Smarty/demo/plugins/cacheresource.memcache.php b/library/Smarty/demo/plugins/cacheresource.memcache.php
deleted file mode 100644
index e265365fb..000000000
--- a/library/Smarty/demo/plugins/cacheresource.memcache.php
+++ /dev/null
@@ -1,97 +0,0 @@
-memcache = new Memcache();
- $this->memcache->addServer('127.0.0.1', 11211);
- }
-
- /**
- * Read values for a set of keys from cache
- *
- * @param array $keys list of keys to fetch
- *
- * @return array list of values with the given keys used as indexes
- * @return boolean true on success, false on failure
- */
- protected function read(array $keys)
- {
- $_keys = $lookup = array();
- foreach ($keys as $k) {
- $_k = sha1($k);
- $_keys[] = $_k;
- $lookup[$_k] = $k;
- }
- $_res = array();
- $res = $this->memcache->get($_keys);
- foreach ($res as $k => $v) {
- $_res[$lookup[$k]] = $v;
- }
-
- return $_res;
- }
-
- /**
- * Save values for a set of keys to cache
- *
- * @param array $keys list of values to save
- * @param int $expire expiration time
- *
- * @return boolean true on success, false on failure
- */
- protected function write(array $keys, $expire = null)
- {
- foreach ($keys as $k => $v) {
- $k = sha1($k);
- $this->memcache->set($k, $v, 0, $expire);
- }
-
- return true;
- }
-
- /**
- * Remove values from cache
- *
- * @param array $keys list of keys to delete
- *
- * @return boolean true on success, false on failure
- */
- protected function delete(array $keys)
- {
- foreach ($keys as $k) {
- $k = sha1($k);
- $this->memcache->delete($k);
- }
-
- return true;
- }
-
- /**
- * Remove *all* values from cache
- *
- * @return boolean true on success, false on failure
- */
- protected function purge()
- {
- $this->memcache->flush();
- }
-}
diff --git a/library/Smarty/demo/plugins/cacheresource.mysql.php b/library/Smarty/demo/plugins/cacheresource.mysql.php
deleted file mode 100644
index d8d00ab26..000000000
--- a/library/Smarty/demo/plugins/cacheresource.mysql.php
+++ /dev/null
@@ -1,162 +0,0 @@
-CREATE TABLE IF NOT EXISTS `output_cache` (
- * `id` CHAR(40) NOT NULL COMMENT 'sha1 hash',
- * `name` VARCHAR(250) NOT NULL,
- * `cache_id` VARCHAR(250) NULL DEFAULT NULL,
- * `compile_id` VARCHAR(250) NULL DEFAULT NULL,
- * `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
- * `content` LONGTEXT NOT NULL,
- * PRIMARY KEY (`id`),
- * INDEX(`name`),
- * INDEX(`cache_id`),
- * INDEX(`compile_id`),
- * INDEX(`modified`)
- * ) ENGINE = InnoDB;
- *
- * @package CacheResource-examples
- * @author Rodney Rehm
- */
-class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom
-{
- // PDO instance
- protected $db;
- protected $fetch;
- protected $fetchTimestamp;
- protected $save;
-
- public function __construct()
- {
- try {
- $this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
- }
- catch (PDOException $e) {
- throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
- }
- $this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
- $this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
- $this->save = $this->db->prepare('REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
- VALUES (:id, :name, :cache_id, :compile_id, :content)');
- }
-
- /**
- * fetch cached content and its modification time from data source
- *
- * @param string $id unique cache content identifier
- * @param string $name template name
- * @param string $cache_id cache id
- * @param string $compile_id compile id
- * @param string $content cached content
- * @param integer $mtime cache modification timestamp (epoch)
- *
- * @return void
- */
- protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
- {
- $this->fetch->execute(array('id' => $id));
- $row = $this->fetch->fetch();
- $this->fetch->closeCursor();
- if ($row) {
- $content = $row['content'];
- $mtime = strtotime($row['modified']);
- } else {
- $content = null;
- $mtime = null;
- }
- }
-
- /**
- * Fetch cached content's modification timestamp from data source
- *
- * @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the complete cached content.
- *
- * @param string $id unique cache content identifier
- * @param string $name template name
- * @param string $cache_id cache id
- * @param string $compile_id compile id
- *
- * @return integer|boolean timestamp (epoch) the template was modified, or false if not found
- */
- protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
- {
- $this->fetchTimestamp->execute(array('id' => $id));
- $mtime = strtotime($this->fetchTimestamp->fetchColumn());
- $this->fetchTimestamp->closeCursor();
-
- return $mtime;
- }
-
- /**
- * Save content to cache
- *
- * @param string $id unique cache content identifier
- * @param string $name template name
- * @param string $cache_id cache id
- * @param string $compile_id compile id
- * @param integer|null $exp_time seconds till expiration time in seconds or null
- * @param string $content content to cache
- *
- * @return boolean success
- */
- protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
- {
- $this->save->execute(array(
- 'id' => $id,
- 'name' => $name,
- 'cache_id' => $cache_id,
- 'compile_id' => $compile_id,
- 'content' => $content,
- ));
-
- return !!$this->save->rowCount();
- }
-
- /**
- * Delete content from cache
- *
- * @param string $name template name
- * @param string $cache_id cache id
- * @param string $compile_id compile id
- * @param integer|null $exp_time seconds till expiration or null
- *
- * @return integer number of deleted caches
- */
- protected function delete($name, $cache_id, $compile_id, $exp_time)
- {
- // delete the whole cache
- if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
- // returning the number of deleted caches would require a second query to count them
- $query = $this->db->query('TRUNCATE TABLE output_cache');
-
- return - 1;
- }
- // build the filter
- $where = array();
- // equal test name
- if ($name !== null) {
- $where[] = 'name = ' . $this->db->quote($name);
- }
- // equal test compile_id
- if ($compile_id !== null) {
- $where[] = 'compile_id = ' . $this->db->quote($compile_id);
- }
- // range test expiration time
- if ($exp_time !== null) {
- $where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
- }
- // equal test cache_id and match sub-groups
- if ($cache_id !== null) {
- $where[] = '(cache_id = ' . $this->db->quote($cache_id)
- . ' OR cache_id LIKE ' . $this->db->quote($cache_id . '|%') . ')';
- }
- // run delete query
- $query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
-
- return $query->rowCount();
- }
-}
diff --git a/library/Smarty/demo/plugins/resource.extendsall.php b/library/Smarty/demo/plugins/resource.extendsall.php
deleted file mode 100644
index 500b3c862..000000000
--- a/library/Smarty/demo/plugins/resource.extendsall.php
+++ /dev/null
@@ -1,60 +0,0 @@
-smarty->getTemplateDir() as $key => $directory) {
- try {
- $s = Smarty_Resource::source(null, $source->smarty, '[' . $key . ']' . $source->name);
- if (!$s->exists) {
- continue;
- }
- $sources[$s->uid] = $s;
- $uid .= $s->filepath;
- }
- catch (SmartyException $e) {
- }
- }
-
- if (!$sources) {
- $source->exists = false;
- $source->template = $_template;
-
- return;
- }
-
- $sources = array_reverse($sources, true);
- reset($sources);
- $s = current($sources);
-
- $source->components = $sources;
- $source->filepath = $s->filepath;
- $source->uid = sha1($uid);
- $source->exists = $exists;
- if ($_template && $_template->smarty->compile_check) {
- $source->timestamp = $s->timestamp;
- }
- // need the template at getContent()
- $source->template = $_template;
- }
-}
diff --git a/library/Smarty/demo/plugins/resource.mysql.php b/library/Smarty/demo/plugins/resource.mysql.php
deleted file mode 100644
index dfc9606b4..000000000
--- a/library/Smarty/demo/plugins/resource.mysql.php
+++ /dev/null
@@ -1,81 +0,0 @@
-CREATE TABLE IF NOT EXISTS `templates` (
- * `name` varchar(100) NOT NULL,
- * `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- * `source` text,
- * PRIMARY KEY (`name`)
- * ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- * Demo data:
- *