[CalendarServer-changes] [11054] CalendarServer/branches/users/glyph/sharedgroups-2
source_changes at macosforge.org
source_changes at macosforge.org
Tue Apr 16 15:22:28 PDT 2013
Revision: 11054
http://trac.calendarserver.org//changeset/11054
Author: glyph at apple.com
Date: 2013-04-16 15:22:28 -0700 (Tue, 16 Apr 2013)
Log Message:
-----------
Up to 11020.
Modified Paths:
--------------
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/caldav.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/test/test_caldav.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/calverify.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/config.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_calverify.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_config.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_gateway.py
CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/util.py
CalendarServer/branches/users/glyph/sharedgroups-2/contrib/performance/loadtest/ical.py
CalendarServer/branches/users/glyph/sharedgroups-2/support/build.sh
CalendarServer/branches/users/glyph/sharedgroups-2/support/submit
CalendarServer/branches/users/glyph/sharedgroups-2/twext/enterprise/queue.py
CalendarServer/branches/users/glyph/sharedgroups-2/txdav/common/datastore/file.py
Added Paths:
-----------
CalendarServer/branches/users/glyph/sharedgroups-2/doc/RFC/RFC6868-Parameter Value Encoding.txt
CalendarServer/branches/users/glyph/sharedgroups-2/support/Apple.make
CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.xcodeproj/
CalendarServer/branches/users/glyph/sharedgroups-2/support/XCode.make
Removed Paths:
-------------
CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.tmproj
CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.xcodeproj/
CalendarServer/branches/users/glyph/sharedgroups-2/support/Makefile.Apple
Property Changed:
----------------
CalendarServer/branches/users/glyph/sharedgroups-2/
CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.xcodeproj/project.xcworkspace/
Property changes on: CalendarServer/branches/users/glyph/sharedgroups-2
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:9885-11000
+ /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:9885-11020
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/caldav.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/caldav.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -1427,6 +1427,7 @@
from twisted.internet import reactor
pool = PeerConnectionPool(reactor, store.newTransaction,
7654, schema)
+ store.queuer = store.queuer.transferProposalCallbacks(pool)
controlSocket.addFactory(_QUEUE_ROUTE,
pool.workerListenerFactory())
# TODO: now that we have the shared control socket, we should get
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/test/test_caldav.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tap/test/test_caldav.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -33,11 +33,12 @@
from twisted.internet.interfaces import IProcessTransport, IReactorProcess
from twisted.internet.protocol import ServerFactory
-from twisted.internet.defer import Deferred, inlineCallbacks
+from twisted.internet.defer import Deferred, inlineCallbacks, passthru
from twisted.internet.task import Clock
from twisted.internet import reactor
-from twisted.application.service import IService, IServiceCollection
+from twisted.application.service import (IService, IServiceCollection,
+ MultiService)
from twisted.application import internet
from twext.web2.dav import auth
@@ -62,6 +63,7 @@
_CONTROL_SERVICE_NAME, getSystemIDs
)
from calendarserver.provision.root import RootResource
+from twext.enterprise.queue import PeerConnectionPool, LocalQueuer
from StringIO import StringIO
@@ -358,14 +360,16 @@
writePlist(self.config, self.configFile)
- def makeService(self):
+ def makeService(self, patcher=passthru):
"""
Create a service by calling into CalDAVServiceMaker with
self.configFile
"""
self.options.parseOptions(["-f", self.configFile])
- return CalDAVServiceMaker().makeService(self.options)
+ maker = CalDAVServiceMaker()
+ maker = patcher(maker)
+ return maker.makeService(self.options)
def getSite(self):
@@ -507,8 +511,41 @@
)
+ def test_storeQueuerSetInMaster(self):
+ """
+ In the master, the store's queuer should be set to a
+ L{PeerConnectionPool}, so that work can be distributed to other
+ processes.
+ """
+ self.config["ProcessType"] = "Combined"
+ self.writeConfig()
+ class NotAStore(object):
+ queuer = LocalQueuer(None)
+ def newTransaction(self):
+ return None
+ def callWithNewTransactions(self, x):
+ pass
+ store = NotAStore()
+ def something(proposal):
+ pass
+ store.queuer.callWithNewProposals(something)
+ def patch(maker):
+ def storageServiceStandIn(createMainService, logObserver,
+ uid=None, gid=None):
+ pool = None
+ logObserver = None
+ svc = createMainService(pool, store, logObserver)
+ multi = MultiService()
+ svc.setServiceParent(multi)
+ return multi
+ self.patch(maker, "storageService", storageServiceStandIn)
+ return maker
+ self.makeService(patch)
+ self.assertIsInstance(store.queuer, PeerConnectionPool)
+ self.assertIn(something, store.queuer.proposalCallbacks)
+
class SlaveServiceTest(BaseServiceMakerTests):
"""
Test various configurations of the Slave service
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/calverify.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/calverify.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -17,8 +17,6 @@
##
from __future__ import print_function
-from twistedcaldav.directory.directory import DirectoryService
-from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
"""
This tool scans the calendar store to analyze organizer/attendee event
@@ -42,30 +40,39 @@
"""
+from calendarserver.tools.cmdline import utilityMain
+
from calendarserver.tools import tables
-from calendarserver.tools.cmdline import utilityMain
from calendarserver.tools.util import getDirectory
+
from pycalendar import definitions
from pycalendar.calendar import PyCalendar
from pycalendar.datetime import PyCalendarDateTime
from pycalendar.exceptions import PyCalendarError
from pycalendar.period import PyCalendarPeriod
from pycalendar.timezone import PyCalendarTimezone
+
from twext.enterprise.dal.syntax import Select, Parameter, Count
+
from twisted.application.service import Service
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.python import log, usage
from twisted.python.usage import Options
+
from twistedcaldav import caldavxml
+from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
from twistedcaldav.dateops import pyCalendarTodatetime
+from twistedcaldav.directory.directory import DirectoryService
from twistedcaldav.ical import Component, ignoredComponents, \
InvalidICalendarDataError, Property
from twistedcaldav.scheduling.itip import iTipGenerator
from twistedcaldav.stdconfig import DEFAULT_CONFIG_FILE
from twistedcaldav.util import normalizationLookup
+
from txdav.base.propertystore.base import PropertyName
from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
from txdav.common.icommondatastore import InternalDataStoreError
+
import base64
import collections
import sys
@@ -195,7 +202,7 @@
if not hasattr(Component, "maxAlarmCounts"):
Component.hasDuplicateAlarms = new_hasDuplicateAlarms
-VERSION = "9"
+VERSION = "10"
def printusage(e=None):
if e:
@@ -228,6 +235,7 @@
--missing : display orphaned calendar homes - can be used.
with either --ical or --mismatch.
--double : detect double-bookings.
+--dark-purge : purge room/resource events with invalid organizer
--nuke PATH|RID : remove specific calendar resources - can
only be used by itself. PATH is the full
@@ -263,6 +271,19 @@
--summary : report only which GUIDs have double-bookings - no details.
--days : number of days ahead to scan [DEFAULT: 365]
+Options for --dark-purge:
+
+--uuid : only scan specified calendar homes. Can be a partial GUID
+ to scan all GUIDs with that as a prefix or "*" for all GUIDS
+ (that are marked as resources or locations in the directory).
+--summary : report only which GUIDs have double-bookings - no details.
+--no-organizer : only detect events without an organizer
+--invalid-organizer : only detect events with an organizer not in the directory
+--disabled-organizer : only detect events with an organizer disabled for calendaring
+
+If none of (--no-organizer, --invalid-organizer, --disabled-organizer) is present, it
+will default to (--invalid-organizer, --disabled-organizer).
+
CHANGES
v8: Detects ORGANIZER or ATTENDEE properties with mailto: calendar user
addresses for users that have valid directory records. Fix is to
@@ -293,13 +314,18 @@
['mismatch', 's', "Detect organizer/attendee mismatches."],
['missing', 'm', "Show 'orphaned' homes."],
['double', 'd', "Detect double-bookings."],
+ ['dark-purge', 'p', "Purge room/resource events with invalid organizer."],
['fix', 'x', "Fix problems."],
['verbose', 'v', "Verbose logging."],
['details', 'V', "Detailed logging."],
['summary', 'S', "Summary of double-bookings."],
['tzid', 't', "Timezone to adjust displayed times to."],
- ]
+ ['no-organizer', '', "Detect dark events without an organizer"],
+ ['invalid-organizer', '', "Detect dark events with an organizer not in the directory"],
+ ['disabled-organizer', '', "Detect dark events with a disabled organizer"],
+]
+
optParameters = [
['config', 'f', DEFAULT_CONFIG_FILE, "Specify caldavd.plist configuration path."],
['uuid', 'u', "", "Only check this user."],
@@ -564,7 +590,32 @@
cb = schema.CALENDAR_BIND
ch = schema.CALENDAR_HOME
tr = schema.TIME_RANGE
+ kwds = {
+ "Start" : pyCalendarTodatetime(start),
+ "Max" : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
+ "UUID" : uuid,
+ }
+ rows = (yield Select(
+ [ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED],
+ From=ch.join(
+ cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID)).join(
+ co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
+ cb.BIND_MODE == _BIND_MODE_OWN).And(
+ cb.CALENDAR_RESOURCE_NAME != "inbox")).join(
+ tr, type="left", on=(co.RESOURCE_ID == tr.CALENDAR_OBJECT_RESOURCE_ID)),
+ Where=(ch.OWNER_UID == Parameter("UUID")).And((tr.START_DATE >= Parameter("Start")).Or(co.RECURRANCE_MAX <= Parameter("Start"))),
+ GroupBy=(ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED,),
+ ).on(self.txn, **kwds))
+ returnValue(tuple(rows))
+
+ @inlineCallbacks
+ def getAllResourceInfoTimeRangeWithUUIDForAllUID(self, start, uuid):
+ co = schema.CALENDAR_OBJECT
+ cb = schema.CALENDAR_BIND
+ ch = schema.CALENDAR_HOME
+ tr = schema.TIME_RANGE
+
cojoin = (cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
cb.BIND_MODE == _BIND_MODE_OWN).And(
cb.CALENDAR_RESOURCE_NAME != "inbox")
@@ -1370,8 +1421,8 @@
rows = yield self.getAllResourceInfoWithUID(self.options["uid"])
descriptor = "getAllResourceInfoWithUID"
elif self.options["uuid"]:
- rows = yield self.getAllResourceInfoTimeRangeWithUUID(self.start, self.options["uuid"])
- descriptor = "getAllResourceInfoTimeRangeWithUUID"
+ rows = yield self.getAllResourceInfoTimeRangeWithUUIDForAllUID(self.start, self.options["uuid"])
+ descriptor = "getAllResourceInfoTimeRangeWithUUIDForAllUID"
self.options["uuid"] = None
else:
rows = yield self.getAllResourceInfoTimeRange(self.start)
@@ -2357,6 +2408,244 @@
+class DarkPurgeService(CalVerifyService):
+ """
+ Service which detects room/resource events that have an invalid organizer.
+ """
+
+ def title(self):
+ return "Dark Purge Service"
+
+
+ @inlineCallbacks
+ def doAction(self):
+
+ if not self.options["no-organizer"] and not self.options["invalid-organizer"] and not self.options["disabled-organizer"]:
+ self.options["invalid-organizer"] = self.options["disabled-organizer"] = True
+
+ self.output.write("\n---- Scanning calendar data ----\n")
+
+ self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+ self.now = PyCalendarDateTime.getNowUTC()
+ self.start = self.options["start"] if "start" in self.options else PyCalendarDateTime.getToday()
+ self.start.setDateOnly(False)
+ self.start.setTimezone(self.tzid)
+ self.fix = self.options["fix"]
+
+ if self.options["verbose"] and self.options["summary"]:
+ ot = time.time()
+
+ # Check loop over uuid
+ UUIDDetails = collections.namedtuple("UUIDDetails", ("uuid", "rname", "purged",))
+ self.uuid_details = []
+ if len(self.options["uuid"]) != 36:
+ self.txn = self.store.newTransaction()
+ if self.options["uuid"]:
+ homes = yield self.getMatchingHomeUIDs(self.options["uuid"])
+ else:
+ homes = yield self.getAllHomeUIDs()
+ yield self.txn.commit()
+ self.txn = None
+ uuids = []
+ if self.options["verbose"]:
+ self.output.write("%d uuids to check\n" % (len(homes,)))
+ for uuid in sorted(homes):
+ record = self.directoryService().recordWithGUID(uuid)
+ if record is not None and record.recordType in (DirectoryService.recordType_locations, DirectoryService.recordType_resources):
+ uuids.append(uuid)
+ else:
+ uuids = [self.options["uuid"], ]
+ if self.options["verbose"]:
+ self.output.write("%d uuids to scan\n" % (len(uuids,)))
+
+ count = 0
+ for uuid in uuids:
+ self.results = {}
+ self.summary = []
+ self.total = 0
+ count += 1
+
+ record = self.directoryService().recordWithGUID(uuid)
+ if record is None:
+ continue
+ if not record.thisServer() or not record.enabledForCalendaring:
+ continue
+
+ rname = record.fullName
+
+ if len(uuids) > 1 and not self.options["summary"]:
+ self.output.write("\n\n-----------------------------\n")
+
+ self.txn = self.store.newTransaction()
+
+ if self.options["verbose"]:
+ t = time.time()
+ rows = yield self.getAllResourceInfoTimeRangeWithUUID(self.start, uuid)
+ descriptor = "getAllResourceInfoTimeRangeWithUUID"
+
+ yield self.txn.commit()
+ self.txn = None
+
+ if self.options["verbose"]:
+ if not self.options["summary"]:
+ self.output.write("%s time: %.1fs\n" % (descriptor, time.time() - t,))
+ else:
+ self.output.write("%s (%d/%d)" % (uuid, count, len(uuids),))
+ self.output.flush()
+
+ self.total = len(rows)
+ if not self.options["summary"]:
+ self.logResult("UUID to process", uuid)
+ self.logResult("Record name", rname)
+ self.addSummaryBreak()
+ self.logResult("Number of events to process", self.total)
+
+ if rows:
+ if not self.options["summary"]:
+ self.addSummaryBreak()
+ purged = yield self.darkPurge(rows, uuid)
+ else:
+ purged = False
+
+ self.uuid_details.append(UUIDDetails(uuid, rname, purged))
+
+ if not self.options["summary"]:
+ self.printSummary()
+ else:
+ self.output.write(" - %s\n" % ("Dark Events" if purged else "OK",))
+ self.output.flush()
+
+ if count == 0:
+ self.output.write("Nothing to scan\n")
+
+ if self.options["summary"]:
+ table = tables.Table()
+ table.addHeader(("GUID", "Name", "RID", "UID", "Organizer",))
+ purged = 0
+ for item in sorted(self.uuid_details):
+ if not item.purged:
+ continue
+ uuid = item.uuid
+ rname = item.rname
+ for detail in item.purged:
+ table.addRow((
+ uuid,
+ rname,
+ detail.resid,
+ detail.uid,
+ detail.organizer,
+ ))
+ uuid = ""
+ rname = ""
+ purged += 1
+ table.addFooter(("Total", "%d" % (purged,), "", "", "",))
+ self.output.write("\n")
+ table.printTable(os=self.output)
+
+ if self.options["verbose"]:
+ self.output.write("%s time: %.1fs\n" % ("Summary", time.time() - ot,))
+
+
+ @inlineCallbacks
+ def darkPurge(self, rows, uuid):
+ """
+ Check each calendar resource by looking at any ORGANIER property value and verifying it is valid.
+ """
+
+ if not self.options["summary"]:
+ self.output.write("\n---- Checking for dark events ----\n")
+ self.txn = self.store.newTransaction()
+
+ if self.options["verbose"]:
+ t = time.time()
+
+ Details = collections.namedtuple("Details", ("resid", "uid", "organizer",))
+
+ count = 0
+ total = len(rows)
+ details = []
+ fixed = 0
+ rjust = 10
+ for resid in rows:
+ resid = resid[1]
+ caldata = yield self.getCalendar(resid, self.fix)
+ if caldata is None:
+ if self.parseError:
+ returnValue((False, self.parseError))
+ else:
+ returnValue((True, "Nothing to scan"))
+
+ cal = Component(None, pycalendar=caldata)
+ uid = cal.resourceUID()
+
+ fail = False
+ organizer = cal.getOrganizer()
+ if organizer is None:
+ if self.options["no-organizer"]:
+ fail = True
+ else:
+ principal = self.directoryService().principalForCalendarUserAddress(organizer)
+ if principal is None and organizer.startswith("urn:uuid:"):
+ principal = self.directoryService().principalCollection.principalForUID(organizer[9:])
+ if principal is None:
+ if self.options["invalid-organizer"]:
+ fail = True
+ elif not principal.calendarsEnabled():
+ if self.options["disabled-organizer"]:
+ fail = True
+
+ if fail:
+ details.append(Details(resid, uid, organizer,))
+ if self.fix:
+ yield self.removeEvent(resid)
+ fixed += 1
+
+ if self.options["verbose"] and not self.options["summary"]:
+ if count == 1:
+ self.output.write("Current".rjust(rjust) + "Total".rjust(rjust) + "Complete".rjust(rjust) + "\n")
+ if divmod(count, 100)[1] == 0:
+ self.output.write((
+ "\r" +
+ ("%s" % count).rjust(rjust) +
+ ("%s" % total).rjust(rjust) +
+ ("%d%%" % safePercent(count, total)).rjust(rjust)
+ ).ljust(80))
+ self.output.flush()
+
+ # To avoid holding locks on all the rows scanned, commit every 100 resources
+ if divmod(count, 100)[1] == 0:
+ yield self.txn.commit()
+ self.txn = self.store.newTransaction()
+
+ yield self.txn.commit()
+ self.txn = None
+ if self.options["verbose"] and not self.options["summary"]:
+ self.output.write((
+ "\r" +
+ ("%s" % count).rjust(rjust) +
+ ("%s" % total).rjust(rjust) +
+ ("%d%%" % safePercent(count, total)).rjust(rjust)
+ ).ljust(80) + "\n")
+
+ # Print table of results
+ if not self.options["summary"]:
+ self.logResult("Number of dark events", len(details))
+
+ self.results["Dark Events"] = details
+ if self.fix:
+ self.results["Fix dark events"] = fixed
+
+ if self.options["verbose"] and not self.options["summary"]:
+ diff_time = time.time() - t
+ self.output.write("Time: %.2f s Average: %.1f ms/resource\n" % (
+ diff_time,
+ safePercent(diff_time, total, 1000.0),
+ ))
+
+ returnValue(details)
+
+
+
def main(argv=sys.argv, stderr=sys.stderr, reactor=None):
if reactor is None:
@@ -2387,6 +2676,11 @@
return SchedulingMismatchService(store, options, output, reactor, config)
elif options["double"]:
return DoubleBookingService(store, options, output, reactor, config)
+ elif options["dark-purge"]:
+ return DarkPurgeService(store, options, output, reactor, config)
+ else:
+ printusage("Invalid operation")
+ sys.exit(1)
utilityMain(options['config'], makeService, reactor)
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/config.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/config.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/config.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -158,6 +158,7 @@
rawInput = sys.stdin.read()
try:
plist = readPlistFromString(rawInput)
+ # Note: values in plist will already be unicode
except xml.parsers.expat.ExpatError, e:
respondWithError(str(e))
return
@@ -234,6 +235,10 @@
for keyPath in WRITABLE_CONFIG_KEYS:
value = getKeyPath(config, keyPath)
if value is not None:
+ # Note: config contains utf-8 encoded strings, but plistlib
+ # wants unicode, so decode here:
+ if isinstance(value, str):
+ value = value.decode("utf-8")
setKeyPath(result, keyPath, value)
respond(command, result)
@@ -247,6 +252,7 @@
writable = WritableConfig(config, config.WritableConfigFile)
writable.read()
valuesToWrite = command.get("Values", {})
+ # Note: values are unicode if they contain non-ascii
for keyPath, value in flattenDictionary(valuesToWrite):
if keyPath in WRITABLE_CONFIG_KEYS:
writable.set(setKeyPath(ConfigDict(), keyPath, value))
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_calverify.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_calverify.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_calverify.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -19,10 +19,11 @@
Tests for calendarserver.tools.calverify
"""
+from calendarserver.tools.calverify import BadDataService, \
+ SchedulingMismatchService, DoubleBookingService, DarkPurgeService
+
from StringIO import StringIO
from calendarserver.tap.util import getRootResource
-from calendarserver.tools.calverify import BadDataService, \
- SchedulingMismatchService, DoubleBookingService
from pycalendar.datetime import PyCalendarDateTime
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue
@@ -2525,67 +2526,338 @@
self.assertEqual(sync_token_oldl1, sync_token_newl1)
- def test_instance(self):
- """
- CalVerifyService.doScan without fix for mismatches. Make sure it detects
- as much as it can. Make sure sync-token is not changed.
- """
- s = """BEGIN:VCALENDAR
+class CalVerifyDarkPurge(CalVerifyMismatchTestsBase):
+ """
+ Tests calverify for events.
+ """
+
+ # No organizer
+ INVITE_NO_ORGANIZER_ICS = """BEGIN:VCALENDAR
VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
CALSCALE:GREGORIAN
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VTIMEZONE
-TZID:America/Los_Angeles
-BEGIN:DAYLIGHT
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
-TZNAME:PDT
-TZOFFSETFROM:-0800
-TZOFFSETTO:-0700
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
-TZNAME:PST
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0800
-END:STANDARD
-END:VTIMEZONE
BEGIN:VEVENT
-UID:4760FF93-C7F8-4EB0-B3E8-0B22A96DB1BC
-DTSTART;TZID=America/Los_Angeles:20130221T170000
-DTEND;TZID=America/Los_Angeles:20130221T180000
-ATTENDEE;CN=Casa Blanca APPLE EMP ONLY (12) DA03 4th;CUTYPE=ROOM;PARTSTAT=
- ACCEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:366CC7BE-FEF7-4FFF-B713-6B883538A24
- 9
-ATTENDEE;CN=Mark Chu;CUTYPE=INDIVIDUAL;EMAIL=markchu at apple.com;PARTSTAT=AC
- CEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:46F9D5D9-08E8-4987-9636-CC796F4093C6
-ATTENDEE;CN=Kristie Phan;CUTYPE=INDIVIDUAL;EMAIL=kristie_phan at apple.com;PA
- RTSTAT=ACCEPTED:urn:uuid:97E8720F-4364-DBEC-6721-123E9A92B980
-CREATED:20130220T200530Z
-DTSTAMP:20130222T002246Z
-EXDATE:20130228T010000Z
-EXDATE:20130314T000000Z
-EXDATE:20130321T000000Z
-EXDATE:20130327T000000Z
-EXDATE:20130328T000000Z
-EXDATE:20130403T000000Z
-LOCATION:Casa Blanca APPLE EMP ONLY (12) DA03 4th
-ORGANIZER;CN=Kristie Phan;EMAIL=kristie_phan at apple.com;SCHEDULE-STATUS=1.2
- :urn:uuid:97E8720F-4364-DBEC-6721-123E9A92B980
-RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;WKST=SU
-SEQUENCE:13
-SUMMARY:ESD Daily Meeting
+CREATED:20100303T181216Z
+UID:INVITE_NO_ORGANIZER_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_ORGANIZER_ICS
+DTSTART:%(year)s%(month)02d07T100000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
END:VEVENT
END:VCALENDAR
-"""
- from twistedcaldav.ical import Component
- c = Component.fromString(s)
- start = PyCalendarDateTime.getToday()
- start.setDateOnly(False)
- end = start.duplicate()
- end.offsetDay(30)
- config.MaxAllowedInstances = 3000
- i = c.expandTimeRanges(end, start, ignoreInvalidInstances=True)
- print(i)
+""".replace("\n", "\r\n") % {"year": nowYear, "month": nowMonth}
+
+ # Valid organizer
+ INVITE_VALID_ORGANIZER_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_VALID_ORGANIZER_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_VALID_ORGANIZER_ICS
+DTSTART:%(year)s%(month)02d08T100000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": nowYear, "month": nowMonth}
+
+ # Invalid organizer #1
+ INVITE_INVALID_ORGANIZER_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_INVALID_ORGANIZER_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_INVALID_ORGANIZER_1_ICS
+DTSTART:%(year)s%(month)02d09T100000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0-1
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0-1
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": nowYear, "month": nowMonth}
+
+ # Invalid organizer #2
+ INVITE_INVALID_ORGANIZER_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_INVALID_ORGANIZER_2_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_INVALID_ORGANIZER_2_ICS
+DTSTART:%(year)s%(month)02d10T100000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:mailto:foobar at example.com
+ATTENDEE:mailto:foobar at example.com
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": nowYear, "month": nowMonth}
+
+ allEvents = {
+ "invite1.ics" : (INVITE_NO_ORGANIZER_ICS, CalVerifyMismatchTestsBase.metadata,),
+ "invite2.ics" : (INVITE_VALID_ORGANIZER_ICS, CalVerifyMismatchTestsBase.metadata,),
+ "invite3.ics" : (INVITE_INVALID_ORGANIZER_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+ "invite4.ics" : (INVITE_INVALID_ORGANIZER_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+ }
+
+ requirements = {
+ CalVerifyMismatchTestsBase.uuid1 : {
+ "calendar" : {},
+ "inbox" : {},
+ },
+ CalVerifyMismatchTestsBase.uuid2 : {
+ "calendar" : {},
+ "inbox" : {},
+ },
+ CalVerifyMismatchTestsBase.uuid3 : {
+ "calendar" : {},
+ "inbox" : {},
+ },
+ CalVerifyMismatchTestsBase.uuidl1 : {
+ "calendar" : allEvents,
+ "inbox" : {},
+ },
+ }
+
+ @inlineCallbacks
+ def test_scanDarkEvents(self):
+ """
+ CalVerifyService.doScan without fix for dark events. Make sure it detects
+ as much as it can. Make sure sync-token is not changed.
+ """
+
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.commit()
+
+ options = {
+ "ical": False,
+ "badcua": False,
+ "mismatch": False,
+ "nobase64": False,
+ "double": True,
+ "dark-purge": False,
+ "fix": False,
+ "verbose": False,
+ "details": False,
+ "summary": False,
+ "days": 365,
+ "uid": "",
+ "uuid": self.uuidl1,
+ "tzid": "utc",
+ "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+ "no-organizer": False,
+ "invalid-organizer": False,
+ "disabled-organizer": False,
+ }
+ output = StringIO()
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], len(self.requirements[CalVerifyMismatchTestsBase.uuidl1]["calendar"]))
+ self.assertEqual(
+ sorted([i.uid for i in calverify.results["Dark Events"]]),
+ ["INVITE_INVALID_ORGANIZER_1_ICS", "INVITE_INVALID_ORGANIZER_2_ICS", ]
+ )
+ self.assertEqual(calverify.results["Number of dark events"], 2)
+ self.assertTrue("Fix dark events" not in calverify.results)
+ self.assertTrue("Fix remove" not in calverify.results)
+
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.assertEqual(sync_token_oldl1, sync_token_newl1)
+
+
+ @inlineCallbacks
+ def test_fixDarkEvents(self):
+ """
+ CalVerifyService.doScan with fix for dark events. Make sure it detects
+ as much as it can. Make sure sync-token is changed.
+ """
+
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.commit()
+
+ options = {
+ "ical": False,
+ "badcua": False,
+ "mismatch": False,
+ "nobase64": False,
+ "double": True,
+ "dark-purge": False,
+ "fix": True,
+ "verbose": False,
+ "details": False,
+ "summary": False,
+ "days": 365,
+ "uid": "",
+ "uuid": self.uuidl1,
+ "tzid": "utc",
+ "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+ "no-organizer": False,
+ "invalid-organizer": False,
+ "disabled-organizer": False,
+ }
+ output = StringIO()
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], len(self.requirements[CalVerifyMismatchTestsBase.uuidl1]["calendar"]))
+ self.assertEqual(
+ sorted([i.uid for i in calverify.results["Dark Events"]]),
+ ["INVITE_INVALID_ORGANIZER_1_ICS", "INVITE_INVALID_ORGANIZER_2_ICS", ]
+ )
+ self.assertEqual(calverify.results["Number of dark events"], 2)
+ self.assertEqual(calverify.results["Fix dark events"], 2)
+ self.assertTrue("Fix remove" in calverify.results)
+
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
+
+ # Re-scan after changes to make sure there are no errors
+ self.commit()
+ options["fix"] = False
+ options["uuid"] = self.uuidl1
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], 2)
+ self.assertEqual(len(calverify.results["Dark Events"]), 0)
+ self.assertTrue("Fix dark events" not in calverify.results)
+ self.assertTrue("Fix remove" not in calverify.results)
+
+
+ @inlineCallbacks
+ def test_fixDarkEventsNoOrganizerOnly(self):
+ """
+ CalVerifyService.doScan with fix for dark events. Make sure it detects
+ as much as it can. Make sure sync-token is changed.
+ """
+
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.commit()
+
+ options = {
+ "ical": False,
+ "badcua": False,
+ "mismatch": False,
+ "nobase64": False,
+ "double": True,
+ "dark-purge": False,
+ "fix": True,
+ "verbose": False,
+ "details": False,
+ "summary": False,
+ "days": 365,
+ "uid": "",
+ "uuid": self.uuidl1,
+ "tzid": "utc",
+ "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+ "no-organizer": True,
+ "invalid-organizer": False,
+ "disabled-organizer": False,
+ }
+ output = StringIO()
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], len(self.requirements[CalVerifyMismatchTestsBase.uuidl1]["calendar"]))
+ self.assertEqual(
+ sorted([i.uid for i in calverify.results["Dark Events"]]),
+ ["INVITE_NO_ORGANIZER_ICS", ]
+ )
+ self.assertEqual(calverify.results["Number of dark events"], 1)
+ self.assertEqual(calverify.results["Fix dark events"], 1)
+ self.assertTrue("Fix remove" in calverify.results)
+
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
+
+ # Re-scan after changes to make sure there are no errors
+ self.commit()
+ options["fix"] = False
+ options["uuid"] = self.uuidl1
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], 3)
+ self.assertEqual(len(calverify.results["Dark Events"]), 0)
+ self.assertTrue("Fix dark events" not in calverify.results)
+ self.assertTrue("Fix remove" not in calverify.results)
+
+
+ @inlineCallbacks
+ def test_fixDarkEventsAllTypes(self):
+ """
+ CalVerifyService.doScan with fix for dark events. Make sure it detects
+ as much as it can. Make sure sync-token is changed.
+ """
+
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.commit()
+
+ options = {
+ "ical": False,
+ "badcua": False,
+ "mismatch": False,
+ "nobase64": False,
+ "double": True,
+ "dark-purge": False,
+ "fix": True,
+ "verbose": False,
+ "details": False,
+ "summary": False,
+ "days": 365,
+ "uid": "",
+ "uuid": self.uuidl1,
+ "tzid": "utc",
+ "start": PyCalendarDateTime(nowYear, 1, 1, 0, 0, 0),
+ "no-organizer": True,
+ "invalid-organizer": True,
+ "disabled-organizer": True,
+ }
+ output = StringIO()
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], len(self.requirements[CalVerifyMismatchTestsBase.uuidl1]["calendar"]))
+ self.assertEqual(
+ sorted([i.uid for i in calverify.results["Dark Events"]]),
+ ["INVITE_INVALID_ORGANIZER_1_ICS", "INVITE_INVALID_ORGANIZER_2_ICS", "INVITE_NO_ORGANIZER_ICS", ]
+ )
+ self.assertEqual(calverify.results["Number of dark events"], 3)
+ self.assertEqual(calverify.results["Fix dark events"], 3)
+ self.assertTrue("Fix remove" in calverify.results)
+
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
+
+ # Re-scan after changes to make sure there are no errors
+ self.commit()
+ options["fix"] = False
+ options["uuid"] = self.uuidl1
+ calverify = DarkPurgeService(self._sqlCalendarStore, options, output, reactor, config)
+ yield calverify.doAction()
+
+ self.assertEqual(calverify.results["Number of events to process"], 1)
+ self.assertEqual(len(calverify.results["Dark Events"]), 0)
+ self.assertTrue("Fix dark events" not in calverify.results)
+ self.assertTrue("Fix remove" not in calverify.results)
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_config.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_config.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_config.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -119,6 +119,8 @@
self.assertEquals(results["result"]["EnableSSL"], True)
self.assertEquals(results["result"]["Notifications"]["Services"]["APNS"]["Enabled"], True)
self.assertEquals(results["result"]["Notifications"]["Services"]["APNS"]["CalDAV"]["CertificatePath"], "/example/changed.cer")
+ dataRoot = "Data/%s/%s" % (unichr(208), u"\ud83d\udca3")
+ self.assertTrue(results["result"]["DataRoot"].endswith(dataRoot))
# The static plist should still have EnableCalDAV = True
staticPlist = plistlib.readPlist(self.configFileName)
@@ -204,10 +206,12 @@
<true/>
<key>Notifications.Services.APNS.CalDAV.CertificatePath</key>
<string>/example/changed.cer</string>
+ <key>DataRoot</key>
+ <string>Data/%s/%s</string>
</dict>
</dict>
</plist>
-"""
+""" % (unichr(208), u"\ud83d\udca3")
command_bogusCommand = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_gateway.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/test/test_gateway.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -124,7 +124,8 @@
self.assertEquals(results["result"]["RecordName"], ["createdlocation01"])
self.assertEquals(results["result"]["State"], "CA")
self.assertEquals(results["result"]["Street"], "1 Infinite Loop")
- self.assertEquals(results["result"]["RealName"], "Created Location 01 %s" % unichr(208))
+ self.assertEquals(results["result"]["RealName"],
+ "Created Location 01 %s %s" % (unichr(208), u"\ud83d\udca3" ))
self.assertEquals(results["result"]["Comment"], "Test Comment")
self.assertEquals(results["result"]["AutoSchedule"], True)
self.assertEquals(results["result"]["AutoAcceptGroup"], "E5A6142C-4189-4E9E-90B0-9CD0268B314B")
@@ -151,7 +152,6 @@
record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
self.assertEquals(record, None)
-
yield self.runCommand(command_createLocation)
directory.flushCaches()
@@ -162,7 +162,8 @@
augmentService.refresh()
record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
- self.assertEquals(record.fullName.decode("utf-8"), "Created Location 01 %s" % unichr(208))
+ self.assertEquals(record.fullName.decode("utf-8"),
+ "Created Location 01 %s %s" % (unichr(208), u"\ud83d\udca3"))
self.assertNotEquals(record, None)
self.assertEquals(record.autoSchedule, True)
@@ -334,7 +335,7 @@
<key>GeneratedUID</key>
<string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
<key>RealName</key>
- <string>Created Location 01 %s</string>
+ <string>Created Location 01 %s %s</string>
<key>RecordName</key>
<array>
<string>createdlocation01</string>
@@ -373,7 +374,7 @@
</array>
</dict>
</plist>
-""" % unichr(208)
+""" % (unichr(208), u"\ud83d\udca3")
command_createResource = """<?xml version="1.0" encoding="UTF-8"?>
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/util.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/calendarserver/tools/util.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -76,6 +76,8 @@
return config
+
+
def getDirectory(config=config):
class MyDirectoryService (AggregateDirectoryService):
@@ -93,7 +95,7 @@
notifierFactory = None
# Need a data store
- _newStore = CommonDataStore(FilePath(config.DocumentRoot),
+ _newStore = CommonDataStore(FilePath(config.DocumentRoot),
notifierFactory, True, False)
if notifierFactory is not None:
notifierFactory.store = _newStore
@@ -136,6 +138,8 @@
def principalForCalendarUserAddress(self, cua):
return self.principalCollection.principalForCalendarUserAddress(cua)
+ def principalForUID(self, uid):
+ return self.principalCollection.principalForUID(uid)
# Load augment/proxy db classes now
if config.AugmentService.type:
@@ -154,7 +158,6 @@
while not directory.isAvailable():
sleep(5)
-
directories = [directory]
if config.ResourceService.Enabled:
@@ -189,34 +192,47 @@
return aggregate
+
+
class DummyDirectoryService (DirectoryService):
realmName = ""
baseGUID = "51856FD4-5023-4890-94FE-4356C4AAC3E4"
- def recordTypes(self): return ()
- def listRecords(self): return ()
- def recordWithShortName(self): return None
+ def recordTypes(self):
+ return ()
+
+ def listRecords(self):
+ return ()
+
+
+ def recordWithShortName(self):
+ return None
+
dummyDirectoryRecord = DirectoryRecord(
- service = DummyDirectoryService(),
- recordType = "dummy",
- guid = "8EF0892F-7CB6-4B8E-B294-7C5A5321136A",
- shortNames = ("dummy",),
- fullName = "Dummy McDummerson",
- firstName = "Dummy",
- lastName = "McDummerson",
+ service=DummyDirectoryService(),
+ recordType="dummy",
+ guid="8EF0892F-7CB6-4B8E-B294-7C5A5321136A",
+ shortNames=("dummy",),
+ fullName="Dummy McDummerson",
+ firstName="Dummy",
+ lastName="McDummerson",
)
class UsageError (StandardError):
pass
+
+
def booleanArgument(arg):
- if arg in ("true", "yes", "yup", "uh-huh", "1", "t", "y"):
+ if arg in ("true", "yes", "yup", "uh-huh", "1", "t", "y"):
return True
- elif arg in ("false", "no", "nope", "nuh-uh", "0", "f", "n"):
+ elif arg in ("false", "no", "nope", "nuh-uh", "0", "f", "n"):
return False
else:
raise ValueError("Not a boolean: %s" % (arg,))
+
+
def autoDisableMemcached(config):
"""
If memcached is not running, set config.Memcached.ClientEnabled to False
@@ -235,6 +251,7 @@
config.Memcached.Pools.Default.ClientEnabled = False
+
def setupMemcached(config):
#
# Connect to memcached
@@ -246,6 +263,7 @@
autoDisableMemcached(config)
+
def checkDirectory(dirpath, description, access=None, create=None, wait=False):
"""
Make sure dirpath is an existing directory, and optionally ensure it has the
@@ -319,9 +337,9 @@
def principalForPrincipalID(principalID, checkOnly=False, directory=None):
-
+
# Allow a directory parameter to be passed in, but default to config.directory
- # But config.directory isn't set right away, so only use it when we're doing more
+ # But config.directory isn't set right away, so only use it when we're doing more
# than checking.
if not checkOnly and not directory:
directory = config.directory
@@ -339,7 +357,6 @@
return directory.principalCollection.principalForUID(uid)
-
if principalID.startswith("("):
try:
i = principalID.index(")")
@@ -348,7 +365,7 @@
return None
recordType = principalID[1:i]
- shortName = principalID[i+1:]
+ shortName = principalID[i + 1:]
if not recordType or not shortName or "(" in recordType:
raise ValueError()
@@ -379,9 +396,13 @@
raise ValueError("Invalid principal identifier: %s" % (principalID,))
+
+
def proxySubprincipal(principal, proxyType):
return principal.getChild("calendar-proxy-" + proxyType)
+
+
@inlineCallbacks
def action_addProxyPrincipal(rootResource, directory, store, principal, proxyType, proxyPrincipal):
try:
@@ -394,6 +415,8 @@
except ProxyWarning, e:
print(e)
+
+
@inlineCallbacks
def action_removeProxyPrincipal(rootResource, directory, store, principal, proxyPrincipal, **kwargs):
try:
@@ -408,6 +431,8 @@
except ProxyWarning, e:
print(e)
+
+
@inlineCallbacks
def addProxy(rootResource, directory, store, principal, proxyType, proxyPrincipal):
proxyURL = proxyPrincipal.url()
@@ -439,6 +464,8 @@
yield scheduleNextGroupCachingUpdate(store, 0)
+
+
@inlineCallbacks
def removeProxy(rootResource, directory, store, principal, proxyPrincipal, **kwargs):
removed = False
@@ -478,16 +505,17 @@
return "\"%s\" (%s:%s)" % (record.fullName, record.recordType,
record.shortNames[0])
+
+
class ProxyError(Exception):
"""
Raised when proxy assignments cannot be performed
"""
+
+
class ProxyWarning(Exception):
"""
Raised for harmless proxy assignment failures such as trying to add a
duplicate or remove a non-existent assignment.
"""
-
-
-
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/contrib/performance/loadtest/ical.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/contrib/performance/loadtest/ical.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -1186,7 +1186,7 @@
self._pushFactories.append(factory)
connect(GAIEndpoint(self.reactor, host, port), factory)
- def _receivedPush(self, inboundID):
+ def _receivedPush(self, inboundID, dataChangedTimestamp):
for href, id in self.ampPushKeys.iteritems():
if inboundID == id:
self._checkCalendarsForEvents(href, push=True)
Copied: CalendarServer/branches/users/glyph/sharedgroups-2/doc/RFC/RFC6868-Parameter Value Encoding.txt (from rev 11020, CalendarServer/trunk/doc/RFC/RFC6868-Parameter Value Encoding.txt)
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/doc/RFC/RFC6868-Parameter Value Encoding.txt (rev 0)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/doc/RFC/RFC6868-Parameter Value Encoding.txt 2013-04-16 22:22:28 UTC (rev 11054)
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF) C. Daboo
+Request for Comments: 6868 Apple
+Updates: 5545, 6321, 6350, 6351 February 2013
+Category: Standards Track
+ISSN: 2070-1721
+
+
+ Parameter Value Encoding in iCalendar and vCard
+
+Abstract
+
+ This specification updates the data formats for iCalendar (RFC 5545)
+ and vCard (RFC 6350) to allow parameter values to include certain
+ characters forbidden by the existing specifications.
+
+Status of This Memo
+
+ This is an Internet Standards Track document.
+
+ This document is a product of the Internet Engineering Task Force
+ (IETF). It represents the consensus of the IETF community. It has
+ received public review and has been approved for publication by the
+ Internet Engineering Steering Group (IESG). Further information on
+ Internet Standards is available in Section 2 of RFC 5741.
+
+ Information about the current status of this document, any errata,
+ and how to provide feedback on it may be obtained at
+ http://www.rfc-editor.org/info/rfc6868.
+
+Copyright Notice
+
+ Copyright (c) 2013 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info) in effect on the date of
+ publication of this document. Please review these documents
+ carefully, as they describe your rights and restrictions with respect
+ to this document. Code Components extracted from this document must
+ include Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 1]
+
+RFC 6868 Parameter Encoding February 2013
+
+
+Table of Contents
+
+ 1. Introduction ....................................................2
+ 2. Conventions Used in This Document ...............................2
+ 3. Parameter Value Encoding Scheme .................................3
+ 3.1. iCalendar Example ..........................................4
+ 3.2. vCard Example ..............................................4
+ 4. Security Considerations .........................................4
+ 5. Acknowledgments .................................................4
+ 6. Normative References ............................................5
+ Appendix A. Choice of Quoting Mechanism ............................6
+
+1. Introduction
+
+ The iCalendar [RFC5545] specification defines a standard way to
+ describe calendar data. The vCard [RFC6350] specification defines a
+ standard way to describe contact data. Both of these use a similar
+ text-based data format. Each iCalendar and vCard data object can
+ include "properties" that have "parameters" and a "value". The value
+ of a "parameter" is typically a token or URI value, but a "generic"
+ text value is also allowed. However, the syntax rules for both
+ iCalendar and vCard prevent the use of a double-quote character or
+ control characters in such values, though double-quote characters and
+ some subset of control characters are allowed in the actual property
+ values.
+
+ As more and more extensions are being developed for these data
+ formats, there is a need to allow at least double-quotes and line
+ feeds to be included in parameter values. The \-escaping mechanism
+ used for property text values is not defined for use with parameter
+ values and cannot be easily used in a backwards-compatible manner.
+ This specification defines a new character escaping mechanism,
+ compatible with existing parsers and chosen to minimize any impact on
+ existing data.
+
+2. Conventions Used in This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
+ "OPTIONAL" in this document are to be interpreted as described in
+ [RFC2119].
+
+
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 2]
+
+RFC 6868 Parameter Encoding February 2013
+
+
+3. Parameter Value Encoding Scheme
+
+ This specification defines the ^ character (U+005E -- Circumflex
+ Accent) as an escape character in parameter values whose value type
+ is defined using the "param-value" syntax element (Section 3.1 of
+ iCalendar [RFC5545] and Section 3.3 of vCard [RFC6350]). The
+ ^-escaping mechanism can be used when the value is either unquoted or
+ quoted (i.e., whether or not the value is surrounded by double-
+ quotes).
+
+ When generating iCalendar or vCard parameter values, the following
+ apply:
+
+ o formatted text line breaks are encoded into ^n (U+005E, U+006E)
+
+ o the ^ character (U+005E) is encoded into ^^ (U+005E, U+005E)
+
+ o the " character (U+0022) is encoded into ^' (U+005E, U+0027)
+
+ When parsing iCalendar or vCard parameter values, the following
+ apply:
+
+ o the character sequence ^n (U+005E, U+006E) is decoded into an
+ appropriate formatted line break according to the type of system
+ being used
+
+ o the character sequence ^^ (U+005E, U+005E) is decoded into the ^
+ character (U+005E)
+
+ o the character sequence ^' (U+005E, U+0027) is decoded into the "
+ character (U+0022)
+
+ o if a ^ (U+005E) character is followed by any character other than
+ the ones above, parsers MUST leave both the ^ and the following
+ character in place
+
+ When converting between iCalendar and vCard text-based data formats
+ and alternative data-format representations such as XML (as described
+ in [RFC6321] and [RFC6351], respectively), implementations MUST
+ ensure that parameter value escape sequences are generated correctly
+ in the text-based format and are decoded when the parameter values
+ appear in the alternate data formats.
+
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 3]
+
+RFC 6868 Parameter Encoding February 2013
+
+
+3.1. iCalendar Example
+
+ The following example is an "ATTENDEE" property with a "CN" parameter
+ whose value includes two double-quote characters. The parameter
+ value is not quoted, as there are no characters in the value that
+ would trigger quoting as required by iCalendar.
+
+ ATTENDEE;CN=George Herman ^'Babe^' Ruth:mailto:babe at example.com
+
+ The unescaped parameter value is
+
+ George Herman "Babe" Ruth
+
+3.2. vCard Example
+
+ The following example is a "GEO" property with an "X-ADDRESS"
+ parameter whose value includes several line feed characters. The
+ parameter value is also quoted, since it contains a comma, which
+ triggers quoting as required by vCard.
+
+ GEO;X-ADDRESS="Pittsburgh Pirates^n115 Federal St^nPitt
+ sburgh, PA 15212":geo:40.446816,-80.00566
+
+ The unescaped parameter value (where each line is terminated by a
+ line break character sequence) is
+
+ Pittsburgh Pirates
+ 115 Federal St
+ Pittsburgh, PA 15212
+
+4. Security Considerations
+
+ There are no additional security issues beyond those of iCalendar
+ [RFC5545] and vCard [RFC6350].
+
+5. Acknowledgments
+
+ Thanks to Michael Angstadt, Tim Bray, Mike Douglass, Barry Leiba,
+ Simon Perreault, and Pete Resnick for feedback on this specification.
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 4]
+
+RFC 6868 Parameter Encoding February 2013
+
+
+6. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC5545] Desruisseaux, B., "Internet Calendaring and Scheduling
+ Core Object Specification (iCalendar)", RFC 5545,
+ September 2009.
+
+ [RFC6321] Daboo, C., Douglass, M., and S. Lees, "xCal: The XML
+ Format for iCalendar", RFC 6321, August 2011.
+
+ [RFC6350] Perreault, S., "vCard Format Specification", RFC 6350,
+ August 2011.
+
+ [RFC6351] Perreault, S., "xCard: vCard XML Representation",
+ RFC 6351, August 2011.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 5]
+
+RFC 6868 Parameter Encoding February 2013
+
+
+Appendix A. Choice of Quoting Mechanism
+
+ Having recognized the need for escaping parameter values, the
+ question is what mechanism to use? One obvious choice would be to
+ adopt the \-escaping used for property values. However, that could
+ not be used as-is, because it escapes a double-quote as the sequence
+ of \ followed by double-quote. Consider what the example in
+ Section 3.1 might look like using \-escaping:
+
+ ATTENDEE;CN="George Herman \"Babe\" Ruth":mailto:babe at example.com
+
+ Existing iCalendar/vCard parsers know nothing about escape sequences
+ in parameters. So they would parse the parameter value as:
+
+ George Herman \
+
+ i.e., the text between the first and second occurrence of a double-
+ quote. However, the text after the second double-quote ought to be
+ either a : or a ; (to delimit the parameter value from the following
+ parameter or property) but is not, so the parser could legitimately
+ throw an error at that point because the data is syntactically
+ invalid. Thus, for backwards-compatibility reasons, a double-quote
+ cannot be escaped using a sequence that itself includes a double-
+ quote, and hence the choice of using a single-quote in this
+ specification.
+
+ Another option would be to use a form of \-escaping modified for use
+ in parameter values only. However, some incorrect, non-interoperable
+ use of \ in parameter values has been observed, and thus it is best
+ to steer clear of that to achieve guaranteed, reliable
+ interoperability. Also, given that double-quote gets changed to
+ single-quote in the escape sequence for a parameter, but not for a
+ value, it is better to not give the impression that the same escape
+ mechanism (and thus code) can be used for both (which could lead to
+ other issues, such as an implementation incorrectly escaping a ; as
+ \; as opposed to quoting the parameter value).
+
+ The choice of ^ as the escape character was made based on the
+ requirement that an ASCII symbol (non-alphanumeric character) be
+ used, and it ought to be one least likely to be found in existing
+ data.
+
+
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 6]
+
+RFC 6868 Parameter Encoding February 2013
+
+
+Author's Address
+
+ Cyrus Daboo
+ Apple Inc.
+ 1 Infinite Loop
+ Cupertino, CA 95014
+ USA
+
+ EMail: cyrus at daboo.name
+ URI: http://www.apple.com/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo Standards Track [Page 7]
+
\ No newline at end of file
Copied: CalendarServer/branches/users/glyph/sharedgroups-2/support/Apple.make (from rev 11020, CalendarServer/trunk/support/Apple.make)
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/support/Apple.make (rev 0)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/support/Apple.make 2013-04-16 22:22:28 UTC (rev 11054)
@@ -0,0 +1,170 @@
+# -*- mode: Makefile; -*-
+##
+# B&I Makefile for CalendarServer
+#
+# This is only useful internally at Apple, probably.
+##
+# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+# Project info
+Project = CalendarServer
+ProjectName = CalendarServer
+UserType = Server
+ToolType = Applications
+
+# Include common makefile targets for B&I
+include $(MAKEFILEPATH)/CoreOS/ReleaseControl/Common.make
+include /AppleInternal/ServerTools/ServerBuildVariables.xcconfig
+
+SIPP = $(SERVER_INSTALL_PATH_PREFIX)
+SERVERSETUP = $(SIPP)$(NSSYSTEMDIR)$(NSLIBRARYSUBDIR)/ServerSetup
+
+Cruft += .dependencies
+Extra_Environment += PATH="$(SIPP)/usr/bin:$$PATH"
+
+CALDAVDSUBDIR = /caldavd
+
+PYTHON = $(USRBINDIR)/python
+PY_HOME = $(SIPP)$(SHAREDIR)$(CALDAVDSUBDIR)
+PY_INSTALL_FLAGS = --root="$(DSTROOT)" --prefix="$(SIPP)" --install-lib="$(PY_HOME)/lib/python" --install-scripts="$(SIPP)$(LIBEXECDIR)$(CALDAVDSUBDIR)"
+CS_INSTALL_FLAGS = --install-scripts="$(SIPP)$(USRSBINDIR)" --install-data="$(SIPP)$(ETCDIR)"
+CS_BUILD_EXT_FLAGS = --include-dirs="$(SIPP)/usr/include" --library-dirs="$(SIPP)/usr/lib"
+
+CS_USER = _calendar
+CS_GROUP = _calendar
+
+#
+# Build
+#
+
+.phony: $(Project) pycalendar build setup prep install install-ossfiles buildit
+
+CalDAVTester:: $(BuildDirectory)/CalDAVTester
+PyKerberos:: $(BuildDirectory)/PyKerberos
+pycalendar:: $(BuildDirectory)/pycalendar
+PyGreSQL-4.0:: $(BuildDirectory)/PyGreSQL-4.0
+sqlparse-0.1.2:: $(BuildDirectory)/sqlparse-0.1.2
+setproctitle-1.1.6:: $(BuildDirectory)/setproctitle-1.1.6
+psutil-0.6.1:: $(BuildDirectory)/psutil-0.6.1
+pycrypto-2.5:: $(BuildDirectory)/pycrypto-2.5
+$(Project):: $(BuildDirectory)/$(Project)
+
+build:: PyKerberos pycalendar PyGreSQL-4.0 sqlparse-0.1.2 setproctitle-1.1.6 psutil-0.6.1 pycrypto-2.5 $(Project)
+
+setup:
+ $(_v) ./run -g
+
+prep:: setup CalDAVTester.tgz PyKerberos.tgz pycalendar.tgz PyGreSQL-4.0.tgz sqlparse-0.1.2.tgz setproctitle-1.1.6.tgz psutil-0.6.1.tgz pycrypto-2.5.tgz
+
+PyKerberos pycalendar PyGreSQL-4.0 sqlparse-0.1.2 setproctitle-1.1.6 psutil-0.6.1 pycrypto-2.5 $(Project)::
+ @echo "Building $@..."
+ $(_v) cd $(BuildDirectory)/$@ && $(Environment) $(PYTHON) setup.py build
+
+install:: build
+ $(_v) cd $(BuildDirectory)/$(Project) && $(Environment) $(PYTHON) setup.py build_ext $(CS_BUILD_EXT_FLAGS) install $(PY_INSTALL_FLAGS) $(CS_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/PyKerberos && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/pycalendar && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/PyGreSQL-4.0 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/sqlparse-0.1.2 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/setproctitle-1.1.6 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/psutil-0.6.1 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) cd $(BuildDirectory)/pycrypto-2.5 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
+ $(_v) for so in $$(find "$(DSTROOT)$(PY_HOME)/lib" -type f -name '*.so'); do $(STRIP) -Sx "$${so}"; done
+ $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(ETCDIR)$(CALDAVDSUBDIR)"
+ $(_v) $(INSTALL_FILE) "$(Sources)/conf/caldavd-apple.plist" "$(DSTROOT)$(SIPP)$(ETCDIR)$(CALDAVDSUBDIR)/caldavd-apple.plist"
+ $(_v) chmod -R ugo+r "$(DSTROOT)$(PY_HOME)"
+ $(_v) for f in $$(find "$(DSTROOT)$(SIPP)$(ETCDIR)" -type f ! -name '*.default'); do cp "$${f}" "$${f}.default"; done
+
+install::
+ @echo "Installing manual pages..."
+ $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/caldavd.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_bootstrap_database.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_command_gateway.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_export.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_manage_principals.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_migrate_resources.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_purge_attachments.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_purge_events.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_purge_principals.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_manage_push.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_shell.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
+ $(_v) gzip -9 -f "$(DSTROOT)$(SIPP)$(MANDIR)/man8/"*.[0-9]
+ @echo "Installing launchd config..."
+ $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(NSLOCALDIR)/$(NSLIBRARYSUBDIR)/Server/Calendar and Contacts"
+ $(_v) $(INSTALL_DIRECTORY) -o "$(CS_USER)" -g "$(CS_GROUP)" -m 0755 "$(DSTROOT)$(VARDIR)/log$(CALDAVDSUBDIR)"
+ $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(NSLIBRARYDIR)/LaunchDaemons"
+ $(_v) $(INSTALL_FILE) "$(Sources)/contrib/launchd/calendarserver.plist" "$(DSTROOT)$(SIPP)$(NSLIBRARYDIR)/LaunchDaemons/org.calendarserver.calendarserver.plist"
+ @echo "Installing changeip script..."
+ $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(LIBEXECDIR)/changeip"
+ $(_v) $(INSTALL_FILE) "$(Sources)/calendarserver/tools/changeip_calendar.py" "$(DSTROOT)$(SIPP)$(LIBEXECDIR)/changeip/changeip_calendar.py"
+ $(_v) chmod ugo+x "$(DSTROOT)$(SIPP)$(LIBEXECDIR)/changeip/changeip_calendar.py"
+
+install::
+ @echo "Installing CalDAVTester package..."
+ $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)/AppleInternal/ServerTools"
+ $(_v) $(INSTALL_FILE) "$(Sources)/CalDAVTester.tgz" "$(DSTROOT)/AppleInternal/ServerTools/CalDAVTester.tgz"
+
+#
+# Automatic Extract
+#
+
+$(BuildDirectory)/$(Project):
+ @echo "Copying source for $(Project)..."
+ $(_v) $(MKDIR) -p "$@"
+ $(_v) pax -rw bin conf Makefile lib-patches setup.py calendarserver twistedcaldav twext txdav twisted support "$@/"
+
+$(BuildDirectory)/%: %.tgz
+ @echo "Extracting source for $(notdir $<)..."
+ $(_v) $(MKDIR) -p "$(BuildDirectory)"
+ $(_v) $(RMDIR) "$@"
+ $(_v) $(TAR) -C "$(BuildDirectory)" -xzf "$<"
+
+%.tgz: ../%
+ @echo "Archiving sources for $(notdir $<)..."
+ $(_v) if [ -f "$</setup.py" ] && grep setuptools "$</setup.py" > /dev/null; then \
+ echo "Working around setuptools' stupid need to download a new version."; \
+ cd "$<" && $(PYTHON) "setup.py" --help >/dev/null; \
+ fi
+ $(_v) $(TAR) -C "$(dir $<)" \
+ --exclude=.svn \
+ --exclude=build \
+ --exclude=_trial_temp \
+ --exclude=dropin.cache \
+ -czf "$@" "$(notdir $<)"
+
+#
+# Open Source Hooey
+#
+
+OSV = $(USRDIR)/local/OpenSourceVersions
+OSL = $(USRDIR)/local/OpenSourceLicenses
+
+#install:: install-ossfiles
+
+install-ossfiles::
+ $(_v) $(INSTALL_DIRECTORY) $(DSTROOT)/$(OSV)
+ $(_v) $(INSTALL_FILE) $(Sources)/$(ProjectName).plist $(DSTROOT)/$(OSV)/$(ProjectName).plist
+ $(_v) $(INSTALL_DIRECTORY) $(DSTROOT)/$(OSL)
+ $(_v) $(INSTALL_FILE) $(BuildDirectory)/$(Project)/LICENSE $(DSTROOT)/$(OSL)/$(ProjectName).txt
+
+#
+# B&I Hooey
+#
+
+buildit: prep
+ @echo "Running buildit..."
+ $(_v) sudo ~rc/bin/buildit $(CC_Archs) $(Sources)
Deleted: CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.tmproj
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.tmproj 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.tmproj 2013-04-16 22:22:28 UTC (rev 11054)
@@ -1,122 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>documents</key>
- <array>
- <dict>
- <key>expanded</key>
- <true/>
- <key>name</key>
- <string>twistedcaldav</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../twistedcaldav</string>
- </dict>
- <dict>
- <key>name</key>
- <string>web2</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../../Twisted/twisted/web2</string>
- </dict>
- <dict>
- <key>name</key>
- <string>twisted</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../../Twisted/twisted</string>
- </dict>
- <dict>
- <key>name</key>
- <string>PyOpenDirectory</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../../PyOpenDirectory</string>
- </dict>
- <dict>
- <key>name</key>
- <string>PyKerberos</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../../PyKerberos</string>
- </dict>
- <dict>
- <key>name</key>
- <string>conf</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../conf</string>
- </dict>
- <dict>
- <key>name</key>
- <string>bin</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../bin</string>
- </dict>
- <dict>
- <key>name</key>
- <string>doc</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*)$</string>
- <key>sourceDirectory</key>
- <string>../doc</string>
- </dict>
- <dict>
- <key>name</key>
- <string>support</string>
- <key>regexFolderFilter</key>
- <string>!.*/(\.[^/]*|.*\.xcodeproj)$</string>
- <key>sourceDirectory</key>
- <string></string>
- </dict>
- <dict>
- <key>children</key>
- <array>
- <dict>
- <key>filename</key>
- <string>../run</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>../test</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>../testcaldav</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>../setup.py</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>../LICENSE</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>../README</string>
- </dict>
- </array>
- <key>name</key>
- <string>topfiles</string>
- </dict>
- </array>
- <key>fileHierarchyDrawerWidth</key>
- <integer>249</integer>
- <key>metaData</key>
- <dict/>
- <key>showFileHierarchyDrawer</key>
- <true/>
- <key>windowFrame</key>
- <string>{{414, 114}, {987, 1030}}</string>
-</dict>
-</plist>
Property changes on: CalendarServer/branches/users/glyph/sharedgroups-2/support/CalendarServer.xcodeproj
___________________________________________________________________
Added: svn:ignore
+ xcuserdata
Deleted: CalendarServer/branches/users/glyph/sharedgroups-2/support/Makefile.Apple
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/support/Makefile.Apple 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/support/Makefile.Apple 2013-04-16 22:22:28 UTC (rev 11054)
@@ -1,170 +0,0 @@
-# -*- mode: Makefile; -*-
-##
-# B&I Makefile for CalendarServer
-#
-# This is only useful internally at Apple, probably.
-##
-# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-# Project info
-Project = CalendarServer
-ProjectName = CalendarServer
-UserType = Server
-ToolType = Applications
-
-# Include common makefile targets for B&I
-include $(MAKEFILEPATH)/CoreOS/ReleaseControl/Common.make
-include /AppleInternal/ServerTools/ServerBuildVariables.xcconfig
-
-SIPP = $(SERVER_INSTALL_PATH_PREFIX)
-SERVERSETUP = $(SIPP)$(NSSYSTEMDIR)$(NSLIBRARYSUBDIR)/ServerSetup
-
-Cruft += .dependencies
-Extra_Environment += PATH="$(SIPP)/usr/bin:$$PATH"
-
-CALDAVDSUBDIR = /caldavd
-
-PYTHON = $(USRBINDIR)/python
-PY_HOME = $(SIPP)$(SHAREDIR)$(CALDAVDSUBDIR)
-PY_INSTALL_FLAGS = --root="$(DSTROOT)" --prefix="$(SIPP)" --install-lib="$(PY_HOME)/lib/python" --install-scripts="$(SIPP)$(LIBEXECDIR)$(CALDAVDSUBDIR)"
-CS_INSTALL_FLAGS = --install-scripts="$(SIPP)$(USRSBINDIR)" --install-data="$(SIPP)$(ETCDIR)"
-CS_BUILD_EXT_FLAGS = --include-dirs="$(SIPP)/usr/include" --library-dirs="$(SIPP)/usr/lib"
-
-CS_USER = _calendar
-CS_GROUP = _calendar
-
-#
-# Build
-#
-
-.phony: $(Project) pycalendar build setup prep install install-ossfiles buildit
-
-CalDAVTester:: $(BuildDirectory)/CalDAVTester
-PyKerberos:: $(BuildDirectory)/PyKerberos
-pycalendar:: $(BuildDirectory)/pycalendar
-PyGreSQL-4.0:: $(BuildDirectory)/PyGreSQL-4.0
-sqlparse-0.1.2:: $(BuildDirectory)/sqlparse-0.1.2
-setproctitle-1.1.6:: $(BuildDirectory)/setproctitle-1.1.6
-psutil-0.6.1:: $(BuildDirectory)/psutil-0.6.1
-pycrypto-2.5:: $(BuildDirectory)/pycrypto-2.5
-$(Project):: $(BuildDirectory)/$(Project)
-
-build:: PyKerberos pycalendar PyGreSQL-4.0 sqlparse-0.1.2 setproctitle-1.1.6 psutil-0.6.1 pycrypto-2.5 $(Project)
-
-setup:
- $(_v) ./run -g
-
-prep:: setup CalDAVTester.tgz PyKerberos.tgz pycalendar.tgz PyGreSQL-4.0.tgz sqlparse-0.1.2.tgz setproctitle-1.1.6.tgz psutil-0.6.1.tgz pycrypto-2.5.tgz
-
-PyKerberos pycalendar PyGreSQL-4.0 sqlparse-0.1.2 setproctitle-1.1.6 psutil-0.6.1 pycrypto-2.5 $(Project)::
- @echo "Building $@..."
- $(_v) cd $(BuildDirectory)/$@ && $(Environment) $(PYTHON) setup.py build
-
-install:: build
- $(_v) cd $(BuildDirectory)/$(Project) && $(Environment) $(PYTHON) setup.py build_ext $(CS_BUILD_EXT_FLAGS) install $(PY_INSTALL_FLAGS) $(CS_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/PyKerberos && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/pycalendar && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/PyGreSQL-4.0 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/sqlparse-0.1.2 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/setproctitle-1.1.6 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/psutil-0.6.1 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) cd $(BuildDirectory)/pycrypto-2.5 && $(Environment) $(PYTHON) setup.py install $(PY_INSTALL_FLAGS)
- $(_v) for so in $$(find "$(DSTROOT)$(PY_HOME)/lib" -type f -name '*.so'); do $(STRIP) -Sx "$${so}"; done
- $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(ETCDIR)$(CALDAVDSUBDIR)"
- $(_v) $(INSTALL_FILE) "$(Sources)/conf/caldavd-apple.plist" "$(DSTROOT)$(SIPP)$(ETCDIR)$(CALDAVDSUBDIR)/caldavd-apple.plist"
- $(_v) chmod -R ugo+r "$(DSTROOT)$(PY_HOME)"
- $(_v) for f in $$(find "$(DSTROOT)$(SIPP)$(ETCDIR)" -type f ! -name '*.default'); do cp "$${f}" "$${f}.default"; done
-
-install::
- @echo "Installing manual pages..."
- $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/caldavd.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_bootstrap_database.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_command_gateway.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_export.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_manage_principals.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_migrate_resources.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_purge_attachments.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_purge_events.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_purge_principals.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_manage_push.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_shell.8" "$(DSTROOT)$(SIPP)$(MANDIR)/man8"
- $(_v) gzip -9 -f "$(DSTROOT)$(SIPP)$(MANDIR)/man8/"*.[0-9]
- @echo "Installing launchd config..."
- $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(NSLOCALDIR)/$(NSLIBRARYSUBDIR)/Server/Calendar and Contacts"
- $(_v) $(INSTALL_DIRECTORY) -o "$(CS_USER)" -g "$(CS_GROUP)" -m 0755 "$(DSTROOT)$(VARDIR)/log$(CALDAVDSUBDIR)"
- $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(NSLIBRARYDIR)/LaunchDaemons"
- $(_v) $(INSTALL_FILE) "$(Sources)/contrib/launchd/calendarserver.plist" "$(DSTROOT)$(SIPP)$(NSLIBRARYDIR)/LaunchDaemons/org.calendarserver.calendarserver.plist"
- @echo "Installing changeip script..."
- $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(SIPP)$(LIBEXECDIR)/changeip"
- $(_v) $(INSTALL_FILE) "$(Sources)/calendarserver/tools/changeip_calendar.py" "$(DSTROOT)$(SIPP)$(LIBEXECDIR)/changeip/changeip_calendar.py"
- $(_v) chmod ugo+x "$(DSTROOT)$(SIPP)$(LIBEXECDIR)/changeip/changeip_calendar.py"
-
-install::
- @echo "Installing CalDAVTester package..."
- $(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)/AppleInternal/ServerTools"
- $(_v) $(INSTALL_FILE) "$(Sources)/CalDAVTester.tgz" "$(DSTROOT)/AppleInternal/ServerTools/CalDAVTester.tgz"
-
-#
-# Automatic Extract
-#
-
-$(BuildDirectory)/$(Project):
- @echo "Copying source for $(Project)..."
- $(_v) $(MKDIR) -p "$@"
- $(_v) pax -rw bin conf Makefile lib-patches setup.py calendarserver twistedcaldav twext txdav twisted support "$@/"
-
-$(BuildDirectory)/%: %.tgz
- @echo "Extracting source for $(notdir $<)..."
- $(_v) $(MKDIR) -p "$(BuildDirectory)"
- $(_v) $(RMDIR) "$@"
- $(_v) $(TAR) -C "$(BuildDirectory)" -xzf "$<"
-
-%.tgz: ../%
- @echo "Archiving sources for $(notdir $<)..."
- $(_v) if [ -f "$</setup.py" ] && grep setuptools "$</setup.py" > /dev/null; then \
- echo "Working around setuptools' stupid need to download a new version."; \
- cd "$<" && $(PYTHON) "setup.py" --help >/dev/null; \
- fi
- $(_v) $(TAR) -C "$(dir $<)" \
- --exclude=.svn \
- --exclude=build \
- --exclude=_trial_temp \
- --exclude=dropin.cache \
- -czf "$@" "$(notdir $<)"
-
-#
-# Open Source Hooey
-#
-
-OSV = $(USRDIR)/local/OpenSourceVersions
-OSL = $(USRDIR)/local/OpenSourceLicenses
-
-#install:: install-ossfiles
-
-install-ossfiles::
- $(_v) $(INSTALL_DIRECTORY) $(DSTROOT)/$(OSV)
- $(_v) $(INSTALL_FILE) $(Sources)/$(ProjectName).plist $(DSTROOT)/$(OSV)/$(ProjectName).plist
- $(_v) $(INSTALL_DIRECTORY) $(DSTROOT)/$(OSL)
- $(_v) $(INSTALL_FILE) $(BuildDirectory)/$(Project)/LICENSE $(DSTROOT)/$(OSL)/$(ProjectName).txt
-
-#
-# B&I Hooey
-#
-
-buildit: prep
- @echo "Running buildit..."
- $(_v) sudo ~rc/bin/buildit $(CC_Archs) $(Sources)
Copied: CalendarServer/branches/users/glyph/sharedgroups-2/support/XCode.make (from rev 11020, CalendarServer/trunk/support/XCode.make)
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/support/XCode.make (rev 0)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/support/XCode.make 2013-04-16 22:22:28 UTC (rev 11054)
@@ -0,0 +1,34 @@
+# -*- mode: Makefile; -*-
+##
+# XCode Makefile for CalendarServer
+##
+# Copyright (c) 2005-2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+default: build
+
+#
+# Run sed to suppress XCode's misguided attempts to interpret our output.
+#
+build::
+ ../run -s 2>&1 \
+ | sed \
+ -e 's|error|oops|' \
+ -e 's|warning|oopsie|' \
+ -e 's|^\(..*\):\([0-9][0-9]*\):\([0-9][0-9]*\): |\1-\2-\3: |';
+
+clean::
+ rm -rf ../.dependencies/ ../build/ ../data/ ../calendarserver/version.py;
+ find .. -name '*.pyc' -o -name '*.so' -o -name dropin.cache -print0 | xargs -0 rm -f;
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/support/build.sh
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/support/build.sh 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/support/build.sh 2013-04-16 22:22:28 UTC (rev 11054)
@@ -775,7 +775,7 @@
"${pypi}/p/python-ldap/${ld}.tar.gz";
# XXX actually PyCalendar should be imported in-place.
- py_dependency -fe -i "src" -r 10988 \
+ py_dependency -fe -i "src" -r 11005 \
"pycalendar" "pycalendar" "pycalendar" \
"${svn_uri_base}/PyCalendar/trunk";
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/support/submit
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/support/submit 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/support/submit 2013-04-16 22:22:28 UTC (rev 11054)
@@ -144,7 +144,7 @@
echo ""
echo "Tweaking for B&I...";
-ln -s support/Makefile.Apple "${wc}/Makefile";
+ln -s support/Apple.make "${wc}/Makefile";
version_file="${wc}/SubmissionInfo.xml";
cat - >> "${version_file}" <<EOF
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/twext/enterprise/queue.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/twext/enterprise/queue.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/twext/enterprise/queue.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -635,7 +635,7 @@
"""
The total load of all currently connected workers.
"""
- return sum(worker.currentLoad() for worker in self.workers)
+ return sum(worker.currentLoad for worker in self.workers)
def _selectLowestLoadWorker(self):
@@ -646,7 +646,7 @@
@return: a worker connection with the lowest current load.
@rtype: L{ConnectionFromWorker}
"""
- return sorted(self.workers[:], key=lambda w: w.currentLoad())[0]
+ return sorted(self.workers[:], key=lambda w: w.currentLoad)[0]
def performWork(self, table, workID):
Modified: CalendarServer/branches/users/glyph/sharedgroups-2/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/branches/users/glyph/sharedgroups-2/txdav/common/datastore/file.py 2013-04-16 22:20:28 UTC (rev 11053)
+++ CalendarServer/branches/users/glyph/sharedgroups-2/txdav/common/datastore/file.py 2013-04-16 22:22:28 UTC (rev 11054)
@@ -77,6 +77,14 @@
)
UIDPATH = "__uids__"
+
+
+class _StubQueuer(object):
+ def transferProposalCallbacks(self, otherQueuer):
+ return otherQueuer
+
+
+
class CommonDataStore(DataStore):
"""
Shared logic for SQL-based data stores, between calendar and addressbook
@@ -87,7 +95,6 @@
@ivar quota: the amount of space granted to each calendar home (in bytes)
for storing attachments, or C{None} if quota should not be enforced.
-
@type quota: C{int} or C{NoneType}
@ivar _propertyStoreClass: The class (or callable object / factory) that
@@ -95,6 +102,10 @@
signature of the L{XattrPropertyStore} type: take 2 arguments
C{(default-user-uid, path-factory)}, return an L{IPropertyStore}
provider.
+
+ @ivar queuer: For compatibility with SQL-based store; currently a
+ non-functional implementation just for tests, but could be fixed to be
+ backed by SQLite or something.
"""
implements(ICalendarStore)
@@ -118,6 +129,8 @@
self._migrating = False
self._enableNotifications = True
self._newTransactionCallbacks = set()
+ # FIXME: see '@ivar queuer' above.
+ self.queuer = _StubQueuer()
def callWithNewTransactions(self, callback):
"""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130416/6d496180/attachment-0001.html>
More information about the calendarserver-changes
mailing list