]> git.mxchange.org Git - friendica-addons.git/commitdiff
Notifications by E-Mail implemented
authorTobias Hößl <tobias@hoessl.eu>
Fri, 27 Jul 2012 18:35:14 +0000 (18:35 +0000)
committerTobias Hößl <tobias@hoessl.eu>
Fri, 27 Jul 2012 18:35:14 +0000 (18:35 +0000)
13 files changed:
dav/SabreDAV/ChangeLog
dav/SabreDAV/bin/migrateto17.php
dav/SabreDAV/examples/sql/mysql.locks.sql
dav/SabreDAV/lib/Sabre/HTTP/BasicAuth.php
dav/SabreDAV/lib/Sabre/HTTP/Version.php
dav/SabreDAV/lib/Sabre/VObject/Component.php
dav/SabreDAV/lib/Sabre/VObject/Component/VCalendar.php
dav/SabreDAV/lib/Sabre/VObject/Node.php
dav/SabreDAV/tests/Sabre/HTTP/BasicAuthTest.php
dav/common/calendar_rendering.fnk.php
dav/common/dav_caldav_backend_private.inc.php
dav/common/wdcal_edit.inc.php
dav/main.php

index 8798f9b0ed9e5a9b8e3d3b11c8cbc322806e554d..1199ae766e9f8cf9db45c7397e21fa4a708ef5ce 100644 (file)
@@ -54,6 +54,8 @@
          the instance of an event, but not the end.
        * Fixed: All-day recurring events wouldn't match if an occurence ended
          exactly on the start of a time-range.
+       * Fixed: HTTP basic auth did not correctly deal with passwords containing
+         colons on some servers.
 
 1.6.3-stable (2012-06-12)
        * Added: It's now possible to specify in Sabre_DAV_Client which type of
index 95db938f8a732be80fabd5372f5cf119dcb8a08d..89207877c68a11212479b29b8d90c4c783cfa770 100644 (file)
@@ -223,7 +223,7 @@ function getDenormalizedData($calendarData) {
             }
         } else {
             $it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->UID);
-            $maxDate = new DateTime(self::MAX_DATE);
+            $maxDate = new DateTime(Sabre_CalDAV_Backend_PDO::MAX_DATE);
             if ($it->isInfinite()) {
                 $lastOccurence = $maxDate->getTimeStamp();
             } else {
index 2fafac9cb23fc3bfc5629d4671f4ce0221410f2d..cf3caf4f71789fd2b292cdb3715664c386b0f6af 100644 (file)
@@ -6,5 +6,8 @@ CREATE TABLE locks (
     token VARCHAR(100),
     scope TINYINT,
     depth TINYINT,
-    uri text
+    uri VARCHAR(1000),
+    INDEX(token),
+    INDEX(uri)
 );
+
index a747cc6a31bf134e2b409d4d39d002d12e38c6f9..f90ed24f5d80c8622a1d806607be31d2771cc1bd 100644 (file)
@@ -46,7 +46,7 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth {
 
         if (strpos(strtolower($auth),'basic')!==0) return false;
 
-        return explode(':', base64_decode(substr($auth, 6)));
+        return explode(':', base64_decode(substr($auth, 6)),2);
 
     }
 
index 23dc7f8a7a17d9de217836a293c09e01645d5af0..e6b4f7e53589964fd2db22be2f43ad62d771689f 100644 (file)
@@ -14,7 +14,7 @@ class Sabre_HTTP_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.6.2';
+    const VERSION = '1.6.4';
 
     /**
      * Stability : alpha, beta, stable
index 6d4b28ac8a02a119fcd6f335428478dee82f14bc..ced5938488fcfc5c871e23f58385618be772e58a 100644 (file)
@@ -104,7 +104,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
          * @return int
          */
         $sortScore = function($key, $array) {
-            
+
             if ($array[$key] instanceof Sabre_VObject_Component) {
                 // We want to encode VTIMEZONE first, this is a personal
                 // preference.
@@ -264,6 +264,27 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
 
     }
 
+    /**
+     * Validates the node for correctness.
+     * An array is returned with warnings.
+     *
+     * Every item in the array has the following properties:
+     *    * level - (number between 1 and 3 with severity information)
+     *    * message - (human readable message)
+     *    * node - (reference to the offending node)
+     *
+     * @return array
+     */
+    public function validate() {
+
+        $result = array();
+        foreach($this->children as $child) {
+            $result = array_merge($result, $child->validate());
+        }
+        return $result;
+
+    }
+
     /* Magic property accessors {{{ */
 
     /**
index f3be29afdbb492c16b7fe28f0e04888c3291fd43..35dd90f2305a9f0b93fc6ab8d569c88801c5bc6e 100644 (file)
@@ -129,5 +129,110 @@ class Sabre_VObject_Component_VCalendar extends Sabre_VObject_Component {
 
     } 
 
+    /**
+     * Validates the node for correctness.
+     * An array is returned with warnings.
+     *
+     * Every item in the array has the following properties:
+     *    * level - (number between 1 and 3 with severity information)
+     *    * message - (human readable message)
+     *    * node - (reference to the offending node)
+     * 
+     * @return array 
+     */
+    public function validate() {
+
+        $warnings = array();
+
+        $version = $this->select('VERSION');
+        if (count($version)!==1) {
+            $warnings[] = array(
+                'level' => 1,
+                'message' => 'The VERSION property must appear in the VCALENDAR component exactly 1 time',
+                'node' => $this,
+            );
+        } else {
+            if ((string)$this->VERSION !== '2.0') {
+                $warnings[] = array(
+                    'level' => 1,
+                    'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.',
+                    'node' => $this,
+                );
+            }
+        } 
+        $version = $this->select('PRODID');
+        if (count($version)!==1) {
+            $warnings[] = array(
+                'level' => 2,
+                'message' => 'The PRODID property must appear in the VCALENDAR component exactly 1 time',
+                'node' => $this,
+            );
+        }
+        if (count($this->CALSCALE) > 1) {
+            $warnings[] = array(
+                'level' => 2,
+                'message' => 'The CALSCALE property must not be specified more than once.',
+                'node' => $this,
+            );
+        }
+        if (count($this->METHOD) > 1) {
+            $warnings[] = array(
+                'level' => 2,
+                'message' => 'The METHOD property must not be specified more than once.',
+                'node' => $this,
+            );
+        }
+
+        $allowedComponents = array(
+            'VEVENT',
+            'VTODO',
+            'VJOURNAL',
+            'VFREEBUSY',
+            'VTIMEZONE',
+        );
+        $allowedProperties = array(
+            'PRODID',
+            'VERSION',
+            'CALSCALE',
+            'METHOD',
+        );
+        $componentsFound = 0;
+        foreach($this->children as $child) {
+            if($child instanceof Sabre_VObject_Component) {
+                $componentsFound++;
+                if (!in_array($child->name, $allowedComponents)) {
+                    $warnings[] = array(
+                        'level' => 1,
+                        'message' => 'The ' . $child->name . " component is not allowed in the VCALENDAR component",
+                        'node' => $this,
+                    );
+                }
+            }
+            if ($child instanceof Sabre_VObject_Property) {
+                if (!in_array($child->name, $allowedProperties)) {
+                    $warnings[] = array(
+                        'level' => 2,
+                        'message' => 'The ' . $child->name . " property is not allowed in the VCALENDAR component",
+                        'node' => $this,
+                    );
+                }
+            }
+        }
+
+        if ($componentsFound===0) {
+            $warnings[] = array(
+                'level' => 1,
+                'message' => 'An iCalendar object must have at least 1 component.',
+                'node' => $this,
+            );
+        }
+
+        return array_merge(
+            $warnings,
+            parent::validate()
+        );
+
+    }
+
 }
 
index 7701309be659c97af676c651836aeb8508ce06e6..6c8319f760eb7bc49c4b13524980dde43c127582 100644 (file)
@@ -32,6 +32,23 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
      */
     public $parent = null;
 
+    /**
+     * Validates the node for correctness.
+     * An array is returned with warnings.
+     *
+     * Every item in the array has the following properties:
+     *    * level - (number between 1 and 3 with severity information)
+     *    * message - (human readable message)
+     *    * node - (reference to the offending node)
+     *
+     * @return array
+     */
+    public function validate() {
+
+        return array();
+
+    }
+
     /* {{{ IteratorAggregator interface */
 
     /**
index b5dd5144554210eebe0408b2c7a8266dd9a1f2c8..1bebcf85e461fddfc3a36e996c6cd12c03dec362 100644 (file)
@@ -60,6 +60,25 @@ class Sabre_HTTP_BasicAuthTest extends PHPUnit_Framework_TestCase {
 
     }
 
+    function testGetUserPassWithColon() {
+
+        $server = array(
+            'HTTP_AUTHORIZATION' => 'Basic ' . base64_encode('admin:1234:5678'),
+        );
+
+        $request = new Sabre_HTTP_Request($server);
+        $this->basicAuth->setHTTPRequest($request);
+
+        $userPass = $this->basicAuth->getUserPass();
+
+        $this->assertEquals(
+            array('admin','1234:5678'),
+            $userPass,
+            'We did not get the username and password we expected'
+        );
+
+    }
+
     function testGetUserPassApacheEdgeCase() {
 
         $server = array(
index e97de36b569ac254a9aa1848df2792c21a9f0496..f8224795707c375b996c60a54e1d920c97f99645 100644 (file)
@@ -73,6 +73,8 @@ function renderCalDavEntry_data(&$calendar, &$calendarobject)
                throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
        }
 
+       $timezoneOffset = date("P"); // @TODO Get the actual timezone from the event
+
 
        if ($componentType !== 'VEVENT') return;
 
@@ -106,15 +108,15 @@ function renderCalDavEntry_data(&$calendar, &$calendarobject)
                $start    = $it->getDtStart()->getTimestamp();
 
                q("INSERT INTO %s%sjqcalendar (`calendar_id`, `calendarobject_id`, `Summary`, `StartTime`, `EndTime`, `IsEditable`, `IsAllDayEvent`, `IsRecurring`, `Color`) VALUES
-                       (%d, %d, '%s', '%s', '%s', %d, %d, %d, '%s')", CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
-                       IntVal($calendar["id"]), IntVal($calendarobject["id"]), dbesc($event["summary"]), date("Y-m-d H:i:s", $start), date("Y-m-d H:i:s", $last_end),
-                       1, $allday, $recurring, dbesc(substr($event["color"], 1))
+                       (%d, %d, '%s', CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), %d, %d, %d, '%s')",
+                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), dbesc($event["summary"]), date("Y-m-d H:i:s", $start),
+                       date("Y-m-d H:i:s", $last_end), 1, $allday, $recurring, dbesc(substr($event["color"], 1))
                );
 
                foreach ($alarms as $alarm) {
                        $alarm    = renderCalDavEntry_calcalarm($alarm, $component);
                        $notified = ($alarm->getTimestamp() < time() ? 1 : 0);
-                       q("INSERT INTO %s%snotifications (`calendar_id`, `calendarobject_id`, `alert_date`, `notified`) VALUES (%d, %d, '%s', %d)",
+                       q("INSERT INTO %s%snotifications (`calendar_id`, `calendarobject_id`, `alert_date`, `notified`) VALUES (%d, %d, CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), %d)",
                                CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), $alarm->format("Y-m-d H:i:s"), $notified
                        );
                }
index b3b32e33698d26f11015213a24e70a02106e965f..86da0270e0df074834b7fdfda5895f34d2d03461 100644 (file)
@@ -113,11 +113,12 @@ class Sabre_CalDAV_Backend_Private extends Sabre_CalDAV_Backend_Common
                $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId);
                $von      = wdcal_php2MySqlTime($sd);
                $bis      = wdcal_php2MySqlTime($ed);
+               $timezoneOffset = date("P");
 
                // @TODO Events, die früher angefangen haben, aber noch andauern
-               $evs = q("SELECT * FROM %s%sjqcalendar WHERE `calendar_id` = %d AND `starttime` between '%s' and '%s'",
-                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
-                       IntVal($calendarId), dbesc($von), dbesc($bis));
+               $evs = q("SELECT *, CONVERT_TZ(`StartTime`, @@session.time_zone, '$timezoneOffset') StartTime, CONVERT_TZ(`EndTime`, @@session.time_zone, '$timezoneOffset') EndTime
+                       FROM %s%sjqcalendar WHERE `calendar_id` = %d AND `StartTime` between '%s' and '%s'",
+                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId), dbesc($von), dbesc($bis));
 
                $events = array();
                foreach ($evs as $row) $events[] = $this->jqcal2wdcal($row, $calendar, $base_path . $row["calendar_id"] . "/");
index 5595369f66337b0e18dbcb50d0daced6719727a6..261e78660dfdafe42ed006970b8a0975e975b9bf 100644 (file)
@@ -70,7 +70,7 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $uri)
                        if ($triggerDuration->s > 0) {
                                $unit = "second";
                                $value = $triggerDuration->s + $triggerDuration->i * 60 + $triggerDuration->h * 3600 + $triggerDuration->d * 3600 * 24; // @TODO support more than days?
-                       }   elseif ($triggerDuration->m) {
+                       } elseif ($triggerDuration->i) {
                                $unit = "minute";
                                $value = $triggerDuration->i + $triggerDuration->h * 60 + $triggerDuration->d * 60 * 24;
                        } elseif ($triggerDuration->h) {
@@ -143,7 +143,7 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $uri)
 
        $out .= "<h2>" . t("Event data") . "</h2>";
 
-       $out .= "<label for='calendar'>" . t("Calendar") . ":</label><select id='calendar' name='calendar' size='1'>";
+       $out .= "<label for='calendar' class='block'>" . t("Calendar") . ":</label><select id='calendar' name='calendar' size='1'>";
        $found   = false;
        $cal_col = "aaaaaa";
        foreach ($calendars as $cal) {
@@ -462,14 +462,15 @@ function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $uri)
 
                $out .= "<div class='noti_holder' ";
                if (!is_numeric($index) && $index == "new") $out .= "style='display: none;' id='noti_new_row'";
-               $out .= "><label class='plain'>" . t("Notify by");
-               $out .= "<select name='noti_type[$index]' size='1'>";
+               $out .= "><label class='block' for='noti_type_" . $index . "'>" . t("Notify by") . ":</label>";
+               $out .= "<select name='noti_type[$index]' size='1' id='noti_type_" . $index . "'>";
                $out .= "<option value=''>- " . t("Remove") . " -</option>\n";
                $out .= "<option value='email' "; if (!$unparsable && $noti["action"] == "email") $out .= "selected"; $out .= ">" . t("E-Mail") . "</option>\n";
                $out .= "<option value='display' "; if (!$unparsable && $noti["action"] == "display") $out .= "selected"; $out .= ">" . t("On Friendica / Display") . "</option>\n";
                //$out .= "<option value='other' "; if ($unparsable) $out .= "selected"; $out .= ">- " . t("other (leave it untouched)") . " -</option>\n"; // @TODO
-               $out .= "</select></label>";
+               $out .= "</select><br>";
 
+               $out .= "<label class='block'>" . t("Time") . ":</label>";
                $out .= "<input name='noti_value[$index]' size='5' style='width: 5em;' value='" . $noti["trigger_value"] . "'>";
 
                $out .= "<select name='noti_unit[$index]' size='1'>";
index 14c987242782fd86afb3c3fbfc2b7415a5ff61ff..e893203493a7452e934e2751164f0813984626ee 100644 (file)
@@ -7,6 +7,7 @@ function dav_install()
        register_hook('event_created', 'addon/dav/dav.php', 'dav_event_created_hook');
        register_hook('event_updated', 'addon/dav/dav.php', 'dav_event_updated_hook');
        register_hook('profile_tabs', 'addon/dav/dav.php', 'dav_profile_tabs_hook');
+       register_hook('cron', 'addon/dav/dav.php', 'dav_cron');
 }
 
 
@@ -15,6 +16,7 @@ function dav_uninstall()
        unregister_hook('event_created', 'addon/dav/dav.php', 'dav_event_created_hook');
        unregister_hook('event_updated', 'addon/dav/dav.php', 'dav_event_updated_hook');
        unregister_hook('profile_tabs', 'addon/dav/dav.php', 'dav_profile_tabs_hook');
+       unregister_hook('cron', 'addon/dav/dav.php', 'dav_cron');
 }
 
 
@@ -97,7 +99,7 @@ function dav_init(&$a)
        }
 
 
-       $server = dav_create_server();
+       $server  = dav_create_server();
        $browser = new Sabre_DAV_Browser_Plugin();
        $server->addPlugin($browser);
        $server->exec();
@@ -159,8 +161,8 @@ function dav_content()
                        }
                } else {
                        $server = dav_create_server(true, true, false);
-                       $cals = dav_get_current_user_calendars($server, DAV_ACL_READ);
-                       $x = wdcal_printCalendar($cals, array(), $a->get_baseurl() . "/dav/wdcal/feed/", "week", 0, 200);
+                       $cals   = dav_get_current_user_calendars($server, DAV_ACL_READ);
+                       $x      = wdcal_printCalendar($cals, array(), $a->get_baseurl() . "/dav/wdcal/feed/", "week", 0, 200);
                }
        }
        return $x;
@@ -205,6 +207,58 @@ function dav_profile_tabs_hook(&$a, &$b)
        );
 }
 
+
+
+/**
+ * @param App $a
+ * @param object $b
+ */
+function dav_cron(&$a, &$b)
+{
+       dav_include_files();
+
+       $r = q("SELECT * FROM %s%snotifications WHERE `notified` = 0 AND `alert_date` <= NOW()", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
+       foreach ($r as $not) {
+               q("UPDATE %s%snotifications SET `notified` = 1 WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $not["id"]);
+               $event = q("SELECT * FROM %s%sjqcalendar WHERE `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $not["calendarobject_id"]);
+               $calendar = q("SELECT * FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB,CALDAV_SQL_PREFIX, $not["calendar_id"]);
+               $users = array();
+               if (count($calendar) != 1 || count($event) == 0) continue;
+               switch ($calendar[0]["namespace"]) {
+                       case CALDAV_NAMESPACE_PRIVATE:
+                               $user = q("SELECT * FROM user WHERE `uid` = %d AND `blocked` = 0", $calendar[0]["namespace_id"]);
+                               if (count($user) != 1) continue;
+                               $users[] = $user[0];
+                               break;
+               }
+               switch ($not["action"]) {
+                       case "email": case "display": // @TODO implement "Display"
+                               foreach ($users as $user) {
+                                       $find = array( "%to%" , "%event%", "%url%");
+                                       $repl = array($user["username"], $event[0]["Summary"], $a->get_baseurl() . "/dav/wdcal/" . $calendar[0]["id"] . "/" . $not["calendarobject_id"] . "/");
+                                       $text_text = str_replace($find, $repl, "Hi %to%!\n\nThe event \"%event%\" is about to begin:\n%url%");
+                                       $text_html = str_replace($find, $repl, "Hi %to%!<br>\n<br>\nThe event \"%event%\" is about to begin:<br>\n<a href='" . "%url%" . "'>%url%</a>");
+                                       $params = array(
+                                               'fromName' => FRIENDICA_PLATFORM,
+                                               'fromEmail' => t('noreply') . '@' . $a->get_hostname(),
+                                               'replyTo' => t('noreply') . '@' . $a->get_hostname(),
+                                               'toEmail' => $user["email"],
+                                               'messageSubject' => t("Notification: " . $event[0]["Summary"]),
+                                               'htmlVersion' => $text_html,
+                                               'textVersion' => $text_text,
+                                               'additionalMailHeader' => "",
+                                       );
+                                       require_once('include/enotify.php');
+                                       enotify::send($params);
+                               }
+                               break;
+               }
+       }
+}
+
+
+
+
 /**
  * @param App $a
  * @param null|object $o