aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/bookmarks.apd2
-rw-r--r--app/chat.apd2
-rw-r--r--app/probe.apd2
-rw-r--r--app/suggest.apd2
-rw-r--r--app/webpages.apd2
-rw-r--r--doc/bbcode.html8
-rw-r--r--doc/hidden_configs.bb41
-rw-r--r--include/Contact.php30
-rw-r--r--include/api.php26
-rw-r--r--include/apps.php113
-rw-r--r--include/bb2diaspora.php24
-rw-r--r--library/ical.php379
-rw-r--r--mod/apps.php1
-rw-r--r--mod/photos.php3
-rw-r--r--version.inc2
-rw-r--r--view/theme/redbasic/css/style.css9
-rw-r--r--view/tpl/app.tpl2
-rwxr-xr-xview/tpl/apps.tpl11
18 files changed, 528 insertions, 131 deletions
diff --git a/app/bookmarks.apd b/app/bookmarks.apd
index f126a35c5..6c3d718a8 100644
--- a/app/bookmarks.apd
+++ b/app/bookmarks.apd
@@ -1,4 +1,4 @@
url: $baseurl/bookmarks
requires: local_user
-name: Bookmarks
+name: View bookmarks
photo: $baseurl/app/bookmarks.png
diff --git a/app/chat.apd b/app/chat.apd
index 2eba8edba..249608f57 100644
--- a/app/chat.apd
+++ b/app/chat.apd
@@ -1,4 +1,4 @@
url: $baseurl/chat/$nick
requires: local_user
-name: Chat
+name: My chatrooms
photo: $baseurl/app/chat.png
diff --git a/app/probe.apd b/app/probe.apd
index c96399391..e2d2428a0 100644
--- a/app/probe.apd
+++ b/app/probe.apd
@@ -1,4 +1,4 @@
url: $baseurl/probe
requires: local_user
-name: Probe
+name: Remote diagnostics
photo: $baseurl/app/probe.png
diff --git a/app/suggest.apd b/app/suggest.apd
index ff82a73d3..f4ca79410 100644
--- a/app/suggest.apd
+++ b/app/suggest.apd
@@ -1,4 +1,4 @@
url: $baseurl/suggest
requires: local_user
-name: Suggest
+name: Suggest channels
photo: $baseurl/app/suggest.png
diff --git a/app/webpages.apd b/app/webpages.apd
index 4241dbb8e..7c7528d6b 100644
--- a/app/webpages.apd
+++ b/app/webpages.apd
@@ -1,4 +1,4 @@
url: $baseurl/webpages/$nick
-requires: local_user
+requires: local_user, webpages
name: Webpages
photo: $baseurl/app/webpages.png
diff --git a/doc/bbcode.html b/doc/bbcode.html
index 0f070eaa2..fac768879 100644
--- a/doc/bbcode.html
+++ b/doc/bbcode.html
@@ -66,6 +66,14 @@
<li>[rpost=title]Text to post[/rpost] The observer will be returned to their home hub to enter a post with the specified title and body. Both are optional <br />
<li>[qr]text to post[/qr] - create a QR code.<br />
<br />
+</ul>
+
+<p>These require a suitable map plugin/addon such as openstreetmap or else the result will be blank</p>
+<ul>
+<li>[map] Generate an inline map using the current browser coordinates of the poster, if browser location is enabled<br />
+<li>[map=latitude,longitude] Generate a map using global coordinates.<br />
+<li>[map]Place Name[/map] Generate a map for a given named location. The first matching location is returned. For instance "Sydney" will usually return Sydney, Australia and not Sydney, Nova Scotia, Canada unless the more precise location is specified. It is highly recommended to use the post preview utility to ensure you have the correct location before submitting the post.<br />
+</ul>
#include doc/macros/main_footer.bb;
</div>
diff --git a/doc/hidden_configs.bb b/doc/hidden_configs.bb
index 727428176..bf9705920 100644
--- a/doc/hidden_configs.bb
+++ b/doc/hidden_configs.bb
@@ -106,24 +106,29 @@ This document assumes you're an administrator.
list of names (no spaces)
[b]system > auto_follow[/b]
Make the first channel of an account auto-follow channels listed here - comma separated list of webbies (member@hub addresses).
- [b]system > admin_email[/b]
- Specifies the administrators email for this site. This is initially set during install.
- [b]system > cron_hour[/b]
- Specify an hour in which to run cron_daily. By default with no config, this will run at midnight UTC.
- [b]system > minimum_feedcheck_minutes[/b]
- The minimum interval between polling RSS feeds. If this is lower than the cron interval, feeds will be polled with each cronjob
- [b]system > blacklisted_sites[/b]
- An array of specific hubs to block from this hub completely.
- [b]system > ignore_imagick[/b]
- Ignore imagick and use GD, even if imagick is installed on the server. Prevents some issues with PNG files in older versions of imagick.
- [b]system > no_age_restriction[/b]
- Do not restric registration to people over the age of 13
- [b]system > override_poll_lockfile[/b]
- Ignore the lock file in the poller process to allow more than one process to run at a time.
- [b]system > projecthome[/b]
- Display the project page on your home page for logged out viewers.
- [b]system > sellpage[/b]
- A URL shown in the public sites list to sell your hub - display service classes, etc.
+ [b]system > admin_email[/b]
+ Specifies the administrators email for this site. This is initially set during install.
+ [b]system > cron_hour[/b]
+ Specify an hour in which to run cron_daily. By default with no config, this will run at midnight UTC.
+ [b]system > minimum_feedcheck_minutes[/b]
+ The minimum interval between polling RSS feeds. If this is lower than the cron interval, feeds will be polled with each cronjob
+ [b]system > blacklisted_sites[/b]
+ An array of specific hubs to block from this hub completely.
+ [b]system > ignore_imagick[/b]
+ Ignore imagick and use GD, even if imagick is installed on the server. Prevents some issues with PNG files in older versions of imagick.
+ [b]system > no_age_restriction[/b]
+ Do not restric registration to people over the age of 13
+ [b]system > override_poll_lockfile[/b]
+ Ignore the lock file in the poller process to allow more than one process to run at a time.
+ [b]system > projecthome[/b]
+ Display the project page on your home page for logged out viewers.
+ [b]system > sellpage[/b]
+ A URL shown in the public sites list to sell your hub - display service classes, etc.
+ [b]randprofile > check[/b]
+ When requesting a random profile, check that it actually exists first
+ [b]randprofile > retry[/b]
+ Number of times to retry getting a random profile
+
#include doc/macros/main_footer.bb;
diff --git a/include/Contact.php b/include/Contact.php
index 4fd43db44..233798181 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -581,12 +581,30 @@ function contact_remove($channel_id, $abook_id) {
function random_profile() {
$randfunc = db_getfunc('rand');
- $r = q("select xchan_url from xchan left join hubloc on hubloc_hash = xchan_hash where hubloc_connected > %s - interval %s order by $randfunc limit 1",
- db_utcnow(), db_quoteinterval('30 day')
- );
- if($r)
- return $r[0]['xchan_url'];
+
+ $checkrandom = get_config('randprofile','check'); // False by default
+ $retryrandom = intval(get_config('randprofile','retry'));
+ if($retryrandom === false) $retryrandom = 5;
+
+ for($i = 0; $i < $retryrandom; $i++) {
+ $r = q("select xchan_url from xchan left join hubloc on hubloc_hash = xchan_hash where hubloc_connected > %s - interval %s order by $randfunc limit 1",
+ db_utcnow(), db_quoteinterval('30 day')
+ );
+
+ if(!$r) return ''; // Couldn't get a random channel
+
+ if($checkrandom) {
+ $x = z_fetch_url($r[0]['xchan_url']);
+ if($x['success'])
+ return $r[0]['xchan_url'];
+ else
+ logger('Random channel turned out to be bad.');
+ }
+ else {
+ return $r[0]['xchan_url'];
+ }
+
+ }
return '';
}
-
diff --git a/include/api.php b/include/api.php
index aeee95d3b..51de412cf 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1868,11 +1868,14 @@ require_once('include/items.php');
require_once("include/message.php");
- $r = q("SELECT `id` FROM `contact` WHERE `uid`=%d AND `nick`='%s'",
+ // in a decentralised world the screen name is ambiguous
+
+ $r = q("SELECT `abook_id` FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel`=%d and xchan_addr like '%s'",
intval(api_user()),
- dbesc($_POST['screen_name']));
+ dbesc($_POST['screen_name'] . '@%')
+ );
- $recipient = api_get_user($a, $r[0]['id']);
+ $recipient = api_get_user($a, $r[0]['abook_id']);
$replyto = '';
$sub = '';
if (x($_REQUEST,'replyto')) {
@@ -1925,10 +1928,11 @@ require_once('include/items.php');
if ($page<0) $page=0;
$start = $page*$count;
-
- $profile_url = $a->get_baseurl() . '/channel/' . $a->user['nickname'];
+ $channel = $a->get_channel();
+
+ $profile_url = $a->get_baseurl() . '/channel/' . $channel['channel_address'];
if ($box=="sentbox") {
- $sql_extra = "`from-url`='".dbesc( $profile_url )."'";
+ $sql_extra = "`from_xchan`='".dbesc( $channel['channel_hash'] )."'";
}
elseif ($box=="conversation") {
$sql_extra = "`parent_mid`='".dbesc( $_GET["uri"] ) ."'";
@@ -1937,10 +1941,10 @@ require_once('include/items.php');
$sql_extra = "true";
}
elseif ($box=="inbox") {
- $sql_extra = "`from-url`!='".dbesc( $profile_url )."'";
+ $sql_extra = "`from_xchan`!='".dbesc( $channel['channel_hash'] )."'";
}
- $r = q("SELECT * FROM `mail` WHERE uid=%d AND $sql_extra ORDER BY created DESC LIMIT %d OFFSET %d",
+ $r = q("SELECT * FROM `mail` WHERE channel_id = %d AND $sql_extra ORDER BY created DESC LIMIT %d OFFSET %d",
intval(api_user()),
intval($count), intval($start)
);
@@ -1950,10 +1954,12 @@ require_once('include/items.php');
foreach($r as $item) {
if ($box == "inbox" || $item['from-url'] != $profile_url){
$recipient = $user_info;
- $sender = api_get_user($a,$item['contact-id']);
+ // fixme to lookup recipient
+ $sender = api_get_user($a);
}
elseif ($box == "sentbox" || $item['from-url'] != $profile_url){
- $recipient = api_get_user($a,$item['contact-id']);
+ // fixme to lookup recipient
+ $recipient = api_get_user($a);
$sender = $user_info;
}
diff --git a/include/apps.php b/include/apps.php
index 9c4fe826a..e08e6a6f5 100644
--- a/include/apps.php
+++ b/include/apps.php
@@ -83,35 +83,37 @@ function parse_app_description($f) {
$ret['target'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['target']);
if(array_key_exists('requires',$ret)) {
- $require = trim(strtolower($ret['requires']));
- switch($require) {
- case 'nologin':
- if(local_user())
- unset($ret);
- break;
- case 'admin':
- if(! is_site_admin())
- unset($ret);
- break;
- case 'local_user':
- if(! local_user())
- unset($ret);
- break;
- case 'public_profile':
- if(! is_public_profile())
- unset($ret);
- break;
- case 'observer':
- if(! $observer)
- unset($ret);
- break;
- default:
- if(! local_user() && feature_enabled(local_user(),$require))
- unset($ret);
- break;
+ $requires = explode(',',$ret['requires']);
+ foreach($requires as $require) {
+ $require = trim(strtolower($require));
+ switch($require) {
+ case 'nologin':
+ if(local_user())
+ unset($ret);
+ break;
+ case 'admin':
+ if(! is_site_admin())
+ unset($ret);
+ break;
+ case 'local_user':
+ if(! local_user())
+ unset($ret);
+ break;
+ case 'public_profile':
+ if(! is_public_profile())
+ unset($ret);
+ break;
+ case 'observer':
+ if(! $observer)
+ unset($ret);
+ break;
+ default:
+ if(! (local_user() && feature_enabled(local_user(),$require)))
+ unset($ret);
+ break;
+ }
}
-// logger('require: ' . print_r($ret,true));
}
if($ret) {
translate_system_apps($ret);
@@ -189,34 +191,37 @@ function app_render($papp,$mode = 'view') {
$papp['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$papp['desc']);
if($k === 'requires') {
- $require = trim(strtolower($v));
- switch($require) {
- case 'nologin':
- if(local_user())
- return '';
- break;
- case 'admin':
- if(! is_site_admin())
- return '';
- break;
- case 'local_user':
- if(! local_user())
- return '';
- break;
- case 'public_profile':
- if(! is_public_profile())
- return '';
- break;
- case 'observer':
- $observer = get_app()->get_observer();
- if(! $observer)
- return '';
- break;
- default:
- if(! local_user() && feature_enabled(local_user(),$require))
- return '';
- break;
+ $requires = explode(',',$v);
+ foreach($requires as $require) {
+ $require = trim(strtolower($require));
+ switch($require) {
+ case 'nologin':
+ if(local_user())
+ return '';
+ break;
+ case 'admin':
+ if(! is_site_admin())
+ return '';
+ break;
+ case 'local_user':
+ if(! local_user())
+ return '';
+ break;
+ case 'public_profile':
+ if(! is_public_profile())
+ return '';
+ break;
+ case 'observer':
+ $observer = get_app()->get_observer();
+ if(! $observer)
+ return '';
+ break;
+ default:
+ if(! (local_user() && feature_enabled(local_user(),$require)))
+ return '';
+ break;
+ }
}
}
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 3c4f07568..5c93ac3aa 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -116,22 +116,11 @@ function diaspora_mention_callback($matches) {
function diaspora2bb($s,$use_zrl = false) {
+ $s = str_replace("&#xD;","\r",$s);
$s = str_replace("&#xD;\n&gt;","",$s);
$s = html_entity_decode($s,ENT_COMPAT,'UTF-8');
- // Too many new lines. So deactivated the following line
- // $s = str_replace("\r","\n",$s);
- // Simply remove cr.
- $s = str_replace("\r","",$s);
-
- // <br/> is invalid. Replace it with the valid expression
- $s = str_replace("<br/>","<br />",$s);
- $s = str_replace("\n","<br />",$s);
-
-
-// $s = preg_replace('/\@\{(.+?)\; (.+?)\@(.+?)\}/','@[url=https://$3/u/$2]$1[/url]',$s);
-
// first try plustags
$s = preg_replace_callback('/\@\{(.+?)\; (.+?)\@(.+?)\}\+/','diaspora_mention_callback',$s);
@@ -143,16 +132,13 @@ function diaspora2bb($s,$use_zrl = false) {
// This seems to work
$s = preg_replace('/\#([^\s\#])/','&#35;$1',$s);
- $s = preg_replace_callback('/\[share(.*?)\]/ism','share_shield',$s);
-
$s = Markdown($s);
+ $s = str_replace("\r","",$s);
+
$s = str_replace('&#35;','#',$s);
-// we seem to have double linebreaks
-// $s = str_replace("\n",'<br />',$s);
$s = html2bbcode($s);
-// $s = str_replace('&#42;','*',$s);
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands
$s = str_replace('&#x2672;',html_entity_decode('&#x2672;',ENT_QUOTES,'UTF-8'),$s);
@@ -175,10 +161,6 @@ function diaspora2bb($s,$use_zrl = false) {
// remove duplicate adjacent code tags
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s);
-
- $s = preg_replace_callback('/\[share(.*?)\]/ism','share_unshield',$s);
-
-
// Don't show link to full picture (until it is fixed)
$s = scale_external_images($s, false);
diff --git a/library/ical.php b/library/ical.php
new file mode 100644
index 000000000..6bb26bad8
--- /dev/null
+++ b/library/ical.php
@@ -0,0 +1,379 @@
+<?php
+/**
+ * This PHP-Class should only read a iCal-File (*.ics), parse it and give an
+ * array with its content.
+ *
+ * PHP Version 5
+ *
+ * @category Parser
+ * @package Ics-parser
+ * @author Martin Thoma <info@martin-thoma.de>
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ * @version SVN: <svn_id>
+ * @link http://code.google.com/p/ics-parser/
+ * @example $ical = new ical('MyCal.ics');
+ * print_r( $ical->events() );
+ */
+
+/**
+ * This example demonstrates how the Ics-Parser should be used.
+ *
+ * PHP Version 5
+ *
+ * @category Example
+ * @package Ics-parser
+ * @author Martin Thoma <info@martin-thoma.de>
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ * @version SVN: <svn_id>
+ * @link http://code.google.com/p/ics-parser/
+ * @example $ical = new ical('MyCal.ics');
+ * print_r( $ical->get_event_array() );
+
+require 'class.iCalReader.php';
+
+$ical = new ICal('MyCal.ics');
+$events = $ical->events();
+
+$date = $events[0]['DTSTART'];
+echo "The ical date: ";
+echo $date;
+echo "<br/>";
+
+echo "The Unix timestamp: ";
+echo $ical->iCalDateToUnixTimestamp($date);
+echo "<br/>";
+
+echo "The number of events: ";
+echo $ical->event_count;
+echo "<br/>";
+
+echo "The number of todos: ";
+echo $ical->todo_count;
+echo "<br/>";
+echo "<hr/><hr/>";
+
+foreach ($events as $event) {
+ echo "SUMMARY: ".$event['SUMMARY']."<br/>";
+ echo "DTSTART: ".$event['DTSTART']." - UNIX-Time: ".$ical->iCalDateToUnixTimestamp($event['DTSTART'])."<br/>";
+ echo "DTEND: ".$event['DTEND']."<br/>";
+ echo "DTSTAMP: ".$event['DTSTAMP']."<br/>";
+ echo "UID: ".$event['UID']."<br/>";
+ echo "CREATED: ".$event['CREATED']."<br/>";
+ echo "DESCRIPTION: ".$event['DESCRIPTION']."<br/>";
+ echo "LAST-MODIFIED: ".$event['LAST-MODIFIED']."<br/>";
+ echo "LOCATION: ".$event['LOCATION']."<br/>";
+ echo "SEQUENCE: ".$event['SEQUENCE']."<br/>";
+ echo "STATUS: ".$event['STATUS']."<br/>";
+ echo "TRANSP: ".$event['TRANSP']."<br/>";
+ echo "<hr/>";
+}
+
+ (end example)
+ *
+ *
+ */
+
+// error_reporting(E_ALL);
+
+/**
+ * This is the iCal-class
+ *
+ * @category Parser
+ * @package Ics-parser
+ * @author Martin Thoma <info@martin-thoma.de>
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ * @link http://code.google.com/p/ics-parser/
+ *
+ * @param {string} filename The name of the file which should be parsed
+ * @constructor
+ */
+class ICal
+{
+ /* How many ToDos are in this ical? */
+ public /** @type {int} */ $todo_count = 0;
+
+ /* How many events are in this ical? */
+ public /** @type {int} */ $event_count = 0;
+
+ /* The parsed calendar */
+ public /** @type {Array} */ $cal;
+
+ /* Which keyword has been added to cal at last? */
+ private /** @type {string} */ $_lastKeyWord;
+
+ /**
+ * Creates the iCal-Object
+ *
+ * @param {string} $filename The path to the iCal-file
+ *
+ * @return Object The iCal-Object
+ */
+ public function __construct($filename)
+ {
+ if (!$filename) {
+ return false;
+ }
+
+ $lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+ if (stristr($lines[0], 'BEGIN:VCALENDAR') === false) {
+ return false;
+ } else {
+ // TODO: Fix multiline-description problem (see http://tools.ietf.org/html/rfc2445#section-4.8.1.5)
+ foreach ($lines as $line) {
+ $line = trim($line);
+ $add = $this->keyValueFromString($line);
+ if ($add === false) {
+ $this->addCalendarComponentWithKeyAndValue($type, false, $line);
+ continue;
+ }
+
+ list($keyword, $value) = $add;
+
+ switch ($line) {
+ // http://www.kanzaki.com/docs/ical/vtodo.html
+ case "BEGIN:VTODO":
+ $this->todo_count++;
+ $type = "VTODO";
+ break;
+
+ // http://www.kanzaki.com/docs/ical/vevent.html
+ case "BEGIN:VEVENT":
+ //echo "vevent gematcht";
+ $this->event_count++;
+ $type = "VEVENT";
+ break;
+
+ //all other special strings
+ case "BEGIN:VCALENDAR":
+ case "BEGIN:DAYLIGHT":
+ // http://www.kanzaki.com/docs/ical/vtimezone.html
+ case "BEGIN:VTIMEZONE":
+ case "BEGIN:STANDARD":
+ $type = $value;
+ break;
+ case "END:VTODO": // end special text - goto VCALENDAR key
+ case "END:VEVENT":
+ case "END:VCALENDAR":
+ case "END:DAYLIGHT":
+ case "END:VTIMEZONE":
+ case "END:STANDARD":
+ $type = "VCALENDAR";
+ break;
+ default:
+ $this->addCalendarComponentWithKeyAndValue($type,
+ $keyword,
+ $value);
+ break;
+ }
+ }
+ return $this->cal;
+ }
+ }
+
+ /**
+ * Add to $this->ical array one value and key.
+ *
+ * @param {string} $component This could be VTODO, VEVENT, VCALENDAR, ...
+ * @param {string} $keyword The keyword, for example DTSTART
+ * @param {string} $value The value, for example 20110105T090000Z
+ *
+ * @return {None}
+ */
+ public function addCalendarComponentWithKeyAndValue($component,
+ $keyword,
+ $value)
+ {
+ if ($keyword == false) {
+ $keyword = $this->last_keyword;
+ switch ($component) {
+ case 'VEVENT':
+ $value = $this->cal[$component][$this->event_count - 1]
+ [$keyword].$value;
+ break;
+ case 'VTODO' :
+ $value = $this->cal[$component][$this->todo_count - 1]
+ [$keyword].$value;
+ break;
+ }
+ }
+
+ if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
+ $keyword = explode(";", $keyword);
+ $keyword = $keyword[0];
+ }
+
+ switch ($component) {
+ case "VTODO":
+ $this->cal[$component][$this->todo_count - 1][$keyword] = $value;
+ //$this->cal[$component][$this->todo_count]['Unix'] = $unixtime;
+ break;
+ case "VEVENT":
+ $this->cal[$component][$this->event_count - 1][$keyword] = $value;
+ break;
+ default:
+ $this->cal[$component][$keyword] = $value;
+ break;
+ }
+ $this->last_keyword = $keyword;
+ }
+
+ /**
+ * Get a key-value pair of a string.
+ *
+ * @param {string} $text which is like "VCALENDAR:Begin" or "LOCATION:"
+ *
+ * @return {array} array("VCALENDAR", "Begin")
+ */
+ public function keyValueFromString($text)
+ {
+ preg_match("/([^:]+)[:]([\w\W]*)/", $text, $matches);
+ if (count($matches) == 0) {
+ return false;
+ }
+ $matches = array_splice($matches, 1, 2);
+ return $matches;
+ }
+
+ /**
+ * Return Unix timestamp from ical date time format
+ *
+ * @param {string} $icalDate A Date in the format YYYYMMDD[T]HHMMSS[Z] or
+ * YYYYMMDD[T]HHMMSS
+ *
+ * @return {int}
+ */
+ public function iCalDateToUnixTimestamp($icalDate)
+ {
+ $icalDate = str_replace('T', '', $icalDate);
+ $icalDate = str_replace('Z', '', $icalDate);
+
+ $pattern = '/([0-9]{4})'; // 1: YYYY
+ $pattern .= '([0-9]{2})'; // 2: MM
+ $pattern .= '([0-9]{2})'; // 3: DD
+ $pattern .= '([0-9]{0,2})'; // 4: HH
+ $pattern .= '([0-9]{0,2})'; // 5: MM
+ $pattern .= '([0-9]{0,2})/'; // 6: SS
+ preg_match($pattern, $icalDate, $date);
+
+ // Unix timestamp can't represent dates before 1970
+ if ($date[1] <= 1970) {
+ return false;
+ }
+ // Unix timestamps after 03:14:07 UTC 2038-01-19 might cause an overflow
+ // if 32 bit integers are used.
+ $timestamp = mktime((int)$date[4],
+ (int)$date[5],
+ (int)$date[6],
+ (int)$date[2],
+ (int)$date[3],
+ (int)$date[1]);
+ return $timestamp;
+ }
+
+ /**
+ * Returns an array of arrays with all events. Every event is an associative
+ * array and each property is an element it.
+ *
+ * @return {array}
+ */
+ public function events()
+ {
+ $array = $this->cal;
+ return $array['VEVENT'];
+ }
+
+ /**
+ * Returns a boolean value whether thr current calendar has events or not
+ *
+ * @return {boolean}
+ */
+ public function hasEvents()
+ {
+ return ( count($this->events()) > 0 ? true : false );
+ }
+
+ /**
+ * Returns false when the current calendar has no events in range, else the
+ * events.
+ *
+ * Note that this function makes use of a UNIX timestamp. This might be a
+ * problem on January the 29th, 2038.
+ * See http://en.wikipedia.org/wiki/Unix_time#Representing_the_number
+ *
+ * @param {boolean} $rangeStart Either true or false
+ * @param {boolean} $rangeEnd Either true or false
+ *
+ * @return {mixed}
+ */
+ public function eventsFromRange($rangeStart = false, $rangeEnd = false)
+ {
+ $events = $this->sortEventsWithOrder($this->events(), SORT_ASC);
+
+ if (!$events) {
+ return false;
+ }
+
+ $extendedEvents = array();
+
+ if ($rangeStart !== false) {
+ $rangeStart = new DateTime();
+ }
+
+ if ($rangeEnd !== false or $rangeEnd <= 0) {
+ $rangeEnd = new DateTime('2038/01/18');
+ } else {
+ $rangeEnd = new DateTime($rangeEnd);
+ }
+
+ $rangeStart = $rangeStart->format('U');
+ $rangeEnd = $rangeEnd->format('U');
+
+
+
+ // loop through all events by adding two new elements
+ foreach ($events as $anEvent) {
+ $timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
+ if ($timestamp >= $rangeStart && $timestamp <= $rangeEnd) {
+ $extendedEvents[] = $anEvent;
+ }
+ }
+
+ return $extendedEvents;
+ }
+
+ /**
+ * Returns a boolean value whether thr current calendar has events or not
+ *
+ * @param {array} $events An array with events.
+ * @param {array} $sortOrder Either SORT_ASC, SORT_DESC, SORT_REGULAR,
+ * SORT_NUMERIC, SORT_STRING
+ *
+ * @return {boolean}
+ */
+ public function sortEventsWithOrder($events, $sortOrder = SORT_ASC)
+ {
+ $extendedEvents = array();
+
+ // loop through all events by adding two new elements
+ foreach ($events as $anEvent) {
+ if (!array_key_exists('UNIX_TIMESTAMP', $anEvent)) {
+ $anEvent['UNIX_TIMESTAMP'] =
+ $this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
+ }
+
+ if (!array_key_exists('REAL_DATETIME', $anEvent)) {
+ $anEvent['REAL_DATETIME'] =
+ date("d.m.Y", $anEvent['UNIX_TIMESTAMP']);
+ }
+
+ $extendedEvents[] = $anEvent;
+ }
+
+ foreach ($extendedEvents as $key => $value) {
+ $timestamp[$key] = $value['UNIX_TIMESTAMP'];
+ }
+ array_multisort($timestamp, $sortOrder, $extendedEvents);
+
+ return $extendedEvents;
+ }
+}
diff --git a/mod/apps.php b/mod/apps.php
index 07d1968d2..8c9706d2f 100644
--- a/mod/apps.php
+++ b/mod/apps.php
@@ -30,6 +30,7 @@ function apps_content(&$a) {
}
return replace_macros(get_markup_template('myapps.tpl'), array(
+ '$sitename' => get_config('system','sitename'),
'$title' => t('Apps'),
'$apps' => $apps,
));
diff --git a/mod/photos.php b/mod/photos.php
index 7a9229cc4..f4e770ec0 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -697,13 +697,10 @@ function photos_content(&$a) {
$imagelink = ($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $rr['resource_id']
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
- $rel=("photo");
-
$photos[] = array(
'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4),
'link' => $imagelink,
- 'rel' => $rel,
'title' => t('View Photo'),
'src' => $a->get_baseurl() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext,
'alt' => $imgalt_e,
diff --git a/version.inc b/version.inc
index 22eac0514..a843ce0e3 100644
--- a/version.inc
+++ b/version.inc
@@ -1 +1 @@
-2014-12-21.896
+2014-12-23.898
diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css
index d0b86982a..0d1f45bda 100644
--- a/view/theme/redbasic/css/style.css
+++ b/view/theme/redbasic/css/style.css
@@ -583,10 +583,17 @@ footer {
}
.app-name {
- width: 125px;
overflow: none;
}
+.app-container img {
+ margin-left: auto;
+ margin-right: auto;
+ width: 80px;
+ height: 80px;
+ display: block;
+}
+
.pager {
padding: 10px;
diff --git a/view/tpl/app.tpl b/view/tpl/app.tpl
index 4719f7f96..9f0b1746b 100644
--- a/view/tpl/app.tpl
+++ b/view/tpl/app.tpl
@@ -1,6 +1,6 @@
<div class="app-container">
<a href="{{$app.url}}" {{if $ap.target}}target="{{$ap.target}}" {{/if}}{{if $app.desc}}title="{{$app.desc}}{{if $app.price}} ({{$app.price}}){{/if}}"{{else}}title="{{$app.name}}"{{/if}}><img src="{{$app.photo}}" width="80" height="80" />
-<div class="app-name">{{$app.name}}</div>
+<div class="app-name" style="text-align:center;">{{$app.name}}</div>
</a>
{{if $app.type !== 'system'}}
{{if $purchase}}
diff --git a/view/tpl/apps.tpl b/view/tpl/apps.tpl
deleted file mode 100755
index d8e538cb7..000000000
--- a/view/tpl/apps.tpl
+++ /dev/null
@@ -1,11 +0,0 @@
-<h3>{{$title}}</h3>
-
-{{foreach $apps as $ap}}
-<div class="app-container">
-<a href="{{$ap.url}}" {{if $ap.target}}target="{{$ap.target}}" {{/if}}{{if $ap.hover}}title="{{$ap.hover}}"{{/if}}><img src="{{$ap.photo}}" width="80" height="80" />
-<div class="app-name">{{$ap.name}}</div>
-</a>
-</div>
-{{/foreach}}
-<div class="clear"></div>
-