From 02b6d470826afa4d555efe48dd853712e9777bba Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Sun, 30 Oct 2011 16:05:14 +1300 Subject: [PATCH 01/13] Add the $c->hide_alarms functionality into DAVResource class. --- inc/DAVResource.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/inc/DAVResource.php b/inc/DAVResource.php index 486ed5f1..eb196b66 100644 --- a/inc/DAVResource.php +++ b/inc/DAVResource.php @@ -283,6 +283,17 @@ class DAVResource $this->resource->location = null; $this->resource->url = null; } + else if ( isset($c->hide_alarms) && $c->hide_alarms && !$this->HavePrivilegeTo('write') ) { + $vcal1 = new iCalComponent($this->resource->caldav_data); + $comps = $vcal1->GetComponents(); + $vcal2 = new iCalComponent(); + $vcal2->VCalendar(); + foreach( $comps AS $comp ) { + $comp->ClearComponents('VALARM'); + $vcal2->AddComponent($comp); + } + $this->resource->caldav_data = $vcal2->Render(); + } } else if ( strtoupper(substr($this->resource->caldav_data,0,11)) == 'BEGIN:VCARD' ) { $this->contenttype = 'text/vcard'; From 10afabbeb9dba524e3ac2115814a1fb675afb88e Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Mon, 31 Oct 2011 13:15:49 +1300 Subject: [PATCH 02/13] Rationalise confidential event rewriting and fix $c->hide_alarm function. --- inc/DAVResource.php | 2 +- inc/caldav-REPORT-calquery.php | 14 +- inc/caldav-REPORT.php | 148 +++--------------- .../regression-suite/0218-Moz-REPORT.result | 21 +-- .../regression-suite/0219-Moz-REPORT.result | 21 +-- 5 files changed, 51 insertions(+), 155 deletions(-) diff --git a/inc/DAVResource.php b/inc/DAVResource.php index eb196b66..03c4d9ee 100644 --- a/inc/DAVResource.php +++ b/inc/DAVResource.php @@ -283,7 +283,7 @@ class DAVResource $this->resource->location = null; $this->resource->url = null; } - else if ( isset($c->hide_alarms) && $c->hide_alarms && !$this->HavePrivilegeTo('write') ) { + else if ( isset($c->hide_alarm) && $c->hide_alarm && !$this->HavePrivilegeTo('write') ) { $vcal1 = new iCalComponent($this->resource->caldav_data); $comps = $vcal1->GetComponents(); $vcal2 = new iCalComponent(); diff --git a/inc/caldav-REPORT-calquery.php b/inc/caldav-REPORT-calquery.php index 8419c243..eda04f9d 100644 --- a/inc/caldav-REPORT-calquery.php +++ b/inc/caldav-REPORT-calquery.php @@ -334,25 +334,25 @@ $sql = 'SELECT caldav_data.*,calendar_item.* FROM collection INNER JOIN caldav_ if ( isset($c->strict_result_ordering) && $c->strict_result_ordering ) $sql .= " ORDER BY caldav_data.dav_id"; $qry = new AwlQuery( $sql, $params ); if ( $qry->Exec("calquery",__LINE__,__FILE__) && $qry->rows() > 0 ) { - while( $calendar_object = $qry->Fetch() ) { - if ( !$need_post_filter || apply_filter( $qry_filters, $calendar_object ) ) { + while( $dav_object = $qry->Fetch() ) { + if ( !$need_post_filter || apply_filter( $qry_filters, $dav_object ) ) { if ( $bound_from != $target_collection->dav_name() ) { - $calendar_object->dav_name = str_replace( $bound_from, $target_collection->dav_name(), $calendar_object->dav_name); + $dav_object->dav_name = str_replace( $bound_from, $target_collection->dav_name(), $dav_object->dav_name); } if ( $need_expansion ) { - $vResource = new vComponent($calendar_object->caldav_data); + $vResource = new vComponent($dav_object->caldav_data); $expanded = expand_event_instances($vResource, $expand_range_start, $expand_range_end, $expand_as_floating ); if ( $expanded->ComponentCount() == 0 ) continue; - if ( $need_expansion ) $calendar_object->caldav_data = $expanded->Render(); + if ( $need_expansion ) $dav_object->caldav_data = $expanded->Render(); } else if ( isset($range_filter) ) { - $vResource = new vComponent($calendar_object->caldav_data); + $vResource = new vComponent($dav_object->caldav_data); $expanded = getVCalendarRange($vResource); dbg_error_log('calquery', 'Expanded to %s:%s which might overlap %s:%s', $expanded->from, $expanded->until, $range_filter->from, $range_filter->until ); if ( !$expanded->overlaps($range_filter) ) continue; } - $responses[] = calendar_to_xml( $properties, $calendar_object ); + $responses[] = component_to_xml( $properties, $dav_object ); } } } diff --git a/inc/caldav-REPORT.php b/inc/caldav-REPORT.php index ca1848a7..c100e5d8 100644 --- a/inc/caldav-REPORT.php +++ b/inc/caldav-REPORT.php @@ -39,7 +39,7 @@ if ( $xmltree->GetTag() != 'DAV::principal-property-search' $target->NeedPrivilege( array('DAV::read', 'urn:ietf:params:xml:ns:caldav:read-free-busy'), true ); // They may have either } -require_once("iCalendar.php"); +require_once("vCalendar.php"); $reportnum = -1; $report = array(); @@ -80,110 +80,6 @@ switch( $xmltree->GetTag() ) { } -/** -* Return XML for a single calendar (or todo) entry from the DB -* -* @param array $properties The properties for this calendar -* @param string $item The calendar data for this calendar -* -* @return string An XML document which is the response for the calendar -*/ -function calendar_to_xml( $properties, $item ) { - global $session, $c, $request, $reply; - - dbg_error_log("REPORT","Building XML Response for item '%s'", $item->dav_name ); - - $denied = array(); - $caldav_data = $item->caldav_data; - $displayname = $item->summary; - if ( isset($properties['calendar-data']) || isset($properties['displayname']) ) { - if ( !$request->AllowedTo('all') && $session->user_no != $item->user_no ){ - // the user is not admin / owner of this calendarlooking at his calendar and can not admin the other cal - /** @todo We should examine the ORGANIZER and ATTENDEE fields in the event. If this person is there then they should see this */ - if ( $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read') ) { - $ical = new iCalComponent( $caldav_data ); - $resources = $ical->GetComponents('VTIMEZONE',false); - $first = $resources[0]; - - // if the event is confidential we fake one that just says "Busy" - $confidential = new iCalComponent(); - $confidential->SetType($first->GetType()); - $confidential->AddProperty( 'SUMMARY', translate('Busy') ); - $confidential->AddProperty( 'CLASS', 'CONFIDENTIAL' ); - $confidential->SetProperties( $first->GetProperties('DTSTART'), 'DTSTART' ); - $confidential->SetProperties( $first->GetProperties('RRULE'), 'RRULE' ); - $confidential->SetProperties( $first->GetProperties('DURATION'), 'DURATION' ); - $confidential->SetProperties( $first->GetProperties('DTEND'), 'DTEND' ); - $confidential->SetProperties( $first->GetProperties('UID'), 'UID' ); - $ical->SetComponents(array($confidential),$confidential->GetType()); - - $caldav_data = $ical->Render(); - $displayname = translate('Busy'); - } - } - } - - $url = ConstructURL($item->dav_name); - - $prop = new XMLElement("prop"); - foreach( $properties AS $k => $v ) { - switch( $k ) { - case 'getcontentlength': - $contentlength = strlen($caldav_data); - $prop->NewElement($k, $contentlength ); - break; - case 'getlastmodified': - $prop->NewElement($k, ISODateToHTTPDate($item->modified) ); - break; - case 'calendar-data': - $reply->CalDAVElement($prop, $k, $caldav_data ); - break; - case 'getcontenttype': - $prop->NewElement($k, "text/calendar" ); - break; - case 'current-user-principal': - $prop->NewElement("current-user-principal", $request->current_user_principal_xml); - break; - case 'displayname': - $prop->NewElement($k, $displayname ); - break; - case 'resourcetype': - $prop->NewElement($k); // Just an empty resourcetype for a non-collection. - break; - case 'getetag': - $prop->NewElement($k, '"'.$item->dav_etag.'"' ); - break; - case '"current-user-privilege-set"': - $prop->NewElement($k, privileges($request->permissions) ); - break; - case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */ - $denied[] = $v; - break; - default: - dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $v ); - $unsupported[] = $v; - } - } - $status = new XMLElement("status", "HTTP/1.1 200 OK" ); - - $propstat = new XMLElement( "propstat", array( $prop, $status) ); - $href = new XMLElement("href", $url ); - $elements = array($href,$propstat); - - if ( count($denied) > 0 ) { - $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" ); - $noprop = new XMLElement("prop"); - foreach( $denied AS $k => $v ) { - $noprop->NewElement( strtolower($v) ); - } - $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); - } - - $response = new XMLElement( "response", $elements ); - - return $response; -} - /** * Return XML for a single component from the DB @@ -219,33 +115,27 @@ function component_to_xml( $properties, $item ) { $contenttype = 'text/vcard'; break; } - if ( isset($properties['calendar-data']) || isset($properties['displayname']) ) { - if ( !$request->AllowedTo('all') && $session->user_no != $item->user_no ){ - // the user is not admin / owner of this calendarlooking at his calendar and can not admin the other cal - /** @todo We should examine the ORGANIZER and ATTENDEE fields in the event. If this person is there then they should see this */ - if ( $type == 'calendar' && $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read') ) { - $ical = new iCalComponent( $caldav_data ); - $resources = $ical->GetComponents('VTIMEZONE',false); - $first = $resources[0]; - - // if the event is confidential we fake one that just says "Busy" - $confidential = new iCalComponent(); - $confidential->SetType($first->GetType()); - $confidential->AddProperty( 'SUMMARY', translate('Busy') ); - $confidential->AddProperty( 'CLASS', 'CONFIDENTIAL' ); - $confidential->SetProperties( $first->GetProperties('DTSTART'), 'DTSTART' ); - $confidential->SetProperties( $first->GetProperties('RRULE'), 'RRULE' ); - $confidential->SetProperties( $first->GetProperties('DURATION'), 'DURATION' ); - $confidential->SetProperties( $first->GetProperties('DTEND'), 'DTEND' ); - $confidential->SetProperties( $first->GetProperties('UID'), 'UID' ); - $ical->SetComponents(array($confidential),$confidential->GetType()); - - $caldav_data = $ical->Render(); - $displayname = translate('Busy'); + if ( $type == 'calendar' ) { + if ( isset($properties['calendar-data']) || isset($properties['displayname']) ) { + if ( !$request->AllowedTo('all') && $session->user_no != $item->user_no ) { + // the user is not admin / owner of this calendar looking at his calendar and can not admin the other cal + if ( $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read') ) { + dbg_error_log("REPORT","Anonymising confidential event for: %s", $item->dav_name ); + $vcal = new vCalendar( $caldav_data ); + $caldav_data = $vcal->Confidential()->Render(); + $displayname = translate('Busy'); + } } } + + if ( isset($properties['calendar-data']) && isset($c->hide_alarm) && $c->hide_alarm && !$request->HavePrivilegeTo('write') ) { + dbg_error_log("REPORT","Stripping event alarms for: %s", $item->dav_name ); + $vcal = new vCalendar($caldav_data); + $vcal->ClearComponents('VALARM'); + $caldav_data = $vcal->Render(); + } } - + $url = ConstructURL($item->dav_name); $prop = new XMLElement("prop"); diff --git a/testing/tests/regression-suite/0218-Moz-REPORT.result b/testing/tests/regression-suite/0218-Moz-REPORT.result index fb357ead..298b9150 100644 --- a/testing/tests/regression-suite/0218-Moz-REPORT.result +++ b/testing/tests/regression-suite/0218-Moz-REPORT.result @@ -2,8 +2,8 @@ HTTP/1.1 207 Multi-Status Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule -ETag: "452f45250e12e66d9f6db823b4615a48" -Content-Length: 3503 +ETag: "987fc68a44b7bc99bdf6fe3ab2d0b0ad" +Content-Length: 3587 Content-Type: text/xml; charset="utf-8" @@ -60,6 +60,16 @@ END:VCALENDAR BEGIN:VCALENDAR PRODID:-//Mozilla Calendar//NONSGML Sunbird//EN VERSION:2.0 +BEGIN:VEVENT +CREATED:20061223T032350Z +LAST-MODIFIED:20061223T033144Z +DTSTAMP:20061223T033144Z +UID:9d050be7-8a02-4355-8ed3-02a9fc5f473f +CLASS:CONFIDENTIAL +DTSTART;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T160000 +DTEND;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T180000 +SUMMARY:Busy +END:VEVENT BEGIN:VTIMEZONE TZID:/mozilla.org/20050126_1/Antarctica/McMurdo X-LIC-LOCATION:Antarctica/McMurdo @@ -78,13 +88,6 @@ DTSTART:19701004T020000 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=10 END:DAYLIGHT END:VTIMEZONE -BEGIN:VEVENT -SUMMARY:Busy -CLASS:CONFIDENTIAL -DTSTART;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T160000 -DTEND;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T180000 -UID:9d050be7-8a02-4355-8ed3-02a9fc5f473f -END:VEVENT END:VCALENDAR diff --git a/testing/tests/regression-suite/0219-Moz-REPORT.result b/testing/tests/regression-suite/0219-Moz-REPORT.result index 11acd203..1ae215d0 100644 --- a/testing/tests/regression-suite/0219-Moz-REPORT.result +++ b/testing/tests/regression-suite/0219-Moz-REPORT.result @@ -2,8 +2,8 @@ HTTP/1.1 207 Multi-Status Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule DAV: extended-mkcol, calendar-proxy, bind, addressbook -ETag: "452f45250e12e66d9f6db823b4615a48" -Content-Length: 3503 +ETag: "987fc68a44b7bc99bdf6fe3ab2d0b0ad" +Content-Length: 3587 Content-Type: text/xml; charset="utf-8" @@ -60,6 +60,16 @@ END:VCALENDAR BEGIN:VCALENDAR PRODID:-//Mozilla Calendar//NONSGML Sunbird//EN VERSION:2.0 +BEGIN:VEVENT +CREATED:20061223T032350Z +LAST-MODIFIED:20061223T033144Z +DTSTAMP:20061223T033144Z +UID:9d050be7-8a02-4355-8ed3-02a9fc5f473f +CLASS:CONFIDENTIAL +DTSTART;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T160000 +DTEND;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T180000 +SUMMARY:Busy +END:VEVENT BEGIN:VTIMEZONE TZID:/mozilla.org/20050126_1/Antarctica/McMurdo X-LIC-LOCATION:Antarctica/McMurdo @@ -78,13 +88,6 @@ DTSTART:19701004T020000 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=10 END:DAYLIGHT END:VTIMEZONE -BEGIN:VEVENT -SUMMARY:Busy -CLASS:CONFIDENTIAL -DTSTART;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T160000 -DTEND;TZID=/mozilla.org/20050126_1/Antarctica/McMurdo:20061223T180000 -UID:9d050be7-8a02-4355-8ed3-02a9fc5f473f -END:VEVENT END:VCALENDAR From a1f92882246038ff5cb88680dca13055c0b4ffed Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Tue, 1 Nov 2011 17:44:45 +1300 Subject: [PATCH 03/13] Update website to reflect new default calendar name. --- docs/website/clients/Chandler-details.php | 2 +- docs/website/clients/Evolution-details.php | 2 +- .../clients/Interoperability-details.php | 28 +++++++++++++------ docs/website/clients/Mozilla-details.php | 2 +- docs/website/clients/Other-details.php | 21 ++++++++++++++ 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/docs/website/clients/Chandler-details.php b/docs/website/clients/Chandler-details.php index ba301955..8214309f 100644 --- a/docs/website/clients/Chandler-details.php +++ b/docs/website/clients/Chandler-details.php @@ -7,7 +7,7 @@ written in Python.

  1. Select "Subscribe" from the "Share" menu (or in older builds it was in the "Collection" menu).
  2. -
  3. Enter a URL like: "http://calendar.example.net/caldav.php/username/home/" (click "Subscribe")
     
  4. +
  5. Enter a URL like: "http://calendar.example.net/caldav.php/username/calendar/" (click "Subscribe")
     
  6. You will then be prompted for a username/password with in an expanded dialog. Enter these and click "Subscribe" again.
     
  7. You should now have a new calendar showing.
diff --git a/docs/website/clients/Evolution-details.php b/docs/website/clients/Evolution-details.php index 39691d1f..1727cb57 100644 --- a/docs/website/clients/Evolution-details.php +++ b/docs/website/clients/Evolution-details.php @@ -5,7 +5,7 @@ was little in the way of a repository available to test against until recently.<
  1. Select "File" then "New" then "Calendar" from the menus.
  2. -
  3. Choose a type of "CalDAV", enter a name, and a URL such as caldav://server.domain.name/caldav.php/username/home/, enter your user name for DAViCal and click "OK".
     
  4. +
  5. Choose a type of "CalDAV", enter a name, and a URL such as caldav://server.domain.name/caldav.php/username/calendar/, enter your user name for DAViCal and click "OK".
     
  6. You should now be prompted for a password for that username. Enter the password and your calendar should now show.
diff --git a/docs/website/clients/Interoperability-details.php b/docs/website/clients/Interoperability-details.php index 0a226fba..4bee40ac 100644 --- a/docs/website/clients/Interoperability-details.php +++ b/docs/website/clients/Interoperability-details.php @@ -10,13 +10,25 @@ that Mulberry does it.

  • Calendar namespace
  • -

    The host name is, of course, up to you. The 'root path' should be /caldav.php/ and anything following that is the calendar namespace.

    -

    Within the calendar namespace DAViCal uses the first element of the path as the user or resource name, so that a client connecting at the root path -can see all of the (accessible) users and resources available to them (Mulberry displays this hierarchy) with any calendars below that.

    -

    Effectively this means that in Evolution, Sunbird and Lightning you should really specify a calendar URL which is something like:

    +

    The host name is, of course, up to you. The 'root path' should be +/caldav.php/ and anything following that is the calendar +namespace.

    + +

    Within the calendar namespace DAViCal uses the first element of the +path as the user or 'princpal' name, so that a client connecting at the +root path can see all of the (accessible) users and resources available +to them (Mulberry displays this hierarchy) with any calendars below that.

    + +

    This means that in Evolution, Lightning and other software wanting a +'calendar' URL you should specify a URL which is something like:

    -http://calendar.example.net/caldav.php/username/home/
    +http://calendar.example.net/caldav.php/username/calendar/
     
    -

    Then, when more calendar client software sees it as useful to be able to browse that hierarchy, you won't be up for any heavy database manipulation.

    -

    I may well enforce this standard in some way before release 1.0, as well as auto-creating the collection records when Evolution, Lightning -or Sunbird attempt to store to a non-existent collection.

    + +

    DAViCal creates two collections automatically when a user is created. In +recent versions these are called 'calendar' and 'addressbook'. Some software +also makes it easy to create more calendars and addressbooks, or you can create +more through DAViCal's web interface, also.

    + +

    In older versions of DAViCal (pre 0.9.9.5) the default calendar was named 'home' +and there was no default addressbook.

    diff --git a/docs/website/clients/Mozilla-details.php b/docs/website/clients/Mozilla-details.php index 9a637fd9..99cbdc7c 100644 --- a/docs/website/clients/Mozilla-details.php +++ b/docs/website/clients/Mozilla-details.php @@ -8,7 +8,7 @@
    1. Select "New Calendar" from the "File" menu.
    2. Choose "On the Network" (click "Next")
       
    3. -
    4. Choose a format of "CalDAV" and enter a URL like: "http://calendar.example.net/caldav.php/username/home/" (click "Next")
       
    5. +
    6. Choose a format of "CalDAV" and enter a URL like: "http://calendar.example.net/caldav.php/username/calendar/" (click "Next")
       
    7. Give the calendar an appropriate display name, and choose a colour for events on this calendar. (click "Next")
       
    8. click "Finish"
    diff --git a/docs/website/clients/Other-details.php b/docs/website/clients/Other-details.php index 0ca4ca8e..f88cb9b7 100644 --- a/docs/website/clients/Other-details.php +++ b/docs/website/clients/Other-details.php @@ -6,3 +6,24 @@ against, but so far these are the only ones I have access to.

    If you want to point me at more free software that supports CalDAV, or send me free copies of such proprietary software, then I will add it to the list as well as make DAViCal work with it.

    + +

    In the general CalDAV terminology, client software will want to know +several facts about the CalDAV server. Some (like iCal and iOS) will try +and discover these facts for themselves, and others (like Lightning and +Evolution) will require you to enter some information. When they ask for +that information they will be asking for the following things:

    +
      +
    1. Where is the user's "home" collection?
    2. +
    3. Where is the user's "calendar" collection?
    4. +
    5. What is the server's domain name
    6. +
    + +

    Typically the answers, in DAViCal's case, are:

    +
      +
    1. .../caldav.php/username/
    2. +
    3. .../caldav.php/username/calendar/ (although in older versions the default calendar was called 'home' rather than 'calendar')
    4. +
    5. I can't help here - whatever you called it, I guess!
    6. +
    + +

    There could well be a wider range of information about many and varied client + software on the DAViCal Wiki as well. \ No newline at end of file From fc0db0e23b09eb37ec89b5ef54723cd9573e5b3b Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Tue, 1 Nov 2011 17:47:06 +1300 Subject: [PATCH 04/13] Fix handling of active flag for general external authentication mechanisms. --- inc/HTTPAuthSession.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/inc/HTTPAuthSession.php b/inc/HTTPAuthSession.php index 4bad8fa3..1715ea1d 100644 --- a/inc/HTTPAuthSession.php +++ b/inc/HTTPAuthSession.php @@ -139,6 +139,11 @@ class HTTPAuthSession { */ if ( isset($_SERVER['PHP_AUTH_USER']) ) { if ( $p = $this->CheckPassword( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) { + if ( isset($p->active) && !isset($p->user_active) ) { + trace_bug('Some authentication failed to return a dav_principal record and needs fixing.'); + $p->user_active = $p->active; + } + /** * Maybe some external authentication didn't return false for an inactive * user, so we'll be pedantic here. @@ -300,7 +305,11 @@ class HTTPAuthSession { * It can expect that: * - Configuration data will be in $c->authenticate_hook['config'], which might be an array, or whatever is needed. */ - return call_user_func( $c->authenticate_hook['call'], $username, $password ); + $principal = call_user_func( $c->authenticate_hook['call'], $username, $password ); + if ( $principal !== false && !($principal instanceof Principal) ) { + $principal = new Principal('username', $username); + } + return $principal; } return false; From 3001207904c90456c6b13fcee4ff403b0ad4c0d8 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Tue, 1 Nov 2011 18:00:02 +1300 Subject: [PATCH 05/13] Update refresh-alarms script to newer style initialisation. This approach makes for a tidier and more reliable initialisation. --- scripts/refresh-alarms.php | 54 ++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 29 deletions(-) mode change 100644 => 100755 scripts/refresh-alarms.php diff --git a/scripts/refresh-alarms.php b/scripts/refresh-alarms.php old mode 100644 new mode 100755 index 18458192..08c39f9d --- a/scripts/refresh-alarms.php +++ b/scripts/refresh-alarms.php @@ -1,29 +1,18 @@ -#!/usr/bin/php +#!/usr/bin/env php +* @copyright Morphoss Ltd +* @license http://gnu.org/copyleft/gpl.html GNU GPL v3 or later +*/ +$script_file = __FILE__; -set_include_path('.'); - -function add_path_for( $include, $paths ) { - foreach( $paths AS $test_path ) { - if ( @file_exists($test_path.'/'.$include) ) { - set_include_path( $test_path. PATH_SEPARATOR. get_include_path()); - return; - } - } -} - -add_path_for('AWLUtilities.php', array( '../../awl/inc' , '../awl/inc' - , '../../../awl/inc' , '/usr/share/awl/inc' , '/usr/local/share/awl/inc') ); -add_path_for('caldav-client-v2.php', array( '../../davical/inc' , '../davical/inc' - , '../../../davical/inc' , '/usr/share/davical/inc' , '/usr/local/share/davical/inc') ); -add_path_for('always.php', array( 'scripts' ) ); -add_path_for('sync-config.php', array( 'config' ) ); - - -require('always.php'); -require_once('AwlQuery.php'); -require_once('RRule-v2.php'); -require_once('vComponent.php'); +chdir(str_replace('/scripts/refresh-alarms.php','/htdocs',$script_file)); +$_SERVER['SERVER_NAME'] = 'localhost'; /** * Call with something like e.g.: @@ -41,15 +30,17 @@ $args->near_past = 'P1D'; $args->far_past = 'P1200D'; $debugging = null; + function parse_arguments() { global $args; - $opts = getopt( 'f:p:n:d:lh' ); + $opts = getopt( 'f:p:s:n:d:lh' ); foreach( $opts AS $k => $v ) { switch( $k ) { case 'f': $args->future = $v; break; case 'n': $args->near_past = $v; break; case 'p': $args->far_past = $v; break; + case 's': $_SERVER['SERVER_NAME'] = $v; break; case 'd': $args->debug = true; $debugging = explode(',',$v); break; case 'l': $args->set_last = true; break; case 'h': usage(); break; @@ -59,9 +50,10 @@ function parse_arguments() { } function usage() { - echo << Near past period to skip for finding last instances: default 1 days ('P1D') -p Far past period to examine for finding last instances: default ~3 years ('P1200D') @@ -71,8 +63,7 @@ Usage: -d Enable debugging -EOUSAGE; - +USAGE; exit(0); } @@ -86,6 +77,11 @@ if ( $args->debug && is_array($debugging )) { $args->near_past = '-' . $args->near_past; $args->far_past = '-' . $args->far_past; +require_once("./always.php"); +require_once('AwlQuery.php'); +require_once('RRule-v2.php'); +require_once('vComponent.php'); + /** * Essentially what we are doing is: From d8d16c8ee904b89abf1ee3a1c11f83b5e2adf4d8 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 01:30:45 +1300 Subject: [PATCH 06/13] Checkpoint the current code for scheduling on DELETE . --- inc/DAVResource.php | 29 +- inc/WritableCollection.php | 169 ++++++++-- inc/caldav-DELETE.php | 8 +- inc/schedule-functions.php | 310 ++++++++++++++++++ .../tests/scheduling/3026-PUT-Accept.result | 16 +- .../3027-PUT-iCal-with-attendees.result | 8 +- .../3027-PUT-iCal-with-attendees.test | 2 +- .../tests/scheduling/3028-DELETE-reply.result | 14 + .../tests/scheduling/3028-DELETE-reply.test | 18 + .../tests/scheduling/3029-DELETE-reply.result | 12 + .../tests/scheduling/3029-DELETE-reply.test | 20 ++ .../3030-DELETE-attendee-event.result | 70 ++++ .../3030-DELETE-attendee-event.test | 23 ++ .../tests/scheduling/3031-DELETE-reply.test | 21 ++ .../3032-PUT-iCal-with-attendees.test | 73 +++++ .../3033-DELETE-organizer-event.test | 31 ++ 16 files changed, 784 insertions(+), 40 deletions(-) create mode 100644 inc/schedule-functions.php create mode 100644 testing/tests/scheduling/3028-DELETE-reply.result create mode 100644 testing/tests/scheduling/3028-DELETE-reply.test create mode 100644 testing/tests/scheduling/3029-DELETE-reply.result create mode 100644 testing/tests/scheduling/3029-DELETE-reply.test create mode 100644 testing/tests/scheduling/3030-DELETE-attendee-event.result create mode 100644 testing/tests/scheduling/3030-DELETE-attendee-event.test create mode 100644 testing/tests/scheduling/3031-DELETE-reply.test create mode 100644 testing/tests/scheduling/3032-PUT-iCal-with-attendees.test create mode 100644 testing/tests/scheduling/3033-DELETE-organizer-event.test diff --git a/inc/DAVResource.php b/inc/DAVResource.php index 03c4d9ee..7cb3f5b2 100644 --- a/inc/DAVResource.php +++ b/inc/DAVResource.php @@ -1059,8 +1059,8 @@ EOQRY; /** - * Checks whether this resource is a calendar - * @param string $type The type of scheduling collection, 'read', 'write' or 'any' + * Checks whether this resource is a scheduling inbox/outbox collection + * @param string $type The type of scheduling collection, 'inbox', 'outbox' or 'any' */ function IsSchedulingCollection( $type = 'any' ) { if ( $this->_is_collection && preg_match( '{schedule-(inbox|outbox)}', $this->collection->type, $matches ) ) { @@ -1070,6 +1070,18 @@ EOQRY; } + /** + * Checks whether this resource is IN a scheduling inbox/outbox collection + * @param string $type The type of scheduling collection, 'inbox', 'outbox' or 'any' + */ + function IsInSchedulingCollection( $type = 'any' ) { + if ( !$this->_is_collection && preg_match( '{schedule-(inbox|outbox)}', $this->collection->type, $matches ) ) { + return ($type == 'any' || $type == $matches[1]); + } + return false; + } + + /** * Checks whether this resource is an addressbook */ @@ -1256,6 +1268,14 @@ EOQRY; } + /** + * Checks whether the target collection is for public events only + */ + function IsPublicOnly() { + return ( isset($this->collection->publicly_events_only) && $this->collection->publicly_events_only == 't' ); + } + + /** * Return the type of whatever contains this resource, or would if it existed. */ @@ -1382,6 +1402,11 @@ EOQRY; return clone($this->resource); break; + case 'dav-data': + if ( !isset($this->resource) ) $this->FetchResource(); + return $this->resource->caldav_data; + break; + case 'principal': if ( !isset($this->principal) ) $this->FetchPrincipal(); return clone($this->principal); diff --git a/inc/WritableCollection.php b/inc/WritableCollection.php index 34e5b802..6d2bb91e 100644 --- a/inc/WritableCollection.php +++ b/inc/WritableCollection.php @@ -17,7 +17,7 @@ class WritableCollection extends DAVResource { return $p->GetParameterValue('TZID'); } - /** + /** * Writes the data to a member in the collection and returns the segment_name of the * resource in our internal namespace. * @@ -36,7 +36,7 @@ class WritableCollection extends DAVResource { return false; } - global $tz_regex, $session, $caldav_context; + global $session, $caldav_context; $resources = $vcal->GetComponents('VTIMEZONE',false); // Not matching VTIMEZONE $user_no = $this->user_no(); @@ -179,18 +179,11 @@ class WritableCollection extends DAVResource { $calitem_params[':dtstamp'] = $dtstamp; $class = $first->GetPValue('CLASS'); - /* Check and see if we should over ride the class. */ - /** @todo is there some way we can move this out of this function? Or at least get rid of the need for the SQL query here. */ - if ( public_events_only($user_no, $path) ) { - $class = 'PUBLIC'; - } - /* * It seems that some calendar clients don't set a class... - * RFC2445, 4.8.1.3: - * Default is PUBLIC + * RFC2445, 4.8.1.3: Default is PUBLIC */ - if ( !isset($class) || $class == '' ) { + if ( $this->IsPublicOnly() || !isset($class) || $class == '' ) { $class = 'PUBLIC'; } $calitem_params[':class'] = $class; @@ -202,19 +195,11 @@ class WritableCollection extends DAVResource { $tz = $vcal->GetTimeZone($tzid); $olson = $vcal->GetOlsonName($tz); - dbg_error_log( 'PUT', ' Using TZID[%s] and location of [%s]', $tzid, (isset($olson) ? $olson : '') ); - if ( !empty($olson) && ($olson != $last_olson) && preg_match( $tz_regex, $olson ) ) { + if ( !empty($olson) && ($olson != $last_olson) ) { dbg_error_log( 'PUT', ' Setting timezone to %s', $olson ); $qry->QDo('SET TIMEZONE TO \''.$olson."'" ); $last_olson = $olson; } - $params = array( ':tzid' => $tzid); - $qry = new AwlQuery('SELECT 1 FROM timezones WHERE tzid = :tzid', $params ); - if ( $qry->Exec('PUT',__LINE__,__FILE__) && $qry->rows() == 0 ) { - $params[':olson_name'] = $olson; - $params[':vtimezone'] = (isset($tz) ? $tz->Render() : null ); - $qry->QDo('INSERT INTO timezones (tzid, olson_name, active, vtimezone) VALUES(:tzid,:olson_name,false,:vtimezone)', $params ); - } } $created = $first->GetPValue('CREATED'); @@ -258,8 +243,8 @@ EOSQL; } if ( !$this->IsSchedulingCollection() ) { - write_alarms($dav_id, $first); - write_attendees($dav_id, $vcal); + $this->WriteCalendarAlarms($dav_id, $vcal); + $this->WriteCalendarAttendees($dav_id, $vcal); if ( $log_action && function_exists('log_caldav_action') ) { log_caldav_action( $put_action_type, $first->GetPValue('UID'), $user_no, $collection_id, $path ); } @@ -317,4 +302,144 @@ EOSQL; return $segment_name; } + + /** + * Given a dav_id and an original vCalendar, pull out each of the VALARMs + * and write the values into the calendar_alarm table. + * + * @return null + */ + function WriteCalendarAlarms( $dav_id, vCalendar $vcal ) { + $qry = new AwlQuery('DELETE FROM calendar_alarm WHERE dav_id = '.$dav_id ); + $qry->Exec('PUT',__LINE__,__FILE__); + + $components = $vcal->GetComponents(); + + $qry->SetSql('INSERT INTO calendar_alarm ( dav_id, action, trigger, summary, description, component, next_trigger ) + VALUES( '.$dav_id.', :action, :trigger, :summary, :description, :component, + :related::timestamp with time zone + :related_trigger::interval )' ); + $qry->Prepare(); + foreach( $components AS $component ) { + if ( $component->GetType() == 'VTIMEZONE' ) continue; + $alarms = $component->GetComponents('VALARM'); + if ( count($alarms) < 1 ) return; + + foreach( $alarms AS $v ) { + $trigger = array_merge($v->GetProperties('TRIGGER')); + if ( $trigger == null ) continue; // Bogus data. + $trigger = $trigger[0]; + $related = null; + $related_trigger = '0M'; + $trigger_type = $trigger->GetParameterValue('VALUE'); + if ( !isset($trigger_type) || $trigger_type == 'DURATION' ) { + switch ( $trigger->GetParameterValue('RELATED') ) { + case 'DTEND': $related = $component->GetPValue('DTEND'); break; + case 'DUE': $related = $component->GetPValue('DUE'); break; + default: $related = $component->GetPValue('DTSTART'); + } + $duration = $trigger->Value(); + if ( !preg_match('{^-?P(:?\d+W)?(:?\d+D)?(:?T(:?\d+H)?(:?\d+M)?(:?\d+S)?)?$}', $duration ) ) continue; + $minus = (substr($duration,0,1) == '-'); + $related_trigger = trim(preg_replace( '#[PT-]#', ' ', $duration )); + if ( $minus ) { + $related_trigger = preg_replace( '{(\d+[WDHMS])}', '-$1 ', $related_trigger ); + } + else { + $related_trigger = preg_replace( '{(\d+[WDHMS])}', '$1 ', $related_trigger ); + } + } + else { + if ( false === strtotime($trigger->Value()) ) continue; // Invalid date. + } + $qry->Bind(':action', $v->GetPValue('ACTION')); + $qry->Bind(':trigger', $trigger->Render()); + $qry->Bind(':summary', $v->GetPValue('SUMMARY')); + $qry->Bind(':description', $v->GetPValue('DESCRIPTION')); + $qry->Bind(':component', $v->Render()); + $qry->Bind(':related', $related ); + $qry->Bind(':related_trigger', $related_trigger ); + $qry->Exec('PUT',__LINE__,__FILE__); + } + } + } + + + /** + * Parse out the attendee property and write a row to the + * calendar_attendee table for each one. + * @param int $dav_id The dav_id of the caldav_data we're processing + * @param vComponent The VEVENT or VTODO containing the ATTENDEEs + * @return null + */ + function WriteCalendarAttendees( $dav_id, vCalendar $vcal ) { + $qry = new AwlQuery('DELETE FROM calendar_attendee WHERE dav_id = '.$dav_id ); + $qry->Exec('PUT',__LINE__,__FILE__); + + $attendees = $vcal->GetAttendees(); + if ( count($attendees) < 1 ) return; + + $qry->SetSql('INSERT INTO calendar_attendee ( dav_id, status, partstat, cn, attendee, role, rsvp, property ) + VALUES( '.$dav_id.', :status, :partstat, :cn, :attendee, :role, :rsvp, :property )' ); + $qry->Prepare(); + $processed = array(); + foreach( $attendees AS $v ) { + $attendee = $v->Value(); + if ( isset($processed[$attendee]) ) { + dbg_error_log( 'LOG', 'Duplicate attendee "%s" in resource "%d"', $attendee, $dav_id ); + dbg_error_log( 'LOG', 'Original: "%s"', $processed[$attendee] ); + dbg_error_log( 'LOG', 'Duplicate: "%s"', $v->Render() ); + continue; /** @todo work out why we get duplicate ATTENDEE on one VEVENT */ + } + $qry->Bind(':attendee', $attendee ); + $qry->Bind(':status', $v->GetParameterValue('STATUS') ); + $qry->Bind(':partstat', $v->GetParameterValue('PARTSTAT') ); + $qry->Bind(':cn', $v->GetParameterValue('CN') ); + $qry->Bind(':role', $v->GetParameterValue('ROLE') ); + $qry->Bind(':rsvp', $v->GetParameterValue('RSVP') ); + $qry->Bind(':property', $v->Render() ); + $qry->Exec('PUT',__LINE__,__FILE__); + $processed[$attendee] = $v->Render(); + } + } + + /** + * Writes the data to a member in the collection and returns the segment_name of the + * resource in our internal namespace. + * + * @param vCalendar $member_dav_name The path to the resource to be deleted. + * @return boolean Success is true, or false on failure. + */ + function actualDeleteCalendarMember( $member_dav_name ) { + global $session, $caldav_context; + + // A quick sanity check... + $segment_name = str_replace( $this->dav_name(), '', $member_dav_name ); + if ( strstr($segment_name, '/') !== false ) { + @dbg_error_log( "DELETE", "DELETE: Refused to delete member '%s' from calendar '%s'!", $member_dav_name, $this->dav_name() ); + return false; + } + + // We need to serialise access to this process just for this collection + $cache = getCacheInstance(); + $myLock = $cache->acquireLock('collection-'.$this->dav_name()); + + $qry = new AwlQuery(); + $params = array( ':dav_name' => $member_dav_name ); + + if ( $qry->QDo("SELECT write_sync_change(collection_id, 404, caldav_data.dav_name) FROM caldav_data WHERE dav_name = :dav_name", $params ) + && $qry->QDo("DELETE FROM property WHERE dav_name = :dav_name", $params ) + && $qry->QDo("DELETE FROM locks WHERE dav_name = :dav_name", $params ) + && $qry->QDo("DELETE FROM caldav_data WHERE dav_name = :dav_name", $params ) ) { + @dbg_error_log( "DELETE", "DELETE: Calendar member %s deleted from calendar '%s'", $member_dav_name, $this->dav_name() ); + + $cache->releaseLock($myLock); + + return true; + } + + $cache->releaseLock($myLock); + return false; + + } + } diff --git a/inc/caldav-DELETE.php b/inc/caldav-DELETE.php index fddb3b24..1029816f 100644 --- a/inc/caldav-DELETE.php +++ b/inc/caldav-DELETE.php @@ -17,6 +17,7 @@ $container->NeedPrivilege('DAV::unbind'); $lock_opener = $request->FailIfLocked(); +require_once('schedule-functions.php'); function delete_collection( $id ) { $params = array( ':collection_id' => $id ); @@ -72,12 +73,14 @@ else { $request->DoResponse( 412, translate("Resource has changed on server - not deleted") ); } - $params = array( ':dav_id' => $dav_resource->resource_id() ); - + // Check to see if we need to do any scheduling transactions for this one. + do_scheduling_for_delete($dav_resource); + // We need to serialise access to this process just for this collection $cache = getCacheInstance(); $myLock = $cache->acquireLock('collection-'.$dav_resource->parent_path()); + $params = array( ':dav_id' => $dav_resource->resource_id() ); if ( $qry->QDo("SELECT write_sync_change(collection_id, 404, caldav_data.dav_name) FROM caldav_data WHERE dav_id = :dav_id", $params ) && $qry->QDo("DELETE FROM property WHERE dav_name = (SELECT dav_name FROM caldav_data WHERE dav_id = :dav_id)", $params ) && $qry->QDo("DELETE FROM locks WHERE dav_name = (SELECT dav_name FROM caldav_data WHERE dav_id = :dav_id)", $params ) @@ -92,7 +95,6 @@ else { $request->DoResponse( 204 ); } $cache->releaseLock($myLock); - } $request->DoResponse( 500 ); diff --git a/inc/schedule-functions.php b/inc/schedule-functions.php new file mode 100644 index 00000000..9553941c --- /dev/null +++ b/inc/schedule-functions.php @@ -0,0 +1,310 @@ + + * @copyright Morphoss Ltd - http://www.morphoss.com/ + * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later version + */ + +require_once('vCalendar.php'); +require_once('WritableCollection.php'); +require_once('RRule-v2.php'); + +/** + * Entry point for scheduling on DELETE, for which there are thee outcomes: + * - We don't do scheduling (disabled, no organizer, ...) + * - We are an ATTENDEE declining the meeting. + * - We are the ORGANIZER canceling the meeting. + * + * @param DAVResource $deleted_resource The resource which has already been deleted + */ +function do_scheduling_for_delete(DAVResource $deleted_resource ) { + // By the time we arrive here the resource *has* actually been deleted from disk + // we can only fail to (de-)schedule the activity... + global $request, $c; + + if ( !isset($request) || (isset($c->enable_auto_schedule) && !$c->enable_auto_schedule) ) return true; + if ( $deleted_resource->IsInSchedulingCollection() ) return true; + + $caldav_data = $deleted_resource->GetProperty('dav-data'); + if ( empty($caldav_data) ) return true; + + $vcal = new vCalendar($caldav_data); + $organizer = $vcal->GetOrganizer(); + if ( $organizer === false || empty($organizer) ) { + dbg_error_log( 'schedule', 'Event has no organizer - no scheduling required.' ); + return true; + } + if ( $vcal->GetScheduleAgent() != 'SERVER' ) { + dbg_error_log( 'schedule', 'SCHEDULE-AGENT=%s - no scheduling required.', $vcal->GetScheduleAgent() ); + return true; + } + $organizer_email = preg_replace( '/^mailto:/i', '', $organizer->Value() ); + + if ( $request->principal->email() == $organizer_email ) { + return doItipOrganizerCancel( $vcal ); + } + else { + if ( isset($_SERVER['HTTP_SCHEDULE_REPLY']) && $_SERVER['HTTP_SCHEDULE_REPLY'] == 'F') { + dbg_error_log( 'schedule', 'Schedule-Request header set to "F" - no scheduling required.' ); + return true; + } + return doItipAttendeeReply( $vcal, 'DECLINED', $request->principal->email()); + } + +} + + +/** +* Do the scheduling adjustments for a REPLY when an ATTENDEE updates their status. +* @param vCalendar $vcal The resource that the ATTENDEE is writing to their calendar +* @param string $organizer The property which is the event ORGANIZER. +*/ +//function do_scheduling_reply( vCalendar $vcal, vProperty $organizer ) { +function doItipAttendeeReply( vCalendar $resource, $partstat ) { + global $request; + + $organizer = $resource->GetOrganizer(); + $organizer_email = preg_replace( '/^mailto:/i', '', $organizer->Value() ); + $organizer_principal = new Principal('email',$organizer_email ); + + $sql = 'SELECT caldav_data.dav_name, caldav_data.caldav_data FROM caldav_data JOIN calendar_item USING(dav_id) '; + $sql .= 'WHERE caldav_data.collection_id IN (SELECT collection_id FROM collection WHERE is_calendar AND user_no =?) '; + $sql .= 'AND uid=? LIMIT 1'; + $uids = $resource->GetPropertiesByPath('/VCALENDAR/*/UID'); + if ( count($uids) == 0 ) { + dbg_error_log( 'schedule', 'No UID in VCALENDAR - giving up on REPLY.' ); + return true; + } + $uid = $uids[0]->Value(); + $qry = new AwlQuery($sql,$organizer_principal->user_no(), $uid); + if ( !$qry->Exec('schedule',__LINE__,__FILE__) || $qry->rows() < 1 ) { + dbg_error_log( 'schedule', 'Could not find original event from organizer - giving up on REPLY.' ); + return true; + } + $row = $qry->Fetch(); + $collection_path = preg_replace('{/[^/]+$}', '/', $row->dav_name ); + $segment_name = str_replace($collection_path, '', $row->dav_name ); + $vcal = new vCalendar($row->caldav_data); + + $attendees = $vcal->GetAttendees(); + foreach( $attendees AS $v ) { + $email = preg_replace( '/^mailto:/i', '', $v->Value() ); + if ( $email == $request->principal->email() ) { + $attendee = $v; + break; + } + } + if ( empty($attendee) ) { + dbg_error_log( 'schedule', 'Could not find ATTENDEE in VEVENT - giving up on REPLY.' ); + return true; + } + + $attendee->SetParameterValue('PARTSTAT', $partstat); + $attendee->SetParameterValue('SCHEDULE-STATUS', '2.0'); + $vcal->UpdateAttendeeStatus($request->principal->email(), clone($attendee) ); + + $organizer_calendar = new WritableCollection(array('path' => $collection_path)); + $organizer_inbox = new WritableCollection(array('path' => $organizer_principal->internal_url('schedule-inbox'))); + + $schedule_reply = GetItip(new vCalendar($row->caldav_data),'REPLY',$attendee->Value()); + $schedule_request = GetItip(new vCalendar($row->caldav_data),'REQUEST',null); + + dbg_error_log( 'schedule', 'Writing ATTENDEE scheduling REPLY from %s to %s', $request->principal->email(), $organizer_principal->email() ); + + $response = '3.7'; // Organizer was not found on server. + if ( !$organizer_calendar->Exists() ) { + dbg_error_log('ERROR','Default calendar at "%s" does not exist for user "%s"', + $organizer_calendar->dav_name(), $schedule_target->username()); + $response = '5.2'; // No scheduling support for user + } + else { + if ( ! $organizer_inbox->HavePrivilegeTo('schedule-deliver-reply') ) { + $response = '3.8'; // No authority to deliver replies to organizer. + } + $response = '1.2'; // Scheduling reply delivered successfully + if ( $organizer_calendar->WriteCalendarMember($vcal, false, false, $segment_name) === false ) { + dbg_error_log('ERROR','Could not write updated calendar member to %s', $attendee_calendar->dav_name() ); + trace_bug('Failed to write scheduling resource.'); + } + $organizer_inbox->WriteCalendarMember($schedule_reply, false, false, $request->principal->username().$segment_name); + } + + + dbg_error_log( 'schedule', 'Status for organizer <%s> set to "%s"', $organizer->Value(), $response ); + $organizer->SetParameterValue( 'SCHEDULE-STATUS', $response ); + $resource->UpdateOrganizerStatus($organizer); // Which was passed in by reference, and we're updating it here. + + // Now we loop through the *other* ATTENDEEs, updating them on the status of the ATTENDEE DECLINE/ACCEPT + foreach( $attendees AS $attendee ) { + $email = preg_replace( '/^mailto:/i', '', $attendee->Value() ); + if ( $email == $request->principal->email() || $email == $organizer_principal->email() ) continue; + + $agent = $attendee->GetParameterValue('SCHEDULE-AGENT'); + if ( !empty($agent) && $agent != 'SERVER' ) continue; + + $schedule_target = new Principal('email',$email); + if ( $schedule_target->Exists() ) { + $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar'))); + if ( !$attendee_calendar->Exists() ) { + dbg_error_log('ERROR','Default calendar at "%s" does not exist for user "%s"', + $attendee_calendar->dav_name(), $schedule_target->username()); + continue; + } + else { + $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox'))); + if ( ! $attendee_inbox->HavePrivilegeTo('schedule-deliver-invite') ) continue; + + if ( $attendee_calendar->WriteCalendarMember($vcal, false) === false ) { + dbg_error_log('ERROR','Could not write updated calendar member to %s', $attendee_calendar->dav_name()); + trace_bug('Failed to write scheduling resource.'); + } + $attendee_inbox->WriteCalendarMember($schedule_request, false); + } + } + } + + return true; +} + +function GetItip( VCalendar $vcal, $method, $attendee_value ) { + + $iTIP = $vcal->GetItip($method, $attendee_value ); + $iTIP->AddProperty('REQUEST-STATUS','2.0'); + $components = $iTIP->GetComponents(); + foreach( $components AS $comp ) { + $properties = array(); + foreach( $comp->GetProperties() AS $k=> $property ) { + switch( $property->Name() ) { + case 'DTSTART': + case 'DTEND': + case 'DUE': + $when = new RepeatRuleDateTime($property); + $properties[] = new vProperty( $property->Name() . ":" . $when->UTC() ); + break; + default: + $properties[] = $property; + } + } + $comp->SetProperties($properties); + } + + return $iTIP; +} + +/** + * Handles sending the iTIP CANCEL messages to each ATTENDEE by the ORGANIZER. + * @param vCalendar $vcal What's being cancelled. + */ +function doItipOrganizerCancel( vCalendar $vcal ) { + global $request; + + $attendees = $vcal->GetAttendees(); + if ( count($attendees) == 0 && count($old_attendees) == 0 ) { + dbg_error_log( 'schedule', 'Event has no attendees - no scheduling required.', count($attendees) ); + return true; + } + + dbg_error_log( 'schedule', 'Writing scheduling resources for %d attendees', count($attendees) ); + $scheduling_actions = false; + + $iTIP = GetItip($vcal, 'CANCEL', null); + + foreach( $attendees AS $attendee ) { + $email = preg_replace( '/^mailto:/i', '', $attendee->Value() ); + if ( $email == $request->principal->email() ) { + dbg_error_log( 'schedule', "not delivering to owner '%s'", $request->principal->email() ); + continue; + } + + $agent = $attendee->GetParameterValue('SCHEDULE-AGENT'); + if ( $agent && $agent != 'SERVER' ) { + dbg_error_log( 'schedule', "not delivering to %s, schedule agent set to value other than server", $email ); + continue; + } + $schedule_target = new Principal('email',$email); + if ( !$schedule_target->Exists() ) { + $response = '3.7'; + } + else { + $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox'))); + if ( ! $attendee_inbox->HavePrivilegeTo('schedule-deliver-invite') ) { + dbg_error_log( 'schedule', "No authority to deliver invite to %s", $schedule_target->internal_url('schedule-inbox') ); + $response = '3.8'; + } + else { + $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar'))); + $response = processItipCancel( $vcal, $attendee, $attendee_calendar, $schedule_target ); + deliverItipCancel( $iTIP, $attendee, $attendee_inbox ); + } + } + dbg_error_log( 'schedule', 'Status for attendee <%s> set to "%s"', $attendee->Value(), $response ); + $attendee->SetParameterValue( 'SCHEDULE-STATUS', $response ); + $scheduling_actions = true; + } + + return true; +} + +/** + * Does the actual processing of the iTIP CANCEL message on behalf of an ATTENDEE, + * which generally means writing it into the ATTENDEE's default calendar. + * + * @param vCalendar $vcal The message. + * @param vProperty $attendee + * @param WritableCollection $attendee_calendar + */ +function processItipCancel( vCalendar $vcal, vProperty $attendee, WritableCollection $attendee_calendar, Principal $attendee_principal ) { + + dbg_error_log( 'schedule', 'Processing iTIP CANCEL to %s', $attendee->Value()); + if ( !$attendee_calendar->Exists() ) { + dbg_error_log('ERROR', 'Default calendar at "%s" does not exist for attendee "%s"', + $attendee_calendar->dav_name(), $attendee->Value()); + return '5.2'; // No scheduling support for user + } + + $sql = 'SELECT caldav_data.dav_name FROM caldav_data JOIN calendar_item USING(dav_id) '; + $sql .= 'WHERE caldav_data.collection_id IN (SELECT collection_id FROM collection WHERE is_calendar AND user_no =?) '; + $sql .= 'AND uid=? LIMIT 1'; + $uids = $vcal->GetPropertiesByPath('/VCALENDAR/*/UID'); + if ( count($uids) == 0 ) { + dbg_error_log( 'schedule', 'No UID in VCALENDAR - giving up on CANCEL processing.' ); + return '3.8'; + } + $uid = $uids[0]->Value(); + $qry = new AwlQuery($sql, $attendee_principal->user_no(), $uid); + if ( !$qry->Exec('schedule',__LINE__,__FILE__) || $qry->rows() < 1 ) { + dbg_error_log( 'schedule', 'Could not find ATTENDEE copy of original event - not trying to DELETE it!' ); + return '1.2'; + } + $row = $qry->Fetch(); + + if ( $attendee_calendar->actualDeleteCalendarMember($row->dav_name) === false ) { + dbg_error_log('ERROR', 'Could not delete calendar member %s for %s', + $row->dav_name(), $attendee->Value()); + trace_bug('Failed to write scheduling resource.'); + return '5.2'; + } + + return '1.2'; // Scheduling invitation delivered successfully + +} + + +/** + * Delivers the iTIP CANCEL message to an ATTENDEE's Scheduling Inbox Collection. + * + * This is pretty simple at present, but could be extended in the future to do the sending + * of e-mail to a remote attendee. + * + * @param vCalendar $iTIP + * @param vProperty $attendee + * @param WritableCollection $attendee_inbox + */ +function deliverItipCancel( vCalendar $iTIP, vProperty $attendee, WritableCollection $attendee_inbox ) { + $attendee_inbox->WriteCalendarMember($iTIP, false); +} + diff --git a/testing/tests/scheduling/3026-PUT-Accept.result b/testing/tests/scheduling/3026-PUT-Accept.result index 9985afc7..73ec3062 100644 --- a/testing/tests/scheduling/3026-PUT-Accept.result +++ b/testing/tests/scheduling/3026-PUT-Accept.result @@ -29,16 +29,16 @@ BEGIN:VEVENT CREATED:20111018T195845Z UID:E1A13F04-iCal-schedule DTEND;TZID=Pacific/Auckland:20111019T110000 -ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: - mailto:manager1@example.net -ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; - PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:user1@example.net TRANSP:OPAQUE SUMMARY:Meeting with User1 DTSTART;TZID=Pacific/Auckland:20111019T100000 DTSTAMP:20111018T200107Z ORGANIZER;CN="Manager 1":mailto:manager1@example.net SEQUENCE:5 +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:user1@example.net END:VEVENT END:VCALENDAR < @@ -118,16 +118,16 @@ BEGIN:VEVENT CREATED:20111018T195845Z UID:E1A13F04-iCal-schedule DTEND;TZID=Pacific/Auckland:20111019T110000 -ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: - mailto:manager1@example.net -ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; - PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:user1@example.net TRANSP:OPAQUE SUMMARY:Meeting with User1 DTSTART;TZID=Pacific/Auckland:20111019T100000 DTSTAMP:20111018T200107Z ORGANIZER;CN="Manager 1":mailto:manager1@example.net SEQUENCE:5 +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:user1@example.net END:VEVENT END:VCALENDAR < diff --git a/testing/tests/scheduling/3027-PUT-iCal-with-attendees.result b/testing/tests/scheduling/3027-PUT-iCal-with-attendees.result index 5c2adf11..707c4729 100644 --- a/testing/tests/scheduling/3027-PUT-iCal-with-attendees.result +++ b/testing/tests/scheduling/3027-PUT-iCal-with-attendees.result @@ -127,16 +127,16 @@ BEGIN:VEVENT CREATED:20111018T195845Z UID:E1A13F04-iCal-schedule DTEND;TZID=Pacific/Auckland:20111019T110000 -ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: - mailto:manager1@example.net -ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; - PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:user1@example.net TRANSP:OPAQUE SUMMARY:Meeting with User1 DTSTART;TZID=Pacific/Auckland:20111019T100000 DTSTAMP:20111018T200107Z ORGANIZER;CN="Manager 1":mailto:manager1@example.net SEQUENCE:5 +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPANT:mailto:user1@example.net END:VEVENT END:VCALENDAR < diff --git a/testing/tests/scheduling/3027-PUT-iCal-with-attendees.test b/testing/tests/scheduling/3027-PUT-iCal-with-attendees.test index c9fce207..d06a4b8d 100644 --- a/testing/tests/scheduling/3027-PUT-iCal-with-attendees.test +++ b/testing/tests/scheduling/3027-PUT-iCal-with-attendees.test @@ -5,7 +5,7 @@ TYPE=PUT URL=http://regression.host/caldav.php/manager1/home/E1A13F04-iCal-schedule.ics HEADER=Content-Type: text/calendar HEADER=DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) -HEADER=If-Match: "87421a4ff0b84a95a31db428ee6d11d9" +HEADER=If-Match: "d60f8959edc5eee6e949a2e5b81dd746" HEAD AUTH=manager1:manager1 diff --git a/testing/tests/scheduling/3028-DELETE-reply.result b/testing/tests/scheduling/3028-DELETE-reply.result new file mode 100644 index 00000000..b9b5f27b --- /dev/null +++ b/testing/tests/scheduling/3028-DELETE-reply.result @@ -0,0 +1,14 @@ +HTTP/1.1 204 No Content +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule +Content-Length: 0 +Content-Type: text/plain; charset="utf-8" + + + dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< + + dav_name: >/user1/home/E1A13F04-iCal-schedule.ics< + + dav_name: >/manager1/.in/user1E1A13F04-iCal-schedule.ics< + diff --git a/testing/tests/scheduling/3028-DELETE-reply.test b/testing/tests/scheduling/3028-DELETE-reply.test new file mode 100644 index 00000000..6dcf874d --- /dev/null +++ b/testing/tests/scheduling/3028-DELETE-reply.test @@ -0,0 +1,18 @@ +# +# iCal DELETE's the invitation in the .in +# +TYPE=DELETE +URL=http://regression.host/user1/.in/E1A13F04-iCal-schedule.ics + +HEADER=User-Agent: DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) +HEAD + +# +# Query to confirm we got rid of it. There should be two now. +QUERY +SELECT dav_name + FROM calendar_item + WHERE uid = 'E1A13F04-iCal-schedule' + ORDER BY dav_id +ENDQUERY + diff --git a/testing/tests/scheduling/3029-DELETE-reply.result b/testing/tests/scheduling/3029-DELETE-reply.result new file mode 100644 index 00000000..798ba092 --- /dev/null +++ b/testing/tests/scheduling/3029-DELETE-reply.result @@ -0,0 +1,12 @@ +HTTP/1.1 204 No Content +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule +Content-Length: 0 +Content-Type: text/plain; charset="utf-8" + + + dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< + + dav_name: >/user1/home/E1A13F04-iCal-schedule.ics< + diff --git a/testing/tests/scheduling/3029-DELETE-reply.test b/testing/tests/scheduling/3029-DELETE-reply.test new file mode 100644 index 00000000..cac5837a --- /dev/null +++ b/testing/tests/scheduling/3029-DELETE-reply.test @@ -0,0 +1,20 @@ +# +# iCal DELETE's the invitation in the .in +# +TYPE=DELETE +URL=http://regression.host/manager1/.in/user1E1A13F04-iCal-schedule.ics + +HEADER=User-Agent: DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) +HEAD + +AUTH=manager1:manager1 + +# +# Query to confirm we got rid of it. There should be two now. +QUERY +SELECT dav_name + FROM calendar_item + WHERE uid = 'E1A13F04-iCal-schedule' + ORDER BY dav_id +ENDQUERY + diff --git a/testing/tests/scheduling/3030-DELETE-attendee-event.result b/testing/tests/scheduling/3030-DELETE-attendee-event.result new file mode 100644 index 00000000..0e514a6b --- /dev/null +++ b/testing/tests/scheduling/3030-DELETE-attendee-event.result @@ -0,0 +1,70 @@ +HTTP/1.1 204 No Content +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule +Content-Length: 0 +Content-Type: text/plain; charset="utf-8" + + + caldav_data: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:6 +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=DECLINED;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=2.0:mai + lto:user1@example.net +END:VEVENT +END:VCALENDAR +< + dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< + + caldav_data: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:REPLY +REQUEST-STATUS:2.0 +BEGIN:VEVENT +UID:E1A13F04-iCal-schedule +DTEND:20111019T010000Z +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user1@example.net +DTSTART:20111019T000000Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +DTSTAMP:20111102T010804Z +END:VEVENT +END:VCALENDAR +< + dav_name: >/manager1/.in/user1E1A13F04-iCal-schedule.ics< + diff --git a/testing/tests/scheduling/3030-DELETE-attendee-event.test b/testing/tests/scheduling/3030-DELETE-attendee-event.test new file mode 100644 index 00000000..3f7ec167 --- /dev/null +++ b/testing/tests/scheduling/3030-DELETE-attendee-event.test @@ -0,0 +1,23 @@ +# +# We now DELETE the ATTENDEE's copy of the actual event. +# - This should send a CANCEL reply and update the manager's +# event copy with the PARTSTAT=DECLINED +# +TYPE=DELETE +URL=http://regression.host/user1/home/E1A13F04-iCal-schedule.ics + +HEADER=User-Agent: DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) +HEAD + +# +# Query to confirm we got rid of it. There should be two now: +# - An event in the manager's calendar, with a PARTSTART=DECLINED for user 1 +# - An iTIP message in the managers's inbox. +QUERY +SELECT calendar_item.dav_name, + caldav_data.caldav_data + FROM calendar_item JOIN caldav_data USING(dav_id, dav_name) + WHERE uid = 'E1A13F04-iCal-schedule' + ORDER BY dav_id +ENDQUERY + diff --git a/testing/tests/scheduling/3031-DELETE-reply.test b/testing/tests/scheduling/3031-DELETE-reply.test new file mode 100644 index 00000000..8e423e19 --- /dev/null +++ b/testing/tests/scheduling/3031-DELETE-reply.test @@ -0,0 +1,21 @@ +# +# Now DELETE's the cancelation reply in the Manager's .in +# +TYPE=DELETE +URL=http://regression.host/manager1/.in/user1E1A13F04-iCal-schedule.ics + +HEADER=User-Agent: DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) +HEAD + +AUTH=manager1:manager1 + +# +# Query to confirm we got rid of it. There should only be one +# lonely meeting in the manager's calendar (which has been declined). +QUERY +SELECT dav_name + FROM calendar_item + WHERE uid = 'E1A13F04-iCal-schedule' + ORDER BY dav_id +ENDQUERY + diff --git a/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test b/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test new file mode 100644 index 00000000..6d24381b --- /dev/null +++ b/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test @@ -0,0 +1,73 @@ +# +# PUT an event with several attendees - so we can delete the organizer +# copy in the next request. +# +# After this we should see 7 events: 1 manager, 3 attendees, 3 attendee iTIP +# +TYPE=PUT +URL=http://regression.host/caldav.php/manager1/home/E1A13F04-iCal-schedule.ics +HEADER=Content-Type: text/calendar +HEADER=DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) +HEADER=If-Match: "651df94a71cc99384231637a5df101f4" +HEAD + +AUTH=manager1:manager1 + +BEGINDATA +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +ENDDATA + + + +QUERY +SELECT caldav_data.user_no, caldav_data.dav_name, + caldav_type, logged_user, caldav_data.caldav_data AS "vcalendar", + summary +FROM caldav_data JOIN calendar_item USING(dav_name) LEFT JOIN timezones ON (tz_id=tzid) +WHERE calendar_item.uid = 'E1A13F04-iCal-schedule' +ORDER BY caldav_data.dav_id +ENDQUERY + diff --git a/testing/tests/scheduling/3033-DELETE-organizer-event.test b/testing/tests/scheduling/3033-DELETE-organizer-event.test new file mode 100644 index 00000000..12b13916 --- /dev/null +++ b/testing/tests/scheduling/3033-DELETE-organizer-event.test @@ -0,0 +1,31 @@ +# +# We now DELETE the ORGANIZER's copy of the actual event. +# - This should send a CANCEL reply and remove each attendee's +# copy of the event +# +TYPE=DELETE +URL=http://regression.host/manager1/home/E1A13F04-iCal-schedule.ics + +HEADER=User-Agent: DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) +HEAD + +AUTH=manager1:manager1 + +# Before we run, this time we'll assume everyone has read their inbox +# and all existing iTIP messages are deleted. +DOSQL +DELETE FROM caldav_data WHERE dav_name ~ E'/\\.in/.*E1A13F04-iCal-schedule\\.ics' +ENDDOSQL + +# +# Query to confirm we got rid of it. There should be two now: +# - An event in the manager's calendar, with a PARTSTART=DECLINED for user 1 +# - An iTIP message in the managers's inbox. +QUERY +SELECT calendar_item.dav_name, + caldav_data.caldav_data + FROM calendar_item JOIN caldav_data USING(dav_id, dav_name) + WHERE uid = 'E1A13F04-iCal-schedule' + ORDER BY dav_id +ENDQUERY + From b3c873d2bb0eb8f28599fe2234654067d88a9637 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 10:15:32 +1300 Subject: [PATCH 07/13] Correct handling of empty CardDAV:address-data element in request. --- inc/caldav-REPORT-cardquery.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/caldav-REPORT-cardquery.php b/inc/caldav-REPORT-cardquery.php index 968919fd..4115ecd4 100644 --- a/inc/caldav-REPORT-cardquery.php +++ b/inc/caldav-REPORT-cardquery.php @@ -7,7 +7,8 @@ function get_address_properties( $address_data_xml ) { global $address_data_properties; $expansion = $address_data_xml->GetElements(); foreach( $expansion AS $k => $v ) { - $address_data_properties[strtoupper($v->GetAttribute('name'))] = true; + if ( $v instanceof XMLElement ) + $address_data_properties[strtoupper($v->GetAttribute('name'))] = true; } } From a2b3e2e8699f25ce8e395989f9b621d115839dcb Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 10:16:06 +1300 Subject: [PATCH 08/13] Regression tests for empty CardDAV:address-data element. --- .../2034-REPORT-addressbook-query.result | 47 +++++++++++++++++++ .../2034-REPORT-addressbook-query.test | 28 +++++++++++ 2 files changed, 75 insertions(+) create mode 100644 testing/tests/carddav/2034-REPORT-addressbook-query.result create mode 100644 testing/tests/carddav/2034-REPORT-addressbook-query.test diff --git a/testing/tests/carddav/2034-REPORT-addressbook-query.result b/testing/tests/carddav/2034-REPORT-addressbook-query.result new file mode 100644 index 00000000..9789156e --- /dev/null +++ b/testing/tests/carddav/2034-REPORT-addressbook-query.result @@ -0,0 +1,47 @@ + + + + /caldav.php/user1/addressbook/andrew_mcmillan.vcf + + + BEGIN:VCARD +VERSION:3.0 +REV:2010-03-29T09:23:34Z +UID:pas-id-4BB0719600000000 +X-SKYPE;X-EVOLUTION-UI-SLOT=1;TYPE=HOME:karora__ +X-JABBER;X-EVOLUTION-UI-SLOT=3;TYPE=HOME:karora@irc.oftc.net +TEL;X-EVOLUTION-UI-SLOT=3;TYPE=CELL:+64 22 123 4567 +TEL;X-EVOLUTION-UI-SLOT=2;TYPE=HOME,VOICE:+64 4 123 4567 +TEL;X-EVOLUTION-UI-SLOT=1;TYPE=WORK,VOICE:+64 22 123 4567 +EMAIL;X-EVOLUTION-UI-SLOT=2;TYPE=HOME:andrew@mcmillan.net.nz +EMAIL;X-EVOLUTION-UI-SLOT=1;TYPE=WORK:andrew@morphoss.com +LABEL;TYPE=HOME:16 Kaka Place\nPorikana\n4173\nNew Zealand +ADR;TYPE=HOME:;;16 Kaka Place;Porikana;;4173;New Zealand +X-MOZILLA-HTML:FALSE +X-EVOLUTION-VIDEO-URL: +FBURL:https://davical.morphoss.com/freebusy.php/andrew@morphoss.com +CALADRURI:mailto:andrew@morphoss.com +CALURI:https://dotcal.com/karora +X-EVOLUTION-BLOG-URL:http://andrew.mcmillan.net.nz/ +CATEGORIES:Developer,Personal,Debian, +X-EVOLUTION-FILE-AS:McMillan\, Andrew +N:McMillan;Andrew;Watson;; +FN:Andrew Watson McMillan +NOTE:Primary author of DAViCal CalDAV Server. +X-EVOLUTION-SPOUSE:Heather Buchanan +X-EVOLUTION-ANNIVERSARY:1989-04-22 +BDAY:1958-07-26 +NICKNAME:karora +X-EVOLUTION-ASSISTANT: +X-EVOLUTION-MANAGER: +ROLE:Geek +ORG:dotCal;;Porirua +TITLE:Chief Technology Officer +URL:http://andrew.mcmillan.net.nz/ +END:VCARD + + + HTTP/1.1 200 OK + + + diff --git a/testing/tests/carddav/2034-REPORT-addressbook-query.test b/testing/tests/carddav/2034-REPORT-addressbook-query.test new file mode 100644 index 00000000..b802eb93 --- /dev/null +++ b/testing/tests/carddav/2034-REPORT-addressbook-query.test @@ -0,0 +1,28 @@ +# +# Request a REPORT +# +TYPE=REPORT +URL=http://mycaldav/caldav.php/user1/addressbook/ + +HEADER=Accept: text/xml,application/xml +HEADER=Content-Type: text/xml +HEADER=Depth: 1 + +# HEAD + +BEGINDATA + + + + + + + + karora + + + +ENDDATA From c09341959184f3597e10791b17a4febb027b9941 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 17:19:39 +1300 Subject: [PATCH 09/13] Updated Polish translation from the friendly folk at Gdansk University of Technology. --- po/pl.po | 670 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 353 insertions(+), 317 deletions(-) diff --git a/po/pl.po b/po/pl.po index 66b933b0..00a84274 100644 --- a/po/pl.po +++ b/po/pl.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Andrew McMillan , 2011. # spasstl , 2011. @@ -10,8 +10,8 @@ msgstr "" "Project-Id-Version: DAViCal\n" "Report-Msgid-Bugs-To: http://repo.or.cz/w/davical.git/tree/HEAD:/issues\n" "POT-Creation-Date: 2011-10-24 21:19+1300\n" -"PO-Revision-Date: 2011-10-24 08:21+0000\n" -"Last-Translator: karora \n" +"PO-Revision-Date: 2011-10-25 12:29+0100\n" +"Last-Translator: Michał Nowakowski \n" "Language-Team: Polish (http://www.transifex.net/projects/p/davical/team/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -22,63 +22,65 @@ msgstr "" #. Translators: this is the formatting of a date with time. See #. http://php.net/manual/en/function.strftime.php msgid "%F %T" -msgstr "" +msgstr "%%x %%c" #. Translators: his is the formatting of just the time. See #. http://php.net/manual/en/function.strftime.php msgid "%T" -msgstr "" +msgstr "%%c" msgid "*** Default Locale ***" -msgstr "" +msgstr "*** Domyślny język ***" msgid "*** Unknown ***" -msgstr "" +msgstr "*** Nieznany ***" #, php-format msgid "- adding %s to group : %s" -msgstr "Dodaj %s do grupy: %s" +msgstr "- dodawanie %s do grupy: %s" #, php-format msgid "- adding users %s to group : %s" -msgstr "Dodaj Użytkownika %s do grupy: %s" +msgstr "- dodawanie użytkowników %s do grupy: %s" #, php-format msgid "- creating groups : %s" -msgstr "" +msgstr "- tworzenie grup : %s" #, php-format msgid "- creating record for users : %s" -msgstr "" +msgstr "- tworzenie rekordów dla użytkowników : %s" #, php-format msgid "- deactivate groups : %s" -msgstr "" +msgstr "- nieaktywne grupy : %s" #, php-format msgid "- deactivating users : %s" -msgstr "" +msgstr "- nieaktywni użytkownicy : %s" #, php-format msgid "- nothing done on : %s" -msgstr "" +msgstr "- nie wykonano żadnych operacji na : %s" #, php-format msgid "- removing %s from group : %s" -msgstr "" +msgstr "- usuwanie %s z grupy : %s" #, php-format msgid "- updating groups : %s" -msgstr "" +msgstr "- aktualizacja grup : %s" #, php-format msgid "- updating user records : %s" -msgstr "" +msgstr "- aktualizacja użytkownika : %s" msgid "" "WARNING: all events in this path will be deleted before inserting allof " "the ics file" msgstr "" +"OSTRZEŻENIE: wszystkie zdarzenia w tej ścieżce zostaną usunięte przed " +"wstawieniem całości pliku ics" #, php-format msgid "" @@ -91,6 +93,13 @@ msgid "" "

    The mailing list\n" "archives can be helpful too.

    " msgstr "" +"

    Pomoc

    \n" +"

    W celu uzyskania wstępnej pomocy, odwiedź stronę domową DAViCala\n" +"lub zerknij do Wiki DAViCala.

    \n" +"

    Jeśli nie możesz tam znaleźć odpowiedzi, odwiedź nasz kanał IRC-owy,\n" +"#davical na serwerze irc.oftc.net,\n" +"lub wyślij pytanie na listę dyskusyjna użytkowników DAViCala.

    \n" +"

    Być może warto będzie się też zapoznać z .

    " #, php-format msgid "" @@ -106,19 +115,19 @@ msgid "A DAViCal principal collection may only contain collections" msgstr "" msgid "A collection already exists at that location." -msgstr "Zbiór już istnieje w tej lokalizacji." +msgstr "Zbiór w tym miejscu już istnieje." msgid "A resource already exists at the destination." -msgstr "" +msgstr "Zasób w tym miejscu już istnieje." msgid "AWL Library version " -msgstr "" +msgstr "Wersja biblioteki AWL" msgid "Access Tickets" -msgstr "" +msgstr "Kody dostępu" msgid "Access ticket deleted" -msgstr "" +msgstr "Kod dostępu usunięty" msgid "Action" msgstr "Akcja" @@ -127,7 +136,7 @@ msgid "Active" msgstr "Aktywny" msgid "Adding new member to this Group Principal" -msgstr "" +msgstr "Dodawanie nowego członka do tej grupy" #. Translators: in the sense of 'systems admin' msgid "Admin" @@ -140,21 +149,22 @@ msgid "Administrator" msgstr "Administrator" msgid "All" -msgstr "" +msgstr "Wszystkie" msgid "All collection data will be unrecoverably deleted." -msgstr "" +msgstr "Zbiór zostanie bezpowrotnie usunięty." #, php-format msgid "All events of user \"%s\" were deleted and replaced by those from file %s" -msgstr "" +msgstr "Wszystkie zdarzenia użytkownika \"%s\" zostały usunięte i zastąpione zdarzeniami z pliku %s" msgid "" "All of the principal's calendars and events will be unrecoverably deleted." msgstr "" +"Wszystkie zdarzenia i kalendarze tego podmiotu zostaną bezpowrotnie usunięte." msgid "All privileges" -msgstr "" +msgstr "Wszystkie uprawnienia" msgid "All requested changes were made." msgstr "Wszystkie zażądane zmiany zostały wprowadzone" @@ -162,45 +172,46 @@ msgstr "Wszystkie zażądane zmiany zostały wprowadzone" msgid "" "Allow free/busy enquiries targeted at the owner of this scheduling inbox" msgstr "" +"Zezwól na zapytania o wolny/zajęty właściciela tej skrzynki" msgid "An \"Administrator\" user has full rights to the whole DAViCal System" -msgstr "" +msgstr "Użytkownik \"Administrator\" ma pełne prawa dostępu do wszystkich zasobów DAViCala" msgid "Anonymous users are not allowed to modify calendars" -msgstr "" +msgstr "Użytkownicy anonimowi nie mogą modyfikować kalendarzy" msgid "Anonymous users may only access public calendars" -msgstr "" +msgstr "Użytkownicy anonimowi mają dostęp tylko do kalendarzy publicznych" msgid "Application DB User" -msgstr "" +msgstr "Użytkownik (aplikacji) bazy danych" msgid "Apply Changes" -msgstr "" +msgstr "Zastosuj" msgid "Apply DB Patches" -msgstr "" +msgstr "Nałóż poprawki na bazę danych" msgid "Attachment" -msgstr "" +msgstr "Załącznik" msgid "Binding deleted" -msgstr "" +msgstr "Usunięto powiązania." msgid "Bindings to other collections" -msgstr "" +msgstr "Powiązania z innymi zbiorami" msgid "Bindings to this Collection" -msgstr "" +msgstr "Powiązania z tym zbiorem" msgid "Bindings to this Principal's Collections" -msgstr "" +msgstr "Powiązania wszystkich zbiorów podmiotu" msgid "Body contains no XML data!" -msgstr "" +msgstr "Treść nie zawiera danych XML!" msgid "Bound As" -msgstr "" +msgstr "Powiązane jako" msgid "Browse all users" msgstr "Przeglądaj wszystkich użytkowników" @@ -210,214 +221,216 @@ msgstr "Zajęty" #, php-format msgid "Calendar \"%s\" was loaded from file." -msgstr "Kalendarz @%s@ władowny z pliku" +msgstr "Kalendarz \"%s\" został załadowany z pliku" msgid "Calendar Principals" -msgstr "" +msgstr "Podmioty kalendarza" msgid "Calendar Timezone" -msgstr "" +msgstr "Strefa czasowa kalendarza" msgid "Can only add tickets for existing collection paths which you own" -msgstr "" +msgstr "Można dodać kody dostępowe tylko dla ścieżek, które istnieją i są twoje." msgid "Categories" -msgstr "" +msgstr "Kategorie" msgid "Change Password" -msgstr "" +msgstr "Zmień hasło" msgid "Click to display user details" -msgstr "Kliknij aby wyświetlić dane użytkownika" +msgstr "Kliknij aby wyświetlić informacje o użytkowniku" msgid "Click to edit principal details" -msgstr "" +msgstr "Kliknij, by edytować dane podmiotu" msgid "Collection" -msgstr "" +msgstr "Zbiór" msgid "Collection Grants" -msgstr "" +msgstr "Zezwolenia na dostęp do zbioru" msgid "Collection ID" -msgstr "" +msgstr "ID Zbioru" msgid "Collection deleted" -msgstr "" +msgstr "Zbiór został usunięty." msgid "" "Collections may not be both CalDAV calendars and CardDAV addressbooks at the" " same time" msgstr "" +"Zbiór nie może być jednocześnie kalendarzem CalDAV i książką adresową CardDAV." msgid "Configuring Calendar Clients for DAViCal" -msgstr "" +msgstr "Konfiguracja klientów kalendarzowych dla DAViCala" msgid "Configuring DAViCal" -msgstr "" +msgstr "Konfiguracja DAViCala" msgid "Confirm" msgstr "Potwierdź" msgid "Confirm Deletion of the Binding" -msgstr "" +msgstr "Potwierdź usunięcie powiązania" msgid "Confirm Deletion of the Collection" -msgstr "" +msgstr "Potwierdź usunięcie zbioru" msgid "Confirm Deletion of the Principal" -msgstr "" +msgstr "Potwierdź usunięcie podmiotu" msgid "Confirm Deletion of the Ticket" -msgstr "" +msgstr "Potwierdź usunięcie kodu dostępu" msgid "Confirm Password" -msgstr "" +msgstr "Potwierdź hasło" msgid "Confirm the new password." msgstr "Potwierdź nowe hasło" msgid "Could not retrieve" -msgstr "" +msgstr "Nie udało się pobrać" msgid "Create" msgstr "Utwórz" msgid "Create Collection" -msgstr "" +msgstr "Utwórz zbiór" msgid "Create Events/Collections" -msgstr "" +msgstr "Tworzenie zbiorów/zdarzeń" msgid "Create New Collection" -msgstr "" +msgstr "Utwórz nowy zbiór" msgid "Create New Principal" -msgstr "" +msgstr "Utwórz nowy podmiot" msgid "Create Principal" -msgstr "" +msgstr "Tworzenie podmiotu" msgid "Create a new principal (i.e. a new user, resource or group)" -msgstr "" +msgstr "Tworzy nowy podmiot (tzn. użytkownika, zasób lub grupę)" msgid "Create a resource or collection" -msgstr "" +msgstr "Utwórz zasób lub zbiór" msgid "Creating new Collection." -msgstr "" +msgstr "Tworzenie nowego zbioru." msgid "Creating new Principal record." -msgstr "" +msgstr "Tworzenie nowego rekordu podmiotu." msgid "Creating new ticket granting privileges to this Principal" -msgstr "" +msgstr "Tworzenie nowego kodu dostępu dla tego podmiotu" msgid "Current DAViCal version " -msgstr "" +msgstr "Wersja DAViCala" msgid "DAV Path" -msgstr "" +msgstr "Ścieżka do zasobu DAV" msgid "" "DAV::resourcetype may only be set to a new value, it may not be removed." msgstr "" +"DAV::resourcetype może tylko otrzymać nową wartość, nie może zostać usunięty." msgid "DAViCal CalDAV Server" -msgstr "" +msgstr "Serwer CalDAV DAViCALa" msgid "DAViCal DB Schema version " -msgstr "" +msgstr "Wersja schematu bazy danych DAViCALa" msgid "DAViCal Homepage" -msgstr "" +msgstr "Strona domowa DAViCala" msgid "DAViCal Wiki" -msgstr "" +msgstr "Wiki DAViCala" msgid "DAViCal only allows BIND requests for collections at present." -msgstr "" +msgstr "DaviCAL aktualnie obsługuje tylko żądania BIND dla zbiorów." msgid "DKIM signature invalid " -msgstr "" +msgstr "Błędny podpis DKIM" msgid "DKIM signature missing" -msgstr "" +msgstr "Brak podpisu DKIM" msgid "DKIM signature validation failed(DNS ERROR)" -msgstr "" +msgstr "Błąd walidacji podpisu DKIM (błąd DNS)" msgid "DKIM signature validation failed(KEY Parse ERROR)" -msgstr "" +msgstr "Błąd walidacji podpisu DKIM (błąd parsowania klucza)" msgid "DKIM signature validation failed(KEY Validation ERROR)" -msgstr "" +msgstr "Błąd walidacji podpisu DKIM (błąd walidacji klucza)" msgid "DKIM signature validation failed(Signature verification ERROR)" -msgstr "" +msgstr "Błąd walidacji podpisu DKIM (błąd weryfikacji podpisu)" msgid "Database Error" msgstr "Błąd bazy danych" msgid "Database Host" -msgstr "" +msgstr "Host bazy danych" msgid "Database Name" -msgstr "" +msgstr "Nazwa bazy danych" msgid "Database Owner" -msgstr "" +msgstr "Właściciel bazy danych" msgid "Database Password" -msgstr "" +msgstr "Hasło do bazy danych" msgid "Database Port" -msgstr "" +msgstr "Port bazy danych" msgid "Database Username" -msgstr "" +msgstr "Użytkownik bazy danych" msgid "Database error" msgstr "Błąd bazy danych" msgid "Date Format Style" -msgstr "" +msgstr "Format daty" msgid "Date Style" msgstr "Format daty" msgid "Default Privileges" -msgstr "" +msgstr "Uprawnienia domyślne" msgid "Default relationships added." -msgstr "" +msgstr "Dodano domyślne zależności." msgid "Delete" msgstr "Usuń" msgid "Delete Events/Collections" -msgstr "" +msgstr "Usuń zasoby/zbiory" msgid "Delete Principal" -msgstr "" +msgstr "Usuń podmiot" msgid "Delete a resource or collection" -msgstr "" +msgstr "Usuń zasób lub zbiór" msgid "Deleted a grant from this Principal" -msgstr "" +msgstr "Cofnięto zezwolenie podmiotowi" msgid "Deleting Binding:" -msgstr "" +msgstr "Usuwanie powiązania:" msgid "Deleting Collection:" -msgstr "" +msgstr "Usuwanie zbioru:" msgid "Deleting Principal:" -msgstr "" +msgstr "Usuwane podmiotu:" msgid "Deleting Ticket:" -msgstr "" +msgstr "Usuwanie kodu dostępowego" msgid "" "Deliver scheduling invitations from an organiser to this scheduling inbox" @@ -427,28 +440,28 @@ msgid "Deliver scheduling replies from an attendee to this scheduling inbox" msgstr "" msgid "Dependencies" -msgstr "" +msgstr "Zależności" msgid "Dependency" -msgstr "" +msgstr "Zależność" msgid "Description" -msgstr "" +msgstr "Opis" msgid "Destination collection does not exist" -msgstr "" +msgstr "Zbiór docelowy nie istnieje" msgid "Directory on the server" -msgstr "" +msgstr "Folder na serwerze" msgid "Display Name" -msgstr "" +msgstr "Nazwa wyświetlana" msgid "Displayname" -msgstr "" +msgstr "Nazwa wyświetlana" msgid "Does the user have the right to perform this role?" -msgstr "Czy użytkownik ma prawo wykonywać tę rolę?" +msgstr "" msgid "EMail" msgstr "E-mail" @@ -457,23 +470,23 @@ msgid "EMail OK" msgstr "E-mail zweryfikowano" msgid "ERROR: The full name may not be blank." -msgstr "" +msgstr "BŁĄD: pełna nazwa nie może być pusta." msgid "ERROR: The new password must match the confirmed password." -msgstr "" +msgstr "BŁĄD: Podana hasła muszą być identyczne." msgid "ERROR: There was a database error writing the roles information!" msgstr "" "Błąd: Wystąpił błąd bazy danych podczas zapisywania informacji o roli." msgid "Edit" -msgstr "" +msgstr "Edytuj" msgid "Edit this user record" msgstr "Zmień dane tego użytkownika " msgid "Email Address" -msgstr "" +msgstr "Adres email" msgid "" "Enter a username, if you know it, and click here, to be e-mailed a temporary" @@ -488,11 +501,11 @@ msgstr "" #, php-format msgid "Error NoGroupFound with filter >%s<, attributes >%s< , dn >%s<" -msgstr "" +msgstr "Błąd NoGroupFound z filtrem >%s<, atrybutami >%s< , dn >%s<" #, php-format msgid "Error NoUserFound with filter >%s<, attributes >%s< , dn >%s<" -msgstr "" +msgstr "Bład NoUserFound z filtrem >%s<, atrybutami >%s< , dn >%s<" msgid "Error querying database." msgstr "Błąd odpytywania bazy danych." @@ -501,119 +514,119 @@ msgid "Error writing calendar details to database." msgstr "Błąd zapisu kalendarza do bazy." msgid "Error writing calendar properties to database." -msgstr "" +msgstr "Błąd zapisu właściwości kalendarza do bazy." msgid "European" -msgstr "" +msgstr "Europejski" msgid "European (d/m/y)" msgstr "Europejski (d/m/r)" msgid "Existing resource does not match \"If-Match\" header - not accepted." -msgstr "" +msgstr "Istniejący zasób nie pasuje do nagłówka \"If-Match\" - odrzucono." msgid "Existing resource matches \"If-None-Match\" header - not accepted." -msgstr "" +msgstr "Istniejący zasób pasuje do nagłówka \"If-None-Match\" - odrzucono." msgid "Expires" -msgstr "" +msgstr "Wygasa" msgid "External Calendars" -msgstr "" +msgstr "Kalendarze zewnętrzne" msgid "External Url" -msgstr "" +msgstr "Zewnętrzne URLe" msgid "Fail" -msgstr "" +msgstr "Błąd" msgid "Failed to write collection." -msgstr "" +msgstr "Błąd zapisu zbioru" msgid "Feeds are only supported for calendars at present." -msgstr "" +msgstr "Kanały są na razie wspierane tylko dla kalendarzy." msgid "For access to the" msgstr "Aby uzyskać dostęp do" msgid "Forbidden" -msgstr "" +msgstr "Zabronione" msgid "Free/Busy" -msgstr "" +msgstr "Wolny/zajęty" msgid "Full Name" msgstr "Imię i nazwisko" msgid "Fullname" -msgstr "" +msgstr "Pełna nazwa" msgid "GET requests on collections are only supported for calendars." -msgstr "" +msgstr "Żądania GET są obsługiwane tylko dla zbiorów typu kalendarz." msgid "GNU gettext support" -msgstr "" +msgstr "Obsługa GNU gettext" msgid "GO!" -msgstr "Uruchom!" +msgstr "Wejdź!" msgid "Go to the DAViCal Feature Requests" -msgstr "" +msgstr "Przejdź do próśb o nową funkcjonalność" msgid "Grant" -msgstr "" +msgstr "Zezwól" msgid "Granting new privileges from this Principal" -msgstr "" +msgstr "Przyznawanie nowych uprawnień podmiotowi" #. Translators: in the sense of a group of people msgid "Group" msgstr "Grupa" msgid "Group Members" -msgstr "" +msgstr "Członkowie grupy" msgid "Group Memberships" -msgstr "" +msgstr "Członkostwo w grupach" msgid "Group Principals" -msgstr "" +msgstr "Grupy" msgid "Has Members" -msgstr "" +msgstr "Członkowie" msgid "Help" msgstr "Pomoc" msgid "Help on the current screen" -msgstr "" +msgstr "Pomoc do bieżącego ekranu" msgid "Help! I've forgotten my password!" msgstr "Pomocy! Zapomniałem hasła!" msgid "Home" -msgstr "Początek" +msgstr "Start" msgid "Home Page" -msgstr "" +msgstr "Strona domowa" msgid "Home addressbook added." -msgstr "" +msgstr "Dodano główną książkę adresową" msgid "Home addressbook already exists." -msgstr "" +msgstr "Główna książka adresowa już istnieje." msgid "Home calendar added." -msgstr "" +msgstr "Dodano kalendarz główny." msgid "Home calendar already exists." -msgstr "" +msgstr "Kalendarz główny już istnieje." msgid "ID" -msgstr "" +msgstr "ID" msgid "ISO Format" -msgstr "" +msgstr "ISO" msgid "ISO Format (YYYY-MM-DD)" msgstr "ISO (RRRR-MM-DD)" @@ -623,49 +636,49 @@ msgid "Id" msgstr "Id" msgid "If you have forgotten your password then" -msgstr "Jeśli zapomniałeś hasła, " +msgstr "Jeśli zapomniałeś hasła," msgid "If you would like to request access, please e-mail" msgstr "Jeśli chcesz poprosić o dostęp, wyślij e-mail do" msgid "Import all .ics files of a directory" -msgstr "" +msgstr "Wczytaj wszystkie pliki .ics z folderu" msgid "Import calendars and Synchronise LDAP." -msgstr "" +msgstr "Importuj kalendarze i zsynchronizuj z LDAP." msgid "Inactive Principals" -msgstr "" +msgstr "Podmioty nieaktywne" msgid "Incorrect content type for addressbook: " -msgstr "" +msgstr "Zły rodzaj zawartości dla książki adresowej: " msgid "Incorrect content type for calendar: " -msgstr "" +msgstr "Zły rodzaj zawartości dla kalendarza: " msgid "Invalid user name or password." -msgstr "Błędna nazwa użytkownika lub hasło." +msgstr "Zła nazwa użytkownika lub hasło." msgid "Invalid username or password." -msgstr "Błędna nazwa użytkownika lub hasło" +msgstr "Zła nazwa użytkownika lub hasło" msgid "Is Member of" -msgstr "" +msgstr "Jest członkiem" msgid "Is a Calendar" -msgstr "" +msgstr "Jest kalendarzem" msgid "Is an Addressbook" -msgstr "" +msgstr "Jest książka adresową" msgid "Is this user active?" msgstr "Aktywny użytkownik?" msgid "Items in Collection" -msgstr "" +msgstr "Elementy zbioru" msgid "Joined" -msgstr "Dodano" +msgstr "Dołączono" msgid "Language" msgstr "Język" @@ -674,116 +687,118 @@ msgid "Last used" msgstr "Ostatnio używany" msgid "List External Calendars" -msgstr "" +msgstr "Pokaż zewnętrzne kalendarze" msgid "List Groups" -msgstr "" +msgstr "Pokaż grupy" msgid "List Resources" -msgstr "" +msgstr "Pokaż zasoby" msgid "List Users" -msgstr "" +msgstr "Pokaż użytkowników" msgid "Load From File" -msgstr "" +msgstr "Wczytaj z pliku" msgid "Locale" -msgstr "" +msgstr "Język" msgid "Location" -msgstr "" +msgstr "Miejsce" msgid "Log On Please" msgstr "Proszę się zalogować" msgid "Log out of DAViCal" -msgstr "" +msgstr "Wylogowanie z DAViCala" msgid "Logout" msgstr "Wyloguj się" msgid "Member deleted from this Group Principal" -msgstr "" +msgstr "Członek usunięty z tej grupy" msgid "" "Most of DAViCal will work but upgrading to PHP 5.2 or later is strongly " "recommended." msgstr "" +"Większość funkcji DAViCALa będzie działać, ale usilnie zaleca się " +"aktualizacje PHP do wersji co najmniej 5.2." msgid "Name" msgstr "Nazwa" msgid "New Collection" -msgstr "" +msgstr "Nowy zbiór" msgid "New Password" msgstr "Nowe hasło" msgid "New Principal" -msgstr "" +msgstr "Nowy podmiot" #. Translators: not 'Yes' msgid "No" -msgstr "" +msgstr "Nie" msgid "No calendar content" -msgstr "" +msgstr "Brak treści kalendarzowej" msgid "No collection found at that location." msgstr "Nie znaleziono zbioru w lokalizacji" msgid "No summary" -msgstr "" +msgstr "Brak podsumowania" #. Translators: short for 'Number' msgid "No." msgstr "Nr" msgid "No. of Collections" -msgstr "" +msgstr "Liczba zbiorów" msgid "No. of Principals" -msgstr "" +msgstr "Liczba podmiotów" msgid "No. of Resources" -msgstr "" +msgstr "Liczba zasobów" msgid "Not overwriting existing destination resource" -msgstr "" +msgstr "Istniejący w docelowym miejscu zasób nie został nadpisany" msgid "Opaque" -msgstr "" +msgstr "Nieprzejrzysty" msgid "Override a Lock" -msgstr "" +msgstr "Przełam blokadę" msgid "PDO PostgreSQL drivers" -msgstr "" +msgstr "Sterowniki PDO do PostgreSQL" msgid "PHP DateTime class" -msgstr "" +msgstr "Klasa PHP DateTime" msgid "PHP LDAP module available" -msgstr "" +msgstr "Dostępny moduł PHP LDAP" msgid "PHP Magic Quotes GPC off" -msgstr "" +msgstr "Wyłączona opcja PHP Magic Quotes GPC" msgid "PHP Magic Quotes runtime off" -msgstr "" +msgstr "Wyłączona opcja PHP MagicQuotes runtime" msgid "PHP PDO module available" -msgstr "" +msgstr "Dostępny moduł PHP PDO" msgid "PHP PostgreSQL available" -msgstr "" +msgstr "Dostępny moduł PHP PostgreSQL" msgid "PHP calendar extension available" -msgstr "" +msgstr "Dostępne rozszerzenia kalendarzowe PHP" msgid "PHP iconv support" -msgstr "" +msgstr "Dostępne wsparcie iconv w PHP" msgid "" "PUT on a collection is only allowed for text/calendar content against a " @@ -796,55 +811,55 @@ msgid "" msgstr "" msgid "Passed" -msgstr "" +msgstr "OK" msgid "Password" msgstr "Hasło" msgid "Path" -msgstr "" +msgstr "Ścieżka" msgid "Person" -msgstr "" +msgstr "Osoba" msgid "Please confirm deletion of access ticket - see below" -msgstr "" +msgstr "Proszę potwierdzić usunięcie kodu dostępowego- p. niżej" msgid "Please confirm deletion of binding - see below" -msgstr "" +msgstr "Proszę potwierdzić usunięcie wiązania - p. niżej" msgid "Please confirm deletion of collection - see below" -msgstr "" +msgstr "Proszę potwierdzić usunięcie zbioru - p. niżej" msgid "Please confirm deletion of the principal" -msgstr "" +msgstr "Proszę potwierdzić usunięcie podmiotu - p. niżej" msgid "Please note the time and advise the administrator of your system." -msgstr "" +msgstr "Proszę zanotować czas zdarzenia i dać znać administratorowi systemu." msgid "Principal" -msgstr "" +msgstr "Podmiot" msgid "Principal Collections" -msgstr "" +msgstr "Zbiory podmiotu" msgid "Principal Grants" -msgstr "" +msgstr "Zezwolenia podmiotu" msgid "Principal ID" -msgstr "" +msgstr "ID podmiotu" msgid "Principal Type" -msgstr "" +msgstr "Rodzaj podmiotu" msgid "Principal deleted" -msgstr "" +msgstr "Podmiot usunięty" msgid "Privileges" -msgstr "" +msgstr "Uprawnienia" msgid "Privileges granted to All Users" -msgstr "" +msgstr "Uprawnienia nadane wszystkim" msgid "Property is read-only" msgstr "Właściwość tylko do odczytu" @@ -854,53 +869,53 @@ msgid "Public" msgstr "Publiczny" msgid "Publicly Readable" -msgstr "" +msgstr "Publiczny do odczytu" msgid "REPORT body contains no XML data!" -msgstr "" +msgstr "Treść REPORT nie zawiera danych XML!" msgid "REPORT body is not valid XML data!" -msgstr "" +msgstr "Treść REPORT nie zawiera prawidłowych danych XML!" msgid "Read" -msgstr "" +msgstr "Odczyt" msgid "Read ACLs for a resource or collection" -msgstr "" +msgstr "Reguły ACL dla odczytu zasobu lub zbioru" msgid "Read Access Controls" -msgstr "" +msgstr "Edycja uprawnień do odczytu" msgid "Read Current User's Access" -msgstr "" +msgstr "Odczyt praw dostępu bieżącego użytkownika" msgid "Read Free/Busy Information" -msgstr "" +msgstr "Odczyt informacji o czasie wolnym" msgid "Read the content of a resource or collection" -msgstr "" +msgstr "Odczyt zawartości zasobu lub zbioru" msgid "" "Read the details of the current user's access control to this resource." -msgstr "" +msgstr "Odczyt praw dostępu bieżącego użytkownika do tego zasobu." msgid "Read the free/busy information for a calendar collection" -msgstr "" +msgstr "Odczyt informacji o czasie wolnym z kalendarza" msgid "Read/Write" -msgstr "" +msgstr "Odczyt/zapis" msgid "References" -msgstr "" +msgstr "Odwołania" msgid "Remove" -msgstr "" +msgstr "Usuń" msgid "Remove a lock" -msgstr "" +msgstr "Usuń blokadę" msgid "Remove dangling external calendars" -msgstr "" +msgstr "Usuń zerwane odwołania do kalendarzy zewnętrznych" msgid "Report Bug" msgstr "Zgłoś błąd" @@ -909,10 +924,10 @@ msgid "Report a bug in the system" msgstr "Zgłoś błąd w systemie" msgid "Request Feature" -msgstr "" +msgstr "Poproś o nową funkcjonalność" msgid "Request body is not valid XML data!" -msgstr "" +msgstr "Treść żądania nie zawiera poprawnych danych XML!" #. Translators a thing which might be booked: a room, a carpark, a #. projector... @@ -923,138 +938,142 @@ msgid "Resource Calendar Principals" msgstr "" msgid "Resource Not Found." -msgstr "" +msgstr "Nie znaleziono zasobu." msgid "Resource has changed on server - not deleted" msgstr "Zasób zmieniony na serwerze - nie usuwam." msgid "Resources may not be changed to / from collections." -msgstr "" +msgstr "Nie można zmieniać typu z zasobu na zbiór ani w druga stronę." msgid "Revoke" -msgstr "" +msgstr "Odwołaj" msgid "Schedule Deliver" -msgstr "" +msgstr "Odbiór informacji w ramach planowania" msgid "Schedule Send" -msgstr "" +msgstr "Wysyłanie informacji w ramach planowania" msgid "Schedule Transparency" msgstr "" msgid "Scheduling: Deliver a Reply" -msgstr "" +msgstr "Planowanie: odbierz odpowiedź" msgid "Scheduling: Deliver an Invitation" -msgstr "" +msgstr "Planowanie: odbierz zaproszenie" msgid "Scheduling: Delivery" -msgstr "" +msgstr "Planowanie: odbieranie powiadomień" msgid "Scheduling: Query free/busy" -msgstr "" +msgstr "Planowanie: zapytaj o czas wolny" msgid "Scheduling: Send a Reply" -msgstr "" +msgstr "Planowanie: wyślij odpowiedź" msgid "Scheduling: Send an Invitation" -msgstr "" +msgstr "Planowanie: wyślij zaproszenie" msgid "Scheduling: Send free/busy" -msgstr "" +msgstr "Planowanie: wyślij informacje o czasie wolnym" msgid "Scheduling: Sending" -msgstr "" +msgstr "Planowanie: wysyłanie powiadomień" msgid "Send free/busy enquiries" -msgstr "" +msgstr "Wysyłaj zapytania o czas wolny" msgid "" "Send scheduling invitations as an organiser from the owner of this " "scheduling outbox." msgstr "" +"Wysyłaj stąd zaproszenia na planowane spotkanie, które organizujesz." msgid "" "Send scheduling replies as an attendee from the owner of this scheduling " "outbox." msgstr "" +"Wysyłaj stąd odpowiedzi jako uczestnik planowanego spotkania." msgid "Set free/busy privileges" -msgstr "" +msgstr "Ustaw uprawnienia do odpytywania o czas wolny." msgid "Set read privileges" -msgstr "" +msgstr "Ustaw uprawnienia do odczytu" msgid "Set read+write privileges" -msgstr "" +msgstr "Ustaw uprawnienia do odczytu i zapisu" msgid "Set schedule-deliver privileges" -msgstr "" +msgstr "Ustaw uprawnienia na planowanie spotkań" msgid "" "Set the path to store your ics e.g. 'calendar' will be referenced as " "/caldav.php/username/calendar/" -msgstr "" +msgstr "Ustaw ścieżkę do kalendarza ics, np 'calendar' będzie widoczny " +"jako /caldav.php/username/calendar/" msgid "Setup" -msgstr "" +msgstr "Ustawienia" msgid "Setup DAViCal" -msgstr "" +msgstr "Ustawienia DAViCala" msgid "Show help on" msgstr "Pokaż pomoc na temat" msgid "Site Statistics" -msgstr "" +msgstr "Statystyki witryny" msgid "Site Statistics require the database to be available!" -msgstr "" +msgstr "Wyświetlenie statystyk wymaga działającego połączenia z bazą danych!" msgid "Some properties were not able to be changed." msgstr "Niektóre właściwości nie mogły zostać zmienione." msgid "Some properties were not able to be set." -msgstr "" +msgstr "Nie udało się ustawić niektórych właściwości." msgid "Source resource does not exist." -msgstr "" +msgstr "Zasób źródłowy nie istnieje." msgid "" "Special collections may not contain a calendar or other special collection." msgstr "" +"Zbiory specjalne nie mogą zawierać kalendarzy ani innych zbiorów specjalnych." msgid "Specific Privileges" -msgstr "" +msgstr "Konkretne uprawnienia" msgid "Status" -msgstr "" +msgstr "Status" #, php-format msgid "Status: %d, Message: %s, User: %d, Path: %s" -msgstr "" +msgstr "Status %d, Wiadomość: %s, Użytkownik: %d, Ścieżka: %s" msgid "Submit" -msgstr "" +msgstr "Wyślij" msgid "Suhosin \"server.strip\" disabled" -msgstr "" +msgstr "Wyłączony Suhosin \"server.strip\"" msgid "Sync LDAP Groups with DAViCal" -msgstr "" +msgstr "Zsynchronizuj grupy LDAP z DAViCalem" msgid "Sync LDAP with DAViCal" -msgstr "" +msgstr "Zsynchronizuj LDAP z DAViCalem" msgid "Target" -msgstr "" +msgstr "Cel" msgid "That destination name contains invalid characters." -msgstr "" +msgstr "Nazwa docelowa zawiera niedozwolone znaki." msgid "That resource is not present on this server." -msgstr "" +msgstr "Nie ma takiego zasobu na tym serwerze." msgid "The BIND Request MUST identify an existing resource." msgstr "" @@ -1068,25 +1087,26 @@ msgstr "" msgid "" "The CalDAV:schedule-calendar-transp property may only be set on calendars." msgstr "" +"Właściwość CalDAV:schedule-calendar-transp może zostać ustawiona tylko dla kalendarzy." msgid "The DAViCal Home Page" -msgstr "" +msgstr "Strona domowa DAViCala" msgid "The access ticket will be deleted." -msgstr "" +msgstr "Kod dostępu zostanie usunięty." msgid "" "The addressbook-query report must be run against an addressbook collection" -msgstr "" +msgstr "Zapytanie o wizytówkę może zostać zadane tylko książce adresowej." msgid "The application failed to understand that request." -msgstr "" +msgstr "Nie zrozumiano żądania." msgid "The application program does not understand that request." msgstr "Aplikacja nie rozumie tego żądania." msgid "The binding will be deleted." -msgstr "" +msgstr "Powiązanie zostanie usunięte." msgid "The calendar path contains illegal characters." msgstr "Ścieżka kalendarza zawiera nieakceptowalne znaki." @@ -1102,44 +1122,45 @@ msgid "" msgstr "" msgid "The collection name may not be blank." -msgstr "" +msgstr "Nazwa zbioru nie może być pusta." msgid "The destination collection does not exist" -msgstr "" +msgstr "Zbiór docelowy nie istnieje." msgid "" "The displayname may only be set on collections, principals or bindings." -msgstr "" +msgstr "Nazwa wyświetlana może zostać ustawiona tylko dla zbiorów, podmiotów i powiązań." msgid "The email address really should not be blank." -msgstr "" +msgstr "Adres pocztowy naprawdę nie powinien być pusty." #, php-format msgid "The file \"%s\" is not UTF-8 encoded, please check error for more details" -msgstr "" +msgstr "Plik \"%s\" nie jest w kodowaniu UTF-8, proszę zapoznać się z opisem błędu, aby uzyskać więcej informacji." msgid "" "The file is not UTF-8 encoded, please check the error for more details." msgstr "" +"Plik nie jest w kodowaniu UTF-8, proszę zapoznać się z opisem błędu, aby uzyskać więcej informacji." msgid "The full name for this person, group or other type of principal." -msgstr "" +msgstr "Pełna nazwa tej osoby, grupy czy też podmiotu innego rodzaju." msgid "The full name must not be blank." -msgstr "" +msgstr "Pełna nazwa nie może być pusta." msgid "The name this user can log into the system with." msgstr "Nazwa, którą ten użytkownik może użyć do zalogowania." msgid "The path on the server where your .ics files are." -msgstr "" +msgstr "Ścieżka na serwerze przechowująca twoje pliki .ics." msgid "The preferred language for this person." msgstr "Preferowany język." #, php-format msgid "The principal \"%s\" does not exist" -msgstr "" +msgstr "Podmiot \"%s\" nie istnieje" msgid "The style of dates used for this person." msgstr "Format daty używany przez tego użytkownika." @@ -1154,10 +1175,10 @@ msgid "The user's password for logging in." msgstr "Hasło logowania." msgid "The username must not be blank, and may not contain a slash" -msgstr "" +msgstr "Nazwa użytkownika nie może być pusta ani zawierać ukośnika." msgid "There was an error reading from the database." -msgstr "" +msgstr "Wystąpił błąd odczytu z bazy danych." msgid "There was an error writing to the database." msgstr "Wystąpił błąd zapisu do bazy danych." @@ -1185,44 +1206,48 @@ msgid "" "correctly. Suggestions or patches to make it do more useful stuff will be " "gratefully received." msgstr "" +"Ta strona sprawdza, czy środowisko zapewni poprawną pracę DAViCala. " +"Mile widziane wszelkie sugestie i łaty poprawiające jej funkcjonalność." msgid "" "This process will import each file in a directory named \"username.ics\" and" " create a user and calendar for each file to import." msgstr "" +"Ten proces zaimportuje każdy plik o nazwie \"username.ics\" ze wskazanego " +"folderu i utworzy na ich podstawie kalendarze użytkowników." msgid "This server only supports the text/calendar format for freebusy URLs" -msgstr "" +msgstr "Ten serwer obsługuje tylko format text/calendar dla URLi wolny/zajęty." msgid "Ticket ID" -msgstr "" +msgstr "ID kodu dostępowego" msgid "Time" -msgstr "" +msgstr "Czas" msgid "To Collection" -msgstr "" +msgstr "Do zbioru" msgid "To ID" -msgstr "" +msgstr "Do ID" msgid "Toggle all privileges" -msgstr "" +msgstr "Przełącz wszystkie uprawnienia" msgid "Tools" -msgstr "" +msgstr "Narzędzia" msgid "Transparent" -msgstr "" +msgstr "Przejrzysty" msgid "URL" -msgstr "" +msgstr "URL" msgid "US Format" -msgstr "" +msgstr "Amerykański" msgid "Unauthenticated User" -msgstr "" +msgstr "Użytkownik niezalogowany" msgid "United States of America (m/d/y)" msgstr "USA (m/d/r)" @@ -1234,27 +1259,28 @@ msgid "Updated" msgstr "Zaktualizowano" msgid "Updating Collection record." -msgstr "" +msgstr "Aktualizacja rekordu zbioru" msgid "Updating Member of this Group Principal" -msgstr "" +msgstr "Aktualizacja członka grupy" msgid "Updating Principal record." -msgstr "" +msgstr "Aktualizacja rekordu podmiotu." msgid "Updating grants by this Principal" msgstr "" msgid "Upgrade DAViCal database schema" -msgstr "" +msgstr "Aktualizacja schematu bazy danych" msgid "Upgrade Database" -msgstr "" +msgstr "Aktualizacja bazy danych" msgid "" "Upload a .ics calendar in iCalendar format to initialise or replace this " "calendar." -msgstr "" +msgstr "Wgraj plik .ics w formacie iCalendar aby stworzyć lub zastąpić ten " +"kalendarz." msgid "User Calendar Principals" msgstr "" @@ -1263,7 +1289,7 @@ msgid "User Details" msgstr "Dane użytkownika" msgid "User Functions" -msgstr "" +msgstr "Funkcje użytkownika" msgid "User Name" msgstr "Nazwa użytkownika" @@ -1278,122 +1304,132 @@ msgid "User record written." msgstr "Dane użytkownika zostały zapisane." msgid "Username" -msgstr "" +msgstr "Nazwa użytkownika" msgid "View My Details" -msgstr "" +msgstr "Moje szczegóły" msgid "View my own principal record" -msgstr "" +msgstr "Mój rekord podmiotu" msgid "View this user record" msgstr "Zobacz dane tego użytkownika" msgid "Visit the DAViCal Wiki" -msgstr "" +msgstr "Odwiedź Wiki DAViCala" #, php-format msgid "Want: %s, Currently: %s" -msgstr "" +msgstr "Chcesz: %s, obecnie: %s" msgid "" "Warning: there are no active admin users! You should fix this before logging" " out. Consider using the $c->do_not_sync_from_ldap configuration setting." msgstr "" +"OSTRZEŻENIE: brak aktywnych administratorów! Musisz to naprawić, zanim się " +"wylogujesz. Rozważ ustawienie $c->do_not_sync_from_ldap." msgid "When the user's e-mail account was validated." msgstr "Kiedy potwierdzono adres e-mail" msgid "Write" -msgstr "" +msgstr "Zapis" msgid "Write ACLs for a resource or collection" -msgstr "" +msgstr "Reguły ACL dla zapisu do zasobu lub zbioru" msgid "Write Access Controls" msgstr "" msgid "Write Data" -msgstr "" +msgstr "Zapis danych" msgid "Write Metadata" -msgstr "" +msgstr "Zapis metadanych" msgid "Write content" -msgstr "" +msgstr "Zapis treści" msgid "Write properties" -msgstr "" +msgstr "Zapis właściwości" msgid "Yes" -msgstr "" +msgstr "Tak" msgid "You are editing" -msgstr "" +msgstr "Edytujesz" msgid "You are not authorised to use this function." msgstr "Nie masz uprawnień aby użyć tej funkcji." msgid "You are viewing" -msgstr "" +msgstr "Oglądasz" msgid "You do not have permission to modify this record." -msgstr "" +msgstr "Nie masz uprawnień do wprowadzania zmian w tym rekordzie." msgid "You may not PUT to a collection URL" -msgstr "" +msgstr "Nie można wykonać operacji PUT na URLu zbioru" msgid "You must log in to use this system." msgstr "Musisz się zalogować." msgid "Your configuration produced PHP errors which should be corrected" -msgstr "" +msgstr "Aktualne ustawienia powodują błędy PHP, które powinny zostać poprawione" msgid "calendar-timezone property is only valid for a calendar." -msgstr "" +msgstr "Właściwość calendar-timezone można określić tylko dla kalendarza" #, php-format msgid "directory %s is not readable" -msgstr "" +msgstr "katalog %s nie jest do odczytu" msgid "" "drivers_imap_pam : imap_url parameter not configured in " "/etc/davical/*-conf.php" msgstr "" +"drivers_imap_pam : nie skonfigurowano parametru imap_url w " +"pliku /etc/davical/*-conf.php" msgid "drivers_ldap : Could not start TLS: ldap_start_tls() failed" -msgstr "" +msgstr "drivers_ldap : Nie udało się włączyć TLS: wywołanie ldap_start_tls() zakończyło się niepowodzeniem" #, php-format msgid "" "drivers_ldap : Failed to bind to host %1$s on port %2$s with bindDN of %3$s" msgstr "" +"drivers_ldap : Nie udało się połączyć z hostem %1$s na porcie %2$s z bindDN ustawionym na %3$s" msgid "" "drivers_ldap : Failed to set LDAP to use protocol version 3, TLS not " "supported" msgstr "" +"drivers_ldap : Nie udało się wynegocjować z serwerem LDAP użycia " +"trzeciej wersji protokołu, brak obsługi TLS" msgid "" "drivers_ldap : Unable to bind to LDAP - check your configuration for bindDN " "and passDN, and that your LDAP server is reachable" msgstr "" +"drivers_ldap : Nie udało się połączyć z LDAP - sprawdź konfigurację bindDN " +"i passDN oraz czy serwer LDAP jest osiągalny" #, php-format msgid "drivers_ldap : Unable to connect to LDAP with port %s on host %s" -msgstr "" +msgstr "drivers_ldap : Nie udało się połączyć z bazą LDAP na porcie %s hosta %s" msgid "" "drivers_ldap : function ldap_connect not defined, check your php_ldap module" msgstr "" +"drivers_ldap : brak funkcji ldap_connect, sprawdź wersję modułu php_ldap" #, php-format msgid "drivers_pwauth_pam : Unable to find %s file" -msgstr "" +msgstr "drivers_pwauth_pam : nie znaleziono pliku %s" #, php-format msgid "drivers_squid_pam : Unable to find %s file" -msgstr "" +msgstr "drivers_squid_pam : nie znaleziono pliku %s" #. Translators: this is a colloquial phrase in english (the name of a flower) #. and is an option allowing people to log in automatically in future @@ -1401,13 +1437,13 @@ msgid "forget me not" msgstr "zapamiętaj mnie" msgid "from principal" -msgstr "" +msgstr "od podmiotu" msgid "path to store your ics" -msgstr "" +msgstr "ścieżka do przechowania pliku ics" msgid "unauthenticated" -msgstr "" +msgstr "niezalogowany" msgid "" "you should log on with the username and password that have been issued to " From b50b2d82ea2d518042276fad97810dcd92ee8f49 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 18:43:10 +1300 Subject: [PATCH 10/13] Force output buffers to be flushed, if they're turned on. If output buffering is turned on, PHP can be a bit slack about sending the data to the client before closing the connection with exit(). These changes ensure we call ob_flush() before we leave. We call @ob_flush() so we don't get noisy warnings when output buffering is off... --- htdocs/admin.php | 2 +- htdocs/always.php | 5 +++-- htdocs/caldav.php | 8 ++++---- htdocs/index.php | 2 +- htdocs/tools.php | 2 +- inc/CalDAVRequest.php | 3 +-- inc/DAViCalSession.php | 4 ++-- inc/HTTPAuthSession.php | 2 +- inc/always.php.in | 5 +++-- inc/auth-functions.php | 2 +- inc/autodiscover-handler.php | 4 ++-- inc/caldav-PROPPATCH.php | 3 +-- inc/well-known.php | 5 +++-- 13 files changed, 24 insertions(+), 23 deletions(-) diff --git a/htdocs/admin.php b/htdocs/admin.php index f2117974..7fe272c3 100644 --- a/htdocs/admin.php +++ b/htdocs/admin.php @@ -24,7 +24,7 @@ if ( ! @include_once( $code_file ) ) { $c->messages[] = sprintf('No page found to %s %s%s%s', $action, ($action == 'browse' ? '' : 'a '), $component, ($action == 'browse' ? 's' : '')); include('page-header.php'); include('page-footer.php'); - exit(0); + @ob_flush(); exit(0); } include('page-header.php'); diff --git a/htdocs/always.php b/htdocs/always.php index f84bd95d..256f0e6d 100644 --- a/htdocs/always.php +++ b/htdocs/always.php @@ -26,6 +26,7 @@ function early_exception_handler($e) { foreach( $trace AS $k => $v ) { printf( "%s[%d] %s%s%s()\n", $v['file'], $v['line'], (isset($v['class'])?$v['class']:''), (isset($v['type'])?$v['type']:''), (isset($v['function'])?$v['function']:'') ); } + @ob_flush(); } set_exception_handler('early_exception_handler'); @@ -89,7 +90,7 @@ if ( ! @include_once('AWLUtilities.php') ) { } if ( ! @include_once('AWLUtilities.php') ) { echo "Could not find the AWL libraries. Are they installed? Check your include_path in php.ini!\n"; - exit; + @ob_flush(); exit(0); } } @@ -145,7 +146,7 @@ else if ( @file_exists('config/config.php') ) { } else { include('davical_configuration_missing.php'); - exit; + @ob_flush(); exit(0); } $config_warnings = trim(ob_get_contents()); ob_end_clean(); diff --git a/htdocs/caldav.php b/htdocs/caldav.php index 8b0d9334..97845e0f 100644 --- a/htdocs/caldav.php +++ b/htdocs/caldav.php @@ -17,17 +17,17 @@ if ( isset($_SERVER['PATH_INFO']) && preg_match( '{^(/favicon.ico|davical.css|(i else { fpassthru($fh); } - exit(0); + @ob_flush(); exit(0); } require_once('./always.php'); if ( isset($_SERVER['PATH_INFO']) && preg_match( '{^/\.well-known/(.+)$}', $_SERVER['PATH_INFO'], $matches ) ) { require ('well-known.php'); - exit(0); + @ob_flush(); exit(0); } elseif ( isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] == '/autodiscover/autodiscover.xml' ) { require ('autodiscover-handler.php'); - exit(0); + @ob_flush(); exit(0); } function logRequestHeaders() { @@ -102,7 +102,7 @@ if ( ! ($request->IsPrincipal() || isset($request->collection) || $request->meth $redirect_url = ConstructURL('/caldav.php'.$matches[1]); dbg_error_log( 'LOG WARNING', 'Redirecting %s for "%s" to "%s"', $request->method, $request->path, $redirect_url ); header('Location: '.$redirect_url ); - exit(0); + @ob_flush(); exit(0); } } diff --git a/htdocs/index.php b/htdocs/index.php index cdbc96c9..782578e1 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -4,7 +4,7 @@ if ( $_SERVER['REQUEST_METHOD'] != "GET" && $_SERVER['REQUEST_METHOD'] != "POST" * If the request is not a GET or POST then they must really want caldav.php! */ include("./caldav.php"); - exit; // Not that it should return from that! + @ob_flush(); exit(0); // Not that it should return from that! } include("./always.php"); diff --git a/htdocs/tools.php b/htdocs/tools.php index 6e60b978..e73a31ea 100644 --- a/htdocs/tools.php +++ b/htdocs/tools.php @@ -21,7 +21,7 @@ require_once("caldav-PUT-functions.php"); include_once('check_UTF8.php'); if ( !$session->AllowedTo("Admin" ) ) - exit; + @ob_flush(); exit(0); if( function_exists("sync_LDAP") && isset($_POST['Sync_LDAP'])){ sync_LDAP(); diff --git a/inc/CalDAVRequest.php b/inc/CalDAVRequest.php index 4455472e..52649da3 100644 --- a/inc/CalDAVRequest.php +++ b/inc/CalDAVRequest.php @@ -1201,8 +1201,7 @@ EOSQL; @dbg_error_log("statistics", "Method: %s, Status: %d, Script: %5.3lfs, Queries: %5.3lfs, URL: %s", $this->method, $status, $script_time, $c->total_query_time, $this->path); } - - exit(0); + @ob_flush(); exit(0); } } diff --git a/inc/DAViCalSession.php b/inc/DAViCalSession.php index e06f1384..68d0f97a 100644 --- a/inc/DAViCalSession.php +++ b/inc/DAViCalSession.php @@ -113,7 +113,7 @@ class DAViCalSession extends Session || (isset($c->restrict_admin_port) && $c->restrict_admin_port != $_SERVER['SERVER_PORT'] ) ) { header('Location: caldav.php'); dbg_error_log( 'LOG WARNING', 'Access to "%s" via "%s:%d" rejected.', $_SERVER['REQUEST_URI'], $current_domain, $_SERVER['SERVER_PORT'] ); - exit(0); + @ob_flush(); exit(0); } if ( isset($c->restrict_admin_roles) && $roles == '' ) $roles = $c->restrict_admin_roles; if ( $this->logged_in && $roles == '' ) return; @@ -156,7 +156,7 @@ class DAViCalSession extends Session } include('page-footer.php'); - exit; + @ob_flush(); exit(0); } } diff --git a/inc/HTTPAuthSession.php b/inc/HTTPAuthSession.php index 1715ea1d..12cf9c07 100644 --- a/inc/HTTPAuthSession.php +++ b/inc/HTTPAuthSession.php @@ -88,7 +88,7 @@ class HTTPAuthSession { header( $auth_header ); echo 'Please log in for access to this system.'; dbg_error_log( "HTTPAuth", ":Session: User is not authorised: %s ", $_SERVER['REMOTE_ADDR'] ); - exit; + @ob_flush(); exit(0); } diff --git a/inc/always.php.in b/inc/always.php.in index 05a9ac22..b1c32d23 100644 --- a/inc/always.php.in +++ b/inc/always.php.in @@ -26,6 +26,7 @@ function early_exception_handler($e) { foreach( $trace AS $k => $v ) { printf( "%s[%d] %s%s%s()\n", $v['file'], $v['line'], (isset($v['class'])?$v['class']:''), (isset($v['type'])?$v['type']:''), (isset($v['function'])?$v['function']:'') ); } + @ob_flush(); } set_exception_handler('early_exception_handler'); @@ -89,7 +90,7 @@ if ( ! @include_once('AWLUtilities.php') ) { } if ( ! @include_once('AWLUtilities.php') ) { echo "Could not find the AWL libraries. Are they installed? Check your include_path in php.ini!\n"; - exit; + @ob_flush(); exit(0); } } @@ -145,7 +146,7 @@ else if ( @file_exists('config/config.php') ) { } else { include('davical_configuration_missing.php'); - exit; + @ob_flush(); exit(0); } $config_warnings = trim(ob_get_contents()); ob_end_clean(); diff --git a/inc/auth-functions.php b/inc/auth-functions.php index 6ada2c2a..b716f2f6 100644 --- a/inc/auth-functions.php +++ b/inc/auth-functions.php @@ -299,7 +299,7 @@ function AuthExternalAWL( $username, $password ) { EOERRMSG; - exit(1); + @ob_flush(); exit(1); } if ( $qry->Exec('Login',__LINE__,__FILE__) && $qry->rows() == 1 ) { diff --git a/inc/autodiscover-handler.php b/inc/autodiscover-handler.php index abf4fcac..65f5ba87 100644 --- a/inc/autodiscover-handler.php +++ b/inc/autodiscover-handler.php @@ -14,7 +14,7 @@ $request = new CalDAVRequest(); if ( !isset($c->enable_autodiscover) || ! $c->enable_autodiscover ) { $request->DoResponse( 404 ); - exit(0); + exit(0); // unneccessary } $ns_outlook_req_2006 = "http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"; @@ -40,7 +40,7 @@ function errorResponse( $code, $message, $debugdata = '' ) { ERROR; $request->DoResponse( $code, $response, 'text/xml; charset="utf-8"' ); - exit(0); + exit(0); // unneccessary } diff --git a/inc/caldav-PROPPATCH.php b/inc/caldav-PROPPATCH.php index 80d301a6..4e1163cd 100644 --- a/inc/caldav-PROPPATCH.php +++ b/inc/caldav-PROPPATCH.php @@ -353,6 +353,5 @@ if ( $qry->Commit() ) { * Or it was all crap. */ $request->DoResponse( 500 ); - -exit(0); +exit(0); // unneccessary diff --git a/inc/well-known.php b/inc/well-known.php index 6e50b1b3..6da42435 100644 --- a/inc/well-known.php +++ b/inc/well-known.php @@ -34,7 +34,7 @@ switch ( $request->path ) { if ( $c->enable_scheduling != true ) { $request->DoResponse( 404, translate('The application program does not understand that request.') ); - exit (); + // Does not return } header ( 'iSchedule-Version: 1.0' ); @@ -103,5 +103,6 @@ RESPONSE; RESPONSE; - exit ( 0 ); + + @ob_flush(); exit(0); } From 372a6a0a2c4bb4e956c18ac94620bedd7e5eec0d Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 18:43:51 +1300 Subject: [PATCH 11/13] If this message has an ORGANIZER elsewhere then we give up. One day we should maybe send a server-side e-mail to them, but for now that doesn't happen... --- inc/schedule-functions.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/inc/schedule-functions.php b/inc/schedule-functions.php index 9553941c..e359060a 100644 --- a/inc/schedule-functions.php +++ b/inc/schedule-functions.php @@ -70,6 +70,11 @@ function doItipAttendeeReply( vCalendar $resource, $partstat ) { $organizer = $resource->GetOrganizer(); $organizer_email = preg_replace( '/^mailto:/i', '', $organizer->Value() ); $organizer_principal = new Principal('email',$organizer_email ); + + if ( !$organizer_principal->Exists() ) { + dbg_error_log( 'schedule', 'Unknown ORGANIZER "%s" - unable to notify.', $organizer->Value() ); + return true; + } $sql = 'SELECT caldav_data.dav_name, caldav_data.caldav_data FROM caldav_data JOIN calendar_item USING(dav_id) '; $sql .= 'WHERE caldav_data.collection_id IN (SELECT collection_id FROM collection WHERE is_calendar AND user_no =?) '; @@ -80,7 +85,7 @@ function doItipAttendeeReply( vCalendar $resource, $partstat ) { return true; } $uid = $uids[0]->Value(); - $qry = new AwlQuery($sql,$organizer_principal->user_no(), $uid); + $qry = new AwlQuery($sql, $organizer_principal->user_no(), $uid); if ( !$qry->Exec('schedule',__LINE__,__FILE__) || $qry->rows() < 1 ) { dbg_error_log( 'schedule', 'Could not find original event from organizer - giving up on REPLY.' ); return true; From 0c5be26d827f121d9860a97e803b09931d3f584d Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 18:44:27 +1300 Subject: [PATCH 12/13] Regression test updates for DELETE scheduling handling. --- .../3030-DELETE-attendee-event.result | 12 +- .../3030-DELETE-attendee-event.test | 2 +- .../tests/scheduling/3031-DELETE-reply.result | 10 + .../3032-PUT-iCal-with-attendees.result | 370 ++++++++++++++++++ .../3032-PUT-iCal-with-attendees.test | 1 - .../3033-DELETE-organizer-event.result | 95 +++++ .../tests/timezone/Restore-Database.result | 2 +- 7 files changed, 483 insertions(+), 9 deletions(-) create mode 100644 testing/tests/scheduling/3031-DELETE-reply.result create mode 100644 testing/tests/scheduling/3032-PUT-iCal-with-attendees.result create mode 100644 testing/tests/scheduling/3033-DELETE-organizer-event.result diff --git a/testing/tests/scheduling/3030-DELETE-attendee-event.result b/testing/tests/scheduling/3030-DELETE-attendee-event.result index 0e514a6b..66efe9ce 100644 --- a/testing/tests/scheduling/3030-DELETE-attendee-event.result +++ b/testing/tests/scheduling/3030-DELETE-attendee-event.result @@ -6,7 +6,8 @@ Content-Length: 0 Content-Type: text/plain; charset="utf-8" - caldav_data: >BEGIN:VCALENDAR + dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< + vcalendar: >BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Apple Inc.//iCal 4.0.4//EN CALSCALE:GREGORIAN @@ -34,7 +35,7 @@ DTEND;TZID=Pacific/Auckland:20111019T140000 TRANSP:OPAQUE SUMMARY:Meeting with User1 DTSTART;TZID=Pacific/Auckland:20111019T130000 -DTSTAMP:20111024T035702Z +DTSTAMP:looks good ORGANIZER;CN="Manager 1":mailto:manager1@example.net SEQUENCE:6 ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: @@ -45,9 +46,9 @@ ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; END:VEVENT END:VCALENDAR < - dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< - caldav_data: >BEGIN:VCALENDAR + dav_name: >/manager1/.in/user1E1A13F04-iCal-schedule.ics< + vcalendar: >BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Apple Inc.//iCal 4.0.4//EN CALSCALE:GREGORIAN @@ -62,9 +63,8 @@ ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; DTSTART:20111019T000000Z ORGANIZER;CN="Manager 1":mailto:manager1@example.net SEQUENCE:7 -DTSTAMP:20111102T010804Z +DTSTAMP:looks good END:VEVENT END:VCALENDAR < - dav_name: >/manager1/.in/user1E1A13F04-iCal-schedule.ics< diff --git a/testing/tests/scheduling/3030-DELETE-attendee-event.test b/testing/tests/scheduling/3030-DELETE-attendee-event.test index 3f7ec167..4ad22f4c 100644 --- a/testing/tests/scheduling/3030-DELETE-attendee-event.test +++ b/testing/tests/scheduling/3030-DELETE-attendee-event.test @@ -15,7 +15,7 @@ HEAD # - An iTIP message in the managers's inbox. QUERY SELECT calendar_item.dav_name, - caldav_data.caldav_data + regexp_replace(caldav_data,'DTSTAMP:[0-9T]{15}Z','DTSTAMP:looks good') AS vcalendar FROM calendar_item JOIN caldav_data USING(dav_id, dav_name) WHERE uid = 'E1A13F04-iCal-schedule' ORDER BY dav_id diff --git a/testing/tests/scheduling/3031-DELETE-reply.result b/testing/tests/scheduling/3031-DELETE-reply.result new file mode 100644 index 00000000..5777a85a --- /dev/null +++ b/testing/tests/scheduling/3031-DELETE-reply.result @@ -0,0 +1,10 @@ +HTTP/1.1 204 No Content +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule +Content-Length: 0 +Content-Type: text/plain; charset="utf-8" + + + dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< + diff --git a/testing/tests/scheduling/3032-PUT-iCal-with-attendees.result b/testing/tests/scheduling/3032-PUT-iCal-with-attendees.result new file mode 100644 index 00000000..67673f9e --- /dev/null +++ b/testing/tests/scheduling/3032-PUT-iCal-with-attendees.result @@ -0,0 +1,370 @@ +HTTP/1.1 100 Continue + +HTTP/1.1 204 No Content +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule +Content-Length: 0 +Content-Type: text/plain; charset="utf-8" + + + caldav_type: >VEVENT< + dav_name: >/manager1/home/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >20< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user1@example.net +ATTENDEE;CN=user2@example.net;CUTYPE=INDIVIDUAL;EMAIL=user2@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user2@example.net +ATTENDEE;CN=user3@example.net;CUTYPE=INDIVIDUAL;EMAIL=user3@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user3@example.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + + caldav_type: >VEVENT< + dav_name: >/user1/.in/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >10< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + + caldav_type: >VEVENT< + dav_name: >/user1/home/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >10< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + + caldav_type: >VEVENT< + dav_name: >/user2/.in/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >11< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + + caldav_type: >VEVENT< + dav_name: >/user2/home/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >11< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + + caldav_type: >VEVENT< + dav_name: >/user3/.in/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >12< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + + caldav_type: >VEVENT< + dav_name: >/user3/home/E1A13F04-iCal-schedule.ics< + logged_user: >20< + summary: >Meeting with User1< + user_no: >12< + vcalendar: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Pacific/Auckland +BEGIN:DAYLIGHT +TZOFFSETFROM:+1200 +RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU +DTSTART:20070930T020000 +TZNAME:GMT+13:00 +TZOFFSETTO:+1300 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+1300 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +DTSTART:20080406T030000 +TZNAME:GMT+12:00 +TZOFFSETTO:+1200 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20111018T195845Z +UID:E1A13F04-iCal-schedule +DTEND;TZID=Pacific/Auckland:20111019T140000 +ATTENDEE;CN="Manager 1";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:mailto:manag + er1@example.net +ATTENDEE;CN="user1@example.net";CUTYPE=INDIVIDUAL;EMAIL="user1@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user1@ex + ample.net +ATTENDEE;CN="user2@example.net";CUTYPE=INDIVIDUAL;EMAIL="user2@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user2@ex + ample.net +ATTENDEE;CN="user3@example.net";CUTYPE=INDIVIDUAL;EMAIL="user3@example.n + et";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:user3@ex + ample.net +TRANSP:OPAQUE +SUMMARY:Meeting with User1 +DTSTART;TZID=Pacific/Auckland:20111019T130000 +DTSTAMP:20111024T035702Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + diff --git a/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test b/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test index 6d24381b..7a2ef1a4 100644 --- a/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test +++ b/testing/tests/scheduling/3032-PUT-iCal-with-attendees.test @@ -8,7 +8,6 @@ TYPE=PUT URL=http://regression.host/caldav.php/manager1/home/E1A13F04-iCal-schedule.ics HEADER=Content-Type: text/calendar HEADER=DAVKit/4.0.3 (732.2); CalendarStore/4.0.4 (997.7); iCal/4.0.4 (1395.7); Mac OS X/10.6.8 (10K549) -HEADER=If-Match: "651df94a71cc99384231637a5df101f4" HEAD AUTH=manager1:manager1 diff --git a/testing/tests/scheduling/3033-DELETE-organizer-event.result b/testing/tests/scheduling/3033-DELETE-organizer-event.result new file mode 100644 index 00000000..3219a3f7 --- /dev/null +++ b/testing/tests/scheduling/3033-DELETE-organizer-event.result @@ -0,0 +1,95 @@ +SQL executed successfully. +DELETE FROM caldav_data WHERE dav_name ~ E'/\\.in/.*E1A13F04-iCal-schedule\\.ics' + +HTTP/1.1 204 No Content +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule +Content-Length: 0 +Content-Type: text/plain; charset="utf-8" + + + caldav_data: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:CANCEL +REQUEST-STATUS:2.0 +BEGIN:VEVENT +UID:E1A13F04-iCal-schedule +DTEND:20111019T010000Z +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user1@example.net +ATTENDEE;CN=user2@example.net;CUTYPE=INDIVIDUAL;EMAIL=user2@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user2@example.net +ATTENDEE;CN=user3@example.net;CUTYPE=INDIVIDUAL;EMAIL=user3@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user3@example.net +DTSTART:20111019T000000Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + dav_name: >/user1/.in/E1A13F04-iCal-schedule.ics< + + caldav_data: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:CANCEL +REQUEST-STATUS:2.0 +BEGIN:VEVENT +UID:E1A13F04-iCal-schedule +DTEND:20111019T010000Z +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user1@example.net +ATTENDEE;CN=user2@example.net;CUTYPE=INDIVIDUAL;EMAIL=user2@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user2@example.net +ATTENDEE;CN=user3@example.net;CUTYPE=INDIVIDUAL;EMAIL=user3@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user3@example.net +DTSTART:20111019T000000Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + dav_name: >/user2/.in/E1A13F04-iCal-schedule.ics< + + caldav_data: >BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//iCal 4.0.4//EN +CALSCALE:GREGORIAN +METHOD:CANCEL +REQUEST-STATUS:2.0 +BEGIN:VEVENT +UID:E1A13F04-iCal-schedule +DTEND:20111019T010000Z +ATTENDEE;CN=Manager 1;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED: + mailto:manager1@example.net +ATTENDEE;CN=user1@example.net;CUTYPE=INDIVIDUAL;EMAIL=user1@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user1@example.net +ATTENDEE;CN=user2@example.net;CUTYPE=INDIVIDUAL;EMAIL=user2@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user2@example.net +ATTENDEE;CN=user3@example.net;CUTYPE=INDIVIDUAL;EMAIL=user3@example.net; + PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE;SCHEDULE-STATUS=1.2 + :mailto:user3@example.net +DTSTART:20111019T000000Z +ORGANIZER;CN="Manager 1":mailto:manager1@example.net +SEQUENCE:7 +END:VEVENT +END:VCALENDAR +< + dav_name: >/user3/.in/E1A13F04-iCal-schedule.ics< + diff --git a/testing/tests/timezone/Restore-Database.result b/testing/tests/timezone/Restore-Database.result index ba0eace9..1ae8b555 100644 --- a/testing/tests/timezone/Restore-Database.result +++ b/testing/tests/timezone/Restore-Database.result @@ -1,6 +1,6 @@ setval -------- - 1657 + 1667 (1 row) setval From 7080b2671ff09b153c231fd4ab7558dfebe13420 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Wed, 2 Nov 2011 18:48:44 +1300 Subject: [PATCH 13/13] Updated Norwegian and Portuguese translations. --- po/nb_NO.po | 40 ++++++++++++++++++++++++---------------- po/pt_PT.po | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/po/nb_NO.po b/po/nb_NO.po index be946bb2..d4076844 100644 --- a/po/nb_NO.po +++ b/po/nb_NO.po @@ -10,8 +10,8 @@ msgstr "" "Project-Id-Version: DAViCal\n" "Report-Msgid-Bugs-To: http://repo.or.cz/w/davical.git/tree/HEAD:/issues\n" "POT-Creation-Date: 2011-10-24 21:19+1300\n" -"PO-Revision-Date: 2011-10-24 08:21+0000\n" -"Last-Translator: karora \n" +"PO-Revision-Date: 2011-10-26 18:54+0000\n" +"Last-Translator: aleksand \n" "Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.net/projects/p/davical/team/nb_NO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -30,7 +30,7 @@ msgid "%T" msgstr "%T" msgid "*** Default Locale ***" -msgstr "*** Standard Locale ***" +msgstr "*** Forvalgt Nasjonalitet ***" msgid "*** Unknown ***" msgstr "*** Ukjent ***" @@ -153,7 +153,7 @@ msgstr "Alle data til samlingen vil ugjenopprettelig bli slettet" #, php-format msgid "All events of user \"%s\" were deleted and replaced by those from file %s" -msgstr "" +msgstr "Alle \"%s\" sine hendelser ble slettet og erstattet med de fra filen %s" msgid "" "All of the principal's calendars and events will be unrecoverably deleted." @@ -205,7 +205,7 @@ msgid "Bindings to this Principal's Collections" msgstr "Forbindelse til denne kontoens samlinger" msgid "Body contains no XML data!" -msgstr "" +msgstr "Meldingskroppen inneholder ingen XML data!" msgid "Bound As" msgstr "Forbundet som" @@ -395,10 +395,10 @@ msgid "Date Style" msgstr "Datoformat" msgid "Default Privileges" -msgstr "Standard privilegier" +msgstr "Forvalgte privilegier" msgid "Default relationships added." -msgstr "" +msgstr "La til forvalgte relasjoner." msgid "Delete" msgstr "Slett" @@ -525,10 +525,10 @@ msgid "Expires" msgstr "Løper ut" msgid "External Calendars" -msgstr "" +msgstr "Eksterne kalendere" msgid "External Url" -msgstr "" +msgstr "Ekstern URL" msgid "Fail" msgstr "Feil" @@ -680,7 +680,7 @@ msgid "Last used" msgstr "Sist brukt" msgid "List External Calendars" -msgstr "" +msgstr "List opp eksterne kalendere" msgid "List Groups" msgstr "Liste grupper" @@ -788,7 +788,7 @@ msgid "PHP PostgreSQL available" msgstr "PHP PostgreSQL tilgjengelig" msgid "PHP calendar extension available" -msgstr "" +msgstr "PHP kalenderutvidelse er tilgjengelig." msgid "PHP iconv support" msgstr "Støtte for PHP iconv" @@ -804,6 +804,8 @@ msgid "" "PUT on a collection is only allowed for text/vcard content against an " "addressbook collection" msgstr "" +"En PUT anmodning er kun tillatt for text/vcard innhold i en " +"adresseboksamling." msgid "Passed" msgstr "Godkjent" @@ -901,7 +903,7 @@ msgid "Read/Write" msgstr "Les/Skriv" msgid "References" -msgstr "" +msgstr "Referanser" msgid "Remove" msgstr "Fjern" @@ -910,7 +912,7 @@ msgid "Remove a lock" msgstr "Fjern en lås" msgid "Remove dangling external calendars" -msgstr "" +msgstr "Fjern haltende eksterne kalendere" msgid "Report Bug" msgstr "Rapporter feil" @@ -1006,6 +1008,8 @@ msgid "" "Set the path to store your ics e.g. 'calendar' will be referenced as " "/caldav.php/username/calendar/" msgstr "" +"Angi en sti for lagring av ics. For eksempel ‹kalender› vil bli referert som" +" /caldav.php/brukernavn/kalender/" msgid "Setup" msgstr "Oppsett" @@ -1053,7 +1057,7 @@ msgid "Suhosin \"server.strip\" disabled" msgstr "Suhosin \"server.strip\" disabled" msgid "Sync LDAP Groups with DAViCal" -msgstr "" +msgstr "Synkroniser LDAP grupper med DAViCal" msgid "Sync LDAP with DAViCal" msgstr "Synk LDAP med DAViCal" @@ -1091,7 +1095,7 @@ msgid "" msgstr "Adressebok-forespørselsrapport må kjøres mot en adressebok-samling" msgid "The application failed to understand that request." -msgstr "" +msgstr "Programmet kunne ikke forstå den anmodningen." msgid "The application program does not understand that request." msgstr "Programmet forstår ikke forespørselen" @@ -1132,6 +1136,8 @@ msgstr "Epostadressen skulle absolutt ikke være tom" #, php-format msgid "The file \"%s\" is not UTF-8 encoded, please check error for more details" msgstr "" +"Filen \"%s\" er ikke inkodet i UTF-8 encoded. Kontroller feilen for flere " +"detaljer." msgid "" "The file is not UTF-8 encoded, please check the error for more details." @@ -1154,7 +1160,7 @@ msgstr "Foretrukket språk for denne personen" #, php-format msgid "The principal \"%s\" does not exist" -msgstr "" +msgstr "Kontoen \"%s\" finnes ikke." msgid "The style of dates used for this person." msgstr "Datoformat brukt for denne personen" @@ -1219,6 +1225,8 @@ msgid "" "This process will import each file in a directory named \"username.ics\" and" " create a user and calendar for each file to import." msgstr "" +"Prosesen vil hente inn hver fil i mappen med navnet \"brukernavn.ics\" og " +"opprette en bruker og kalender for hver bruker og kalender som hentes inn." msgid "This server only supports the text/calendar format for freebusy URLs" msgstr "" diff --git a/po/pt_PT.po b/po/pt_PT.po index d042ca3c..da44d342 100644 --- a/po/pt_PT.po +++ b/po/pt_PT.po @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: DAViCal\n" "Report-Msgid-Bugs-To: http://repo.or.cz/w/davical.git/tree/HEAD:/issues\n" "POT-Creation-Date: 2011-10-24 21:19+1300\n" -"PO-Revision-Date: 2011-10-24 08:21+0000\n" -"Last-Translator: karora \n" +"PO-Revision-Date: 2011-10-26 19:34+0000\n" +"Last-Translator: m42 \n" "Language-Team: Portuguese (Portugal) (http://www.transifex.net/projects/p/davical/team/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -157,6 +157,8 @@ msgstr "Todos os dados da colecção serão irremediavelmente apagados" #, php-format msgid "All events of user \"%s\" were deleted and replaced by those from file %s" msgstr "" +"Todos os eventos do utilizador \"%s\" foram apagados e substituídos pelos do" +" ficheiro %s" msgid "" "All of the principal's calendars and events will be unrecoverably deleted." @@ -210,7 +212,7 @@ msgid "Bindings to this Principal's Collections" msgstr "Ligações às colecções deste Principal" msgid "Body contains no XML data!" -msgstr "" +msgstr "O corpo não contém dados XML!" msgid "Bound As" msgstr "Ligado Como" @@ -407,7 +409,7 @@ msgid "Default Privileges" msgstr "Privilégios predefinidos" msgid "Default relationships added." -msgstr "" +msgstr "Acrescentados relacionamentos predefinidos" msgid "Delete" msgstr "Eliminar" @@ -541,10 +543,10 @@ msgid "Expires" msgstr "Expira" msgid "External Calendars" -msgstr "" +msgstr "Calendários Externos" msgid "External Url" -msgstr "" +msgstr "Url Externo" msgid "Fail" msgstr "Falha" @@ -696,7 +698,7 @@ msgid "Last used" msgstr "Último usado" msgid "List External Calendars" -msgstr "" +msgstr "Listar Calendários Externos" msgid "List Groups" msgstr "Listar Grupos" @@ -762,7 +764,7 @@ msgstr "Sem sumário" #. Translators: short for 'Number' msgid "No." -msgstr "Não." +msgstr "Núm." msgid "No. of Collections" msgstr "Núm. de colecções" @@ -804,7 +806,7 @@ msgid "PHP PostgreSQL available" msgstr "PHP PostgreSQL disponível" msgid "PHP calendar extension available" -msgstr "" +msgstr "Extensão PHP para calendários disponível" msgid "PHP iconv support" msgstr "Suporte iconv do PHP" @@ -813,13 +815,15 @@ msgid "" "PUT on a collection is only allowed for text/calendar content against a " "calendar collection" msgstr "" -"PUT numa colecção é apenas permitido para conteúdo de texto/calendário em " -"face de uma colecção de calendário" +"PUT de conteúdo text/calendar apenas é permitido numa colecção do tipo " +"calendário" msgid "" "PUT on a collection is only allowed for text/vcard content against an " "addressbook collection" msgstr "" +"PUT de conteúdo text/vcard apenas é permitido numa colecção do tipo livro de" +" endereços" msgid "Passed" msgstr "Passou" @@ -918,7 +922,7 @@ msgid "Read/Write" msgstr "Ler/Escrever" msgid "References" -msgstr "" +msgstr "Referências" msgid "Remove" msgstr "Remover" @@ -927,7 +931,7 @@ msgid "Remove a lock" msgstr "Remover um lock" msgid "Remove dangling external calendars" -msgstr "" +msgstr "Remover calendários externos com problemas" msgid "Report Bug" msgstr "Relatar um bug" @@ -1027,6 +1031,8 @@ msgid "" "Set the path to store your ics e.g. 'calendar' will be referenced as " "/caldav.php/username/calendar/" msgstr "" +"Definir o caminho para guardar o seu ficheiro ics - e.g. 'calendar' será " +"referido como /caldav.php/nome_de_utilizador/calendar/" msgid "Setup" msgstr "Configurar" @@ -1075,7 +1081,7 @@ msgid "Suhosin \"server.strip\" disabled" msgstr "\"server.strip\" do suhosin desabilitado" msgid "Sync LDAP Groups with DAViCal" -msgstr "" +msgstr "Sincronizar Grupos LDAP com o DAViCal" msgid "Sync LDAP with DAViCal" msgstr "Sincronizar LDAP com o DAViCal" @@ -1117,7 +1123,7 @@ msgstr "" "livros de endereços" msgid "The application failed to understand that request." -msgstr "" +msgstr "A aplicação não conseguiu entender esse pedido." msgid "The application program does not understand that request." msgstr "O programa não entende esse pedido." @@ -1159,6 +1165,8 @@ msgstr "O endereço de email não devia, de facto, ficar em branco." #, php-format msgid "The file \"%s\" is not UTF-8 encoded, please check error for more details" msgstr "" +"O ficheiro \"%s\" não está codificado como UTF-8, por favor verifique a " +"mensagem de erro para mais promenores" msgid "" "The file is not UTF-8 encoded, please check the error for more details." @@ -1183,7 +1191,7 @@ msgstr "O idioma preferido para esta pessoa." #, php-format msgid "The principal \"%s\" does not exist" -msgstr "" +msgstr "O principal \"%s\" não existe" msgid "The style of dates used for this person." msgstr "O estilo de datas em uso para esta pessoa." @@ -1251,6 +1259,8 @@ msgid "" "This process will import each file in a directory named \"username.ics\" and" " create a user and calendar for each file to import." msgstr "" +"Este processo irá importar cada ficheiro chamado \"nome_de_utilizador.ics\" " +"ecriar um utilizador e calendário para cada ficheiro." msgid "This server only supports the text/calendar format for freebusy URLs" msgstr ""