forked from friendica/friendica-addons
Notifications by E-Mail implemented
This commit is contained in:
parent
5dcbe8eaa5
commit
5b83872773
13 changed files with 245 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -6,5 +6,8 @@ CREATE TABLE locks (
|
|||
token VARCHAR(100),
|
||||
scope TINYINT,
|
||||
depth TINYINT,
|
||||
uri text
|
||||
uri VARCHAR(1000),
|
||||
INDEX(token),
|
||||
INDEX(uri)
|
||||
);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {{{ */
|
||||
|
||||
/**
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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"] . "/");
|
||||
|
|
|
@ -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'>";
|
||||
|
|
54
dav/main.php
54
dav/main.php
|
@ -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');
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue