[IMP]: base_calendar caldav crm_caldav: Apply Doc String + quality check
bzr revid: ksa@tinyerp.co.in-20100325120700-qin0rom78ex3vima
This commit is contained in:
parent
58fddb6132
commit
0eb05a2c5d
|
@ -18,6 +18,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil import parser
|
||||
from dateutil import rrule
|
||||
|
@ -38,6 +39,7 @@ def get_recurrent_dates(rrulestring, exdate, startdate=None):
|
|||
"""
|
||||
Get recurrent dates
|
||||
"""
|
||||
|
||||
def todate(date):
|
||||
val = parser.parse(''.join((re.compile('\d')).findall(date)))
|
||||
return val
|
||||
|
@ -56,6 +58,7 @@ def base_calendar_id2real_id(base_calendar_id=None, with_date=False):
|
|||
Convert base calendar id into real id.
|
||||
@return: base calendar id
|
||||
"""
|
||||
|
||||
if base_calendar_id and isinstance(base_calendar_id, (str, unicode)):
|
||||
res = base_calendar_id.split('-')
|
||||
if len(res) >= 2:
|
||||
|
@ -74,6 +77,7 @@ def real_id2base_calendar_id(real_id, recurrent_date):
|
|||
Convert real id into base_calendar_id.
|
||||
@return: real id with recurrent date.
|
||||
"""
|
||||
|
||||
if real_id and recurrent_date:
|
||||
recurrent_date = time.strftime("%Y%m%d%H%M%S", \
|
||||
time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S"))
|
||||
|
@ -89,6 +93,7 @@ def _links_get(self, cr, uid, context={}):
|
|||
@param context: A standard dictionary for contextual values
|
||||
@return: list of dictionary which contain object and name and id.
|
||||
"""
|
||||
|
||||
obj = self.pool.get('res.request.link')
|
||||
ids = obj.search(cr, uid, [])
|
||||
res = obj.read(cr, uid, ids, ['object', 'name'], context=context)
|
||||
|
@ -288,6 +293,7 @@ class calendar_attendee(osv.osv):
|
|||
@param context: A standard dictionary for contextual values
|
||||
@return: list of dictionary which contain object and name and id.
|
||||
"""
|
||||
|
||||
obj = self.pool.get('res.request.link')
|
||||
ids = obj.search(cr, uid, [])
|
||||
res = obj.read(cr, uid, ids, ['object', 'name'], context=context)
|
||||
|
@ -323,7 +329,7 @@ class calendar_attendee(osv.osv):
|
|||
('needs-action', 'Needs Action'),
|
||||
('accepted', 'Accepted'),
|
||||
('declined', 'Declined'),
|
||||
('delegated', 'Delegated')], 'State', readonly=True,
|
||||
('delegated', 'Delegated')], 'State', readonly=True,\
|
||||
help="Status of the attendee's participation"),
|
||||
'rsvp': fields.boolean('Required Reply?',
|
||||
help="Indicats whether the favor of a reply is requested"),
|
||||
|
@ -333,19 +339,32 @@ class calendar_attendee(osv.osv):
|
|||
request was delegated to"),
|
||||
'delegated_from': fields.function(_compute_data, method=True, string=\
|
||||
'Delegated From', type="char", store=True, size=124, multi='delegated_from'),
|
||||
'parent_ids': fields.many2many('calendar.attendee', 'calendar_attendee_parent_rel', 'attendee_id', 'parent_id', 'Delegrated From'),
|
||||
'child_ids': fields.many2many('calendar.attendee', 'calendar_attendee_child_rel', 'attendee_id', 'child_id', 'Delegrated To'),
|
||||
'sent_by': fields.function(_compute_data, method=True, string='Sent By', type="char", multi='sent_by', store=True, size=124, help="Specify the user that is acting on behalf of the calendar user"),
|
||||
'sent_by_uid': fields.function(_compute_data, method=True, string='Sent By User', type="many2one", relation="res.users", multi='sent_by_uid'),
|
||||
'cn': fields.function(_compute_data, method=True, string='Common name', type="char", size=124, multi='cn', store=True),
|
||||
'dir': fields.char('URI Reference', size=124, help="Reference to the URI that points to the directory information corresponding to the attendee."),
|
||||
'language': fields.function(_compute_data, method=True, string='Language', type="selection", selection=_lang_get, multi='language', store=True, help="To specify the language for text values in a property or property parameter."),
|
||||
'parent_ids': fields.many2many('calendar.attendee', 'calendar_attendee_parent_rel',\
|
||||
'attendee_id', 'parent_id', 'Delegrated From'),
|
||||
'child_ids': fields.many2many('calendar.attendee', 'calendar_attendee_child_rel',\
|
||||
'attendee_id', 'child_id', 'Delegrated To'),
|
||||
'sent_by': fields.function(_compute_data, method=True, string='Sent By',\
|
||||
type="char", multi='sent_by', store=True, size=124,\
|
||||
help="Specify the user that is acting on behalf of the calendar user"),
|
||||
'sent_by_uid': fields.function(_compute_data, method=True, string='Sent By User',\
|
||||
type="many2one", relation="res.users", multi='sent_by_uid'),
|
||||
'cn': fields.function(_compute_data, method=True, string='Common name',\
|
||||
type="char", size=124, multi='cn', store=True),
|
||||
'dir': fields.char('URI Reference', size=124, help="Reference to the URI\
|
||||
that points to the directory information corresponding to the attendee."),
|
||||
'language': fields.function(_compute_data, method=True, string='Language',\
|
||||
type="selection", selection=_lang_get, multi='language',\
|
||||
store=True, help="To specify the language for text values in a\
|
||||
property or property parameter."),
|
||||
'user_id': fields.many2one('res.users', 'User'),
|
||||
'partner_address_id': fields.many2one('res.partner.address', 'Contact'),
|
||||
'partner_id': fields.related('partner_address_id', 'partner_id', type='many2one', relation='res.partner', string='Partner', help="Partner related to contact"),
|
||||
'partner_id': fields.related('partner_address_id', 'partner_id', type='many2one',\
|
||||
relation='res.partner', string='Partner', help="Partner related to contact"),
|
||||
'email': fields.char('Email', size=124, help="Email of Invited Person"),
|
||||
'event_date': fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'),
|
||||
'event_end_date': fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'),
|
||||
'event_date': fields.function(_compute_data, method=True, string='Event Date',\
|
||||
type="datetime", multi='event_date'),
|
||||
'event_end_date': fields.function(_compute_data, method=True, string='Event End Date',\
|
||||
type="datetime", multi='event_end_date'),
|
||||
'ref': fields.reference('Event Ref', selection=_links_get, size=128),
|
||||
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
|
||||
}
|
||||
|
@ -356,11 +375,15 @@ request was delegated to"),
|
|||
response_re = re.compile("Are you coming\?.*\n*.*(YES|NO|MAYBE).*", re.UNICODE)
|
||||
|
||||
def msg_new(self, cr, uid, msg):
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks, """
|
||||
return False
|
||||
|
||||
def msg_act_get(self, msg):
|
||||
"""
|
||||
Get Message.
|
||||
@param self: The object pointer
|
||||
@return: dictionary of actions which contain state field value.
|
||||
"""
|
||||
|
||||
|
@ -399,6 +422,7 @@ request was delegated to"),
|
|||
@param context: A standard dictionary for contextual values
|
||||
@return: True
|
||||
"""
|
||||
|
||||
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.name
|
||||
for att in self.browse(cr, uid, ids, context=context):
|
||||
sign = att.sent_by_uid and att.sent_by_uid.signature or ''
|
||||
|
@ -441,6 +465,7 @@ request was delegated to"),
|
|||
@param user_id: User id
|
||||
@return: dictionary of value. which put value in email and availability fields.
|
||||
"""
|
||||
|
||||
if not user_id:
|
||||
return {'value': {'email': ''}}
|
||||
usr_obj = self.pool.get('res.users')
|
||||
|
@ -448,6 +473,13 @@ request was delegated to"),
|
|||
return {'value': {'email': user.address_id.email, 'availability':user.availability}}
|
||||
|
||||
def do_tentative(self, cr, uid, ids, context=None, *args):
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of calendar attendee’s IDs
|
||||
@param *args: Get Tupple value
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
self.write(cr, uid, ids, {'state': 'tentative'}, context)
|
||||
|
||||
def do_accept(self, cr, uid, ids, context=None, *args):
|
||||
|
@ -458,6 +490,7 @@ request was delegated to"),
|
|||
@param ids: List of calendar attendee’s IDs.
|
||||
@return: True
|
||||
"""
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
|
@ -475,9 +508,21 @@ request was delegated to"),
|
|||
return True
|
||||
|
||||
def do_decline(self, cr, uid, ids, context=None, *args):
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of calendar attendee’s IDs
|
||||
@param *args: Get Tupple value
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
self.write(cr, uid, ids, {'state': 'declined'}, context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param vals: Get Values
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
|
@ -506,7 +551,8 @@ class res_alarm(osv.osv):
|
|||
'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \
|
||||
are both optional, but if one occurs, so MUST the other"""),
|
||||
'repeat': fields.integer('Repeat'),
|
||||
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it."),
|
||||
'active': fields.boolean('Active', help="If the active field is set to \
|
||||
true, it will allow you to hide the event alarm information without removing it."),
|
||||
|
||||
|
||||
}
|
||||
|
@ -528,6 +574,7 @@ are both optional, but if one occurs, so MUST the other"""),
|
|||
@param context: A standard dictionary for contextual values
|
||||
@return: True
|
||||
"""
|
||||
|
||||
alarm_obj = self.pool.get('calendar.alarm')
|
||||
ir_obj = self.pool.get('ir.model')
|
||||
model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0]
|
||||
|
@ -574,6 +621,7 @@ are both optional, but if one occurs, so MUST the other"""),
|
|||
@param model: Model name.
|
||||
@return: True
|
||||
"""
|
||||
|
||||
alarm_obj = self.pool.get('calendar.alarm')
|
||||
ir_obj = self.pool.get('ir.model')
|
||||
model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0]
|
||||
|
@ -597,17 +645,22 @@ class calendar_alarm(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
|
||||
'name': fields.char('Summary', size=124, help="""Contains the text to be used as the message subject for email
|
||||
or contains the text to be used for display"""),
|
||||
'name': fields.char('Summary', size=124, help="""Contains the text to be \
|
||||
used as the message subject for email \
|
||||
or contains the text to be used for display"""),
|
||||
'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
|
||||
('procedure', 'Procedure'), ('email', 'Email') ], 'Action', \
|
||||
required=True, help="Defines the action to be invoked when an alarm is triggered"),
|
||||
'description': fields.text('Description', help='Provides a more complete description of the calendar component, than that provided by the "SUMMARY" property'),
|
||||
'description': fields.text('Description', help='Provides a more complete \
|
||||
description of the calendar component, than that \
|
||||
provided by the "SUMMARY" property'),
|
||||
'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
|
||||
'alarm_id', 'attendee_id', 'Attendees', readonly=True),
|
||||
'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
|
||||
* File which is intended to be sent as message attachments for email,
|
||||
* Points to a procedure resource, which is invoked when the alarm is triggered for procedure."""),
|
||||
'attach': fields.binary('Attachment', help="""* Points to a sound resource,\
|
||||
which is rendered when the alarm is triggered for audio,
|
||||
* File which is intended to be sent as message attachments for email,
|
||||
* Points to a procedure resource, which is invoked when\
|
||||
the alarm is triggered for procedure."""),
|
||||
'res_id': fields.integer('Resource ID'),
|
||||
'model_id': fields.many2one('ir.model', 'Model'),
|
||||
'user_id': fields.many2one('res.users', 'Owner'),
|
||||
|
@ -636,6 +689,7 @@ or contains the text to be used for display"""),
|
|||
@param context: A standard dictionary for contextual values
|
||||
@return: new record id for calendar_alarm.
|
||||
"""
|
||||
|
||||
event_date = vals.get('event_date', False)
|
||||
if event_date:
|
||||
dtstart = datetime.strptime(vals['event_date'], "%Y-%m-%d %H:%M:%S")
|
||||
|
@ -652,6 +706,15 @@ or contains the text to be used for display"""),
|
|||
|
||||
def do_run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \
|
||||
context=None):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of calendar alarm’s IDs.
|
||||
@param use_new_cursor: False or the dbname
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
|
@ -722,6 +785,17 @@ class calendar_event(osv.osv):
|
|||
|
||||
|
||||
def onchange_dates(self, cr, uid, ids, start_date, duration=False, end_date=False, context={}):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of calendar event’s IDs.
|
||||
@param start_date: Get starting date
|
||||
@param duration: Get Duration between start date and end date or False
|
||||
@param end_date: Get Ending Date or False
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
"""
|
||||
if not start_date:
|
||||
return {}
|
||||
value = {}
|
||||
|
@ -782,10 +856,11 @@ class calendar_event(osv.osv):
|
|||
'Show as'),
|
||||
'base_calendar_url': fields.char('Caldav URL', size=264),
|
||||
'exdate': fields.text('Exception Date/Times', help="This property \
|
||||
defines the list of date/time exceptions for arecurring calendar component."),
|
||||
defines the list of date/time exceptions for arecurring calendar component."),
|
||||
'exrule': fields.char('Exception Rule', size=352, help="defines a \
|
||||
rule or repeating pattern for anexception to a recurrence set"),
|
||||
'rrule': fields.function(_get_rulestring, type='char', size=124, method=True, string='Recurrent Rule', store=True),
|
||||
rule or repeating pattern for anexception to a recurrence set"),
|
||||
'rrule': fields.function(_get_rulestring, type='char', size=124, method=True,\
|
||||
string='Recurrent Rule', store=True),
|
||||
'rrule_type': fields.selection([('none', ''), ('daily', 'Daily'), \
|
||||
('weekly', 'Weekly'), ('monthly', 'Monthly'), \
|
||||
('yearly', 'Yearly'), ('custom', 'Custom')], 'Recurrency'),
|
||||
|
@ -793,7 +868,8 @@ rule or repeating pattern for anexception to a recurrence set"),
|
|||
'base_calendar_alarm_id': fields.many2one('calendar.alarm', 'Alarm'),
|
||||
'recurrent_uid': fields.integer('Recurrent ID'),
|
||||
'recurrent_id': fields.datetime('Recurrent ID date'),
|
||||
'vtimezone': fields.related('user_id', 'context_tz', type='char', size=24, string='Timezone', store=True),
|
||||
'vtimezone': fields.related('user_id', 'context_tz', type='char', size=24,\
|
||||
string='Timezone', store=True),
|
||||
'user_id': fields.many2one('res.users', 'Responsible'),
|
||||
'freq': fields.selection([('None', 'No Repeat'), \
|
||||
('secondly', 'Secondly'), \
|
||||
|
@ -835,6 +911,16 @@ rule or repeating pattern for anexception to a recurrence set"),
|
|||
}
|
||||
|
||||
def modify_this(self, cr, uid, event_id, defaults, real_date, context=None, *args):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param event_id: Get Event_id
|
||||
@param real_date: Get Real Date
|
||||
@param context: A standard dictionary for contextual values
|
||||
@param *args: Get Tuppel Value
|
||||
|
||||
"""
|
||||
|
||||
event_id = base_calendar_id2real_id(event_id)
|
||||
datas = self.read(cr, uid, event_id, context=context)
|
||||
|
@ -878,6 +964,14 @@ rule or repeating pattern for anexception to a recurrence set"),
|
|||
return True
|
||||
|
||||
def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param base_start_date: Get Start Date
|
||||
@param base_until_date: Get End Date
|
||||
@param limit: The Number of Results to Return """
|
||||
|
||||
if not limit:
|
||||
limit = 100
|
||||
if isinstance(select, (str, int, long)):
|
||||
|
@ -1009,6 +1103,8 @@ rule or repeating pattern for anexception to a recurrence set"),
|
|||
@param cr: the current row, from the database cursor,
|
||||
@param user: the current user’s ID for security checks,
|
||||
@param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
|
||||
@param offset: The Number of Results to Pass
|
||||
@param limit: The Number of Results to Return
|
||||
@return: List of id
|
||||
"""
|
||||
args_without_date = []
|
||||
|
@ -1182,17 +1278,38 @@ rule or repeating pattern for anexception to a recurrence set"),
|
|||
calendar_event()
|
||||
|
||||
class calendar_todo(osv.osv):
|
||||
""" Calendar Task """
|
||||
|
||||
_name = "calendar.todo"
|
||||
_inherit = "calendar.event"
|
||||
_description = "Calendar Task"
|
||||
|
||||
def _get_date(self, cr, uid, ids, name, arg, context):
|
||||
""" Get Date
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of calendar todo's IDs.
|
||||
@param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
res = {}
|
||||
for event in self.browse(cr, uid, ids, context=context):
|
||||
res[event.id] = event.date_start
|
||||
return res
|
||||
|
||||
def _set_date(self, cr, uid, id, name, value, arg, context):
|
||||
""" Set Date
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param id: calendar's ID.
|
||||
@param value: Get Value
|
||||
@param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
event = self.browse(cr, uid, id, context=context)
|
||||
cr.execute("UPDATE %s set date_start='%s' where id=%s" \
|
||||
% (self._table, value, id))
|
||||
|
@ -1214,6 +1331,13 @@ class ir_attachment(osv.osv):
|
|||
_inherit = 'ir.attachment'
|
||||
|
||||
def search_count(self, cr, user, args, context=None):
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param user: the current user’s ID for security checks,
|
||||
@param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
args1 = []
|
||||
for arg in args:
|
||||
args1.append(map(lambda x:str(x).split('-')[0], arg))
|
||||
|
@ -1221,6 +1345,16 @@ class ir_attachment(osv.osv):
|
|||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||
context=None, count=False):
|
||||
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
|
||||
@param offset: The Number of Results to pass,
|
||||
@param limit: The Number of Results to Return,
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
new_args = args
|
||||
for i, arg in enumerate(new_args):
|
||||
if arg[0] == 'res_id':
|
||||
|
@ -1235,6 +1369,13 @@ class ir_values(osv.osv):
|
|||
|
||||
def set(self, cr, uid, key, key2, name, models, value, replace=True, \
|
||||
isobject=False, meta=False, preserve_user=False, company=False):
|
||||
|
||||
""" set IR Values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param model: Get The Model """
|
||||
|
||||
new_model = []
|
||||
for data in models:
|
||||
if type(data) in (list, tuple):
|
||||
|
@ -1246,6 +1387,13 @@ class ir_values(osv.osv):
|
|||
|
||||
def get(self, cr, uid, key, key2, models, meta=False, context={}, \
|
||||
res_id_req=False, without_user=True, key2_req=True):
|
||||
|
||||
""" Get IR Values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param model: Get The Model """
|
||||
|
||||
new_model = []
|
||||
for data in models:
|
||||
if type(data) in (list, tuple):
|
||||
|
@ -1263,6 +1411,15 @@ class ir_model(osv.osv):
|
|||
|
||||
def read(self, cr, uid, ids, fields=None, context={},
|
||||
load='_classic_read'):
|
||||
|
||||
""" Read IR Model
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of IR Model’s IDs.
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
|
||||
data = super(ir_model, self).read(cr, uid, ids, fields=fields, \
|
||||
context=context, load=load)
|
||||
if data:
|
||||
|
@ -1275,13 +1432,21 @@ ir_model()
|
|||
class virtual_report_spool(web_services.report_spool):
|
||||
|
||||
def exp_report(self, db, uid, object, ids, datas=None, context=None):
|
||||
|
||||
""" Export Report
|
||||
@param self: The object pointer
|
||||
@param db: get the current database,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
|
||||
if object == 'printscreen.list':
|
||||
return super(virtual_report_spool, self).exp_report(db, uid, \
|
||||
object, ids, datas, context)
|
||||
new_ids = []
|
||||
for id in ids:
|
||||
new_ids.append(base_calendar_id2real_id(id))
|
||||
if datas.get('id',False):
|
||||
if datas.get('id', False):
|
||||
datas['id'] = base_calendar_id2real_id(datas['id'])
|
||||
return super(virtual_report_spool, self).exp_report(db, uid, object, new_ids, datas, context)
|
||||
|
||||
|
@ -1291,6 +1456,14 @@ class res_users(osv.osv):
|
|||
_inherit = 'res.users'
|
||||
|
||||
def _get_user_avail(self, cr, uid, ids, context=None):
|
||||
|
||||
""" Get USer Availability
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of res user’s IDs.
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
current_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
res = {}
|
||||
attendee_obj = self.pool.get('calendar.attendee')
|
||||
|
@ -1313,6 +1486,14 @@ class res_users(osv.osv):
|
|||
return res
|
||||
|
||||
def _get_user_avail_fun(self, cr, uid, ids, name, args, context=None):
|
||||
|
||||
""" Get USer Availability Function
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of res user’s IDs.
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
return self._get_user_avail(cr, uid, ids, context=context)
|
||||
|
||||
_columns = {
|
||||
|
|
|
@ -41,7 +41,8 @@ class base_calendar_invite_attendee(osv.osv_memory):
|
|||
'email': fields.char('Email', size=124),
|
||||
'contact_ids': fields.many2many('res.partner.address', 'invite_contact_rel',
|
||||
'invite_id', 'contact_id', 'Contacts'),
|
||||
'send_mail': fields.boolean('Send mail?', help='Check this if you want to send an Email to Invited Person')
|
||||
'send_mail': fields.boolean('Send mail?', help='Check this if you want to \
|
||||
send an Email to Invited Person')
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -141,7 +142,7 @@ class base_calendar_invite_attendee(osv.osv_memory):
|
|||
raise osv.except_osv(_('Error!'), ("%s must have an email \
|
||||
Address to send mail") % (name[0]))
|
||||
att_obj._send_mail(cr, uid, attendees, mail_to, \
|
||||
email_from=tools.config.get('email_from', False))
|
||||
email_from= tools.config.get('email_from', False))
|
||||
|
||||
return {}
|
||||
|
||||
|
@ -155,6 +156,7 @@ class base_calendar_invite_attendee(osv.osv_memory):
|
|||
@param partner_id: id of Partner
|
||||
@return: dictionary of value.
|
||||
"""
|
||||
|
||||
if not partner_id:
|
||||
return {'value': {'contact_ids': []}}
|
||||
cr.execute('select id from res_partner_address \
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
<data>
|
||||
<!-- Attendee invite wizard-->
|
||||
|
||||
<record id="view_calendar_invite_attendee_wizard" model="ir.ui.view">
|
||||
<record id="view_calendar_invite_attendee_wizard"
|
||||
model="ir.ui.view">
|
||||
<field name="name">Invite Attendees</field>
|
||||
<field name="model">base_calendar.invite.attendee</field>
|
||||
<field name="type">form</field>
|
||||
|
@ -11,7 +12,7 @@
|
|||
<form string="Invite People">
|
||||
<field name="type" />
|
||||
<field name="send_mail" />
|
||||
<newline/>
|
||||
<newline />
|
||||
<group col="1" colspan="4"
|
||||
attrs="{'invisible': [('type', '!=', 'external')]}">
|
||||
<field name="email" colspan="4"
|
||||
|
@ -36,7 +37,7 @@
|
|||
nolabel="1" domain="[('partner_id', '=', partner_id)]"
|
||||
attrs="{'readonly': [('type', '!=', 'partner')]}" />
|
||||
</group>
|
||||
<newline/>
|
||||
<newline />
|
||||
<separator string="" colspan="6" />
|
||||
<label string="" colspan="2" />
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
|
|
|
@ -25,7 +25,11 @@ from osv import fields
|
|||
class calendar_event_edit_all(osv.osv_memory):
|
||||
|
||||
def _default_values(self, cr, uid, context={}):
|
||||
"""
|
||||
""" Get Default value for Start Date
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values
|
||||
@Return: Get Default value for Start Date
|
||||
"""
|
||||
context_id = context and context.get('active_id', False) or False
|
||||
|
@ -39,9 +43,14 @@ class calendar_event_edit_all(osv.osv_memory):
|
|||
return event['date']
|
||||
|
||||
def _default_deadline(self, cr, uid, context={}):
|
||||
"""
|
||||
""" Get Default value for End Date
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values
|
||||
@return: Get Default value for End Date
|
||||
"""
|
||||
|
||||
context_id = context and context.get('active_id', False) or False
|
||||
if context_id:
|
||||
if context.get('date_deadline'):
|
||||
|
|
|
@ -27,6 +27,7 @@ __author__ = AUTHOR
|
|||
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
import os
|
||||
|
||||
class BufferedHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
"""
|
||||
Buffering HTTP Request Handler
|
||||
|
@ -47,12 +48,12 @@ class BufferedHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
If you override the handle() method remember to call
|
||||
this (see below)
|
||||
"""
|
||||
self.__buffer=""
|
||||
self.__outfp=os.tmpfile()
|
||||
self.__buffer = ""
|
||||
self.__outfp = os.tmpfile()
|
||||
|
||||
def _append(self,s):
|
||||
""" append a string to the buffer """
|
||||
self.__buffer=self.__buffer+s
|
||||
self.__buffer = self.__buffer+s
|
||||
|
||||
def _flush(self):
|
||||
""" flush the buffer to wfile """
|
||||
|
@ -60,7 +61,7 @@ class BufferedHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
self.__outfp.write(self.__buffer)
|
||||
self.__outfp.flush()
|
||||
self.wfile.flush()
|
||||
self.__buffer=""
|
||||
self.__buffer = ""
|
||||
|
||||
def handle(self):
|
||||
""" Handle a HTTP request """
|
||||
|
@ -97,3 +98,4 @@ class BufferedHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
|
||||
protocol_version="HTTP/1.1"
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Python WebDAV Server.
|
||||
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
|
||||
|
@ -23,12 +25,20 @@ Subclass this class and specify an IFACE_CLASS. See example.
|
|||
|
||||
"""
|
||||
|
||||
DEBUG=None
|
||||
DEBUG = None
|
||||
|
||||
from utils import VERSION, AUTHOR
|
||||
__version__ = VERSION
|
||||
__author__ = AUTHOR
|
||||
|
||||
from propfind import PROPFIND
|
||||
from delete import DELETE
|
||||
from davcopy import COPY
|
||||
from davmove import MOVE
|
||||
|
||||
from string import atoi, split
|
||||
from status import STATUS_CODES
|
||||
from errors import *
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -39,16 +49,6 @@ import posixpath
|
|||
import base64
|
||||
import urlparse
|
||||
import urllib
|
||||
|
||||
from propfind import PROPFIND
|
||||
from delete import DELETE
|
||||
from davcopy import COPY
|
||||
from davmove import MOVE
|
||||
|
||||
from string import atoi,split
|
||||
from status import STATUS_CODES
|
||||
from errors import *
|
||||
|
||||
import BaseHTTPServer
|
||||
|
||||
class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
|
@ -74,21 +74,21 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
def _log(self, message):
|
||||
pass
|
||||
|
||||
def _append(self,s):
|
||||
def _append(self, s):
|
||||
""" write the string to wfile """
|
||||
self.wfile.write(s)
|
||||
|
||||
def send_body(self,DATA,code,msg,desc,ctype='application/octet-stream',headers=None):
|
||||
def send_body(self, DATA, code, msg, desc, ctype='application/octet-stream', headers=None):
|
||||
""" send a body in one part """
|
||||
|
||||
if not headers:
|
||||
headers = {}
|
||||
self.send_response(code,message=msg)
|
||||
self.send_response(code, message=msg)
|
||||
self.send_header("Connection", "keep-alive")
|
||||
self.send_header("Accept-Ranges", "bytes")
|
||||
|
||||
for a,v in headers.items():
|
||||
self.send_header(a,v)
|
||||
for a, v in headers.items():
|
||||
self.send_header(a, v)
|
||||
|
||||
if DATA:
|
||||
self.send_header("Content-Length", str(len(DATA)))
|
||||
|
@ -100,11 +100,11 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
if DATA:
|
||||
self._append(DATA)
|
||||
|
||||
def send_body_chunks(self,DATA,code,msg,desc,ctype='text/xml; encoding="utf-8"'):
|
||||
def send_body_chunks(self, DATA, code, msg, desc, ctype='text/xml; encoding="utf-8"'):
|
||||
""" send a body in chunks """
|
||||
|
||||
self.responses[207]=(msg,desc)
|
||||
self.send_response(code,message=msg)
|
||||
self.responses[207]=(msg, desc)
|
||||
self.send_response(code, message=msg)
|
||||
self.send_header("Content-type", ctype)
|
||||
self.send_header("Connection", "keep-alive")
|
||||
self.send_header("Transfer-Encoding", "chunked")
|
||||
|
@ -128,12 +128,12 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
|
||||
def do_PROPFIND(self):
|
||||
|
||||
dc=self.IFACE_CLASS
|
||||
dc = self.IFACE_CLASS
|
||||
# read the body
|
||||
body=None
|
||||
body = None
|
||||
if self.headers.has_key("Content-Length"):
|
||||
l=self.headers['Content-Length']
|
||||
body=self.rfile.read(atoi(l))
|
||||
l = self.headers['Content-Length']
|
||||
body = self.rfile.read(atoi(l))
|
||||
alt_body = """<?xml version="1.0" encoding="utf-8"?>
|
||||
<propfind xmlns="DAV:"><prop>
|
||||
<getcontentlength xmlns="DAV:"/>
|
||||
|
@ -149,26 +149,26 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
|
||||
# which Depth?
|
||||
if self.headers.has_key('Depth'):
|
||||
d=self.headers['Depth']
|
||||
d = self.headers['Depth']
|
||||
else:
|
||||
d="infinity"
|
||||
d = "infinity"
|
||||
|
||||
uri=self.geturi()
|
||||
pf=PROPFIND(uri,dc,d)
|
||||
uri = self.geturi()
|
||||
pf = PROPFIND(uri, dc, d)
|
||||
|
||||
if body:
|
||||
pf.read_propfind(body)
|
||||
|
||||
try:
|
||||
DATA=pf.createResponse()
|
||||
DATA=DATA+"\n"
|
||||
DATA = pf.createResponse()
|
||||
DATA = DATA+"\n"
|
||||
# print "Data:", DATA
|
||||
except DAV_NotFound,(ec,dd):
|
||||
except DAV_NotFound, (ec, dd):
|
||||
return self.send_notFound(dd, uri)
|
||||
except DAV_Error, (ec,dd):
|
||||
return self.send_error(ec,dd)
|
||||
except DAV_Error, (ec, dd):
|
||||
return self.send_error(ec, dd)
|
||||
|
||||
self.send_body_chunks(DATA,207,"Multi-Status","Multiple responses")
|
||||
self.send_body_chunks(DATA, 207, "Multi-Status", "Multiple responses")
|
||||
|
||||
def geturi(self):
|
||||
buri = self.IFACE_CLASS.baseuri
|
||||
|
@ -179,110 +179,110 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
|
||||
def do_GET(self):
|
||||
"""Serve a GET request."""
|
||||
dc=self.IFACE_CLASS
|
||||
uri=self.geturi()
|
||||
dc = self.IFACE_CLASS
|
||||
uri = self.geturi()
|
||||
|
||||
# get the last modified date
|
||||
try:
|
||||
lm=dc.get_prop(uri,"DAV:","getlastmodified")
|
||||
lm = dc.get_prop(uri, "DAV:", "getlastmodified")
|
||||
except:
|
||||
lm="Sun, 01 Dec 2014 00:00:00 GMT" # dummy!
|
||||
headers={"Last-Modified":lm , "Connection": "keep-alive"}
|
||||
lm = "Sun, 01 Dec 2014 00:00:00 GMT" # dummy!
|
||||
headers = {"Last-Modified":lm , "Connection": "keep-alive"}
|
||||
|
||||
# get the content type
|
||||
try:
|
||||
ct=dc.get_prop(uri,"DAV:","getcontenttype")
|
||||
ct = dc.get_prop(uri, "DAV:", "getcontenttype")
|
||||
except:
|
||||
ct="application/octet-stream"
|
||||
ct = "application/octet-stream"
|
||||
|
||||
# get the data
|
||||
try:
|
||||
data=dc.get_data(uri)
|
||||
except DAV_Error, (ec,dd):
|
||||
data = dc.get_data(uri)
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_status(ec)
|
||||
return
|
||||
|
||||
# send the data
|
||||
self.send_body(data,200,"OK","OK",ct,headers)
|
||||
self.send_body(data, 200, "OK", "OK", ct, headers)
|
||||
|
||||
def do_HEAD(self):
|
||||
""" Send a HEAD response """
|
||||
dc=self.IFACE_CLASS
|
||||
uri=self.geturi()
|
||||
dc = self.IFACE_CLASS
|
||||
uri = self.geturi()
|
||||
|
||||
# get the last modified date
|
||||
try:
|
||||
lm=dc.get_prop(uri,"DAV:","getlastmodified")
|
||||
lm = dc.get_prop(uri, "DAV:", "getlastmodified")
|
||||
except:
|
||||
lm="Sun, 01 Dec 2014 00:00:00 GMT" # dummy!
|
||||
lm = "Sun, 01 Dec 2014 00:00:00 GMT" # dummy!
|
||||
|
||||
headers={"Last-Modified":lm, "Connection": "keep-alive"}
|
||||
headers = {"Last-Modified":lm, "Connection": "keep-alive"}
|
||||
|
||||
# get the content type
|
||||
try:
|
||||
ct=dc.get_prop(uri,"DAV:","getcontenttype")
|
||||
ct = dc.get_prop(uri, "DAV:", "getcontenttype")
|
||||
except:
|
||||
ct="application/octet-stream"
|
||||
ct = "application/octet-stream"
|
||||
|
||||
try:
|
||||
data=dc.get_data(uri)
|
||||
headers["Content-Length"]=str(len(data))
|
||||
data = dc.get_data(uri)
|
||||
headers["Content-Length"] = str(len(data))
|
||||
except DAV_NotFound:
|
||||
self.send_body(None,404,"Not Found","")
|
||||
self.send_body(None, 404, "Not Found", "")
|
||||
return
|
||||
|
||||
self.send_body(None,200,"OK","OK",ct,headers)
|
||||
self.send_body(None, 200, "OK", "OK", ct, headers)
|
||||
|
||||
def do_POST(self):
|
||||
self.send_error(404,"File not found")
|
||||
self.send_error(404, "File not found")
|
||||
|
||||
def do_MKCOL(self):
|
||||
""" create a new collection """
|
||||
|
||||
dc=self.IFACE_CLASS
|
||||
uri=self.geturi()
|
||||
dc = self.IFACE_CLASS
|
||||
uri = self.geturi()
|
||||
try:
|
||||
res = dc.mkcol(uri)
|
||||
if res:
|
||||
self.send_body(None,201,"Created",'')
|
||||
self.send_body(None, 201, "Created", '')
|
||||
else:
|
||||
self.send_body(None,415,"Cannot create",'')
|
||||
self.send_body(None, 415, "Cannot create", '')
|
||||
#self.send_header("Connection", "keep-alive")
|
||||
# Todo: some content, too
|
||||
except DAV_Error, (ec,dd):
|
||||
self.send_body(None,int(ec),dd,dd)
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_body(None, int(ec), dd, dd)
|
||||
|
||||
def do_DELETE(self):
|
||||
""" delete an resource """
|
||||
dc=self.IFACE_CLASS
|
||||
uri=self.geturi()
|
||||
dl=DELETE(uri,dc)
|
||||
dc = self.IFACE_CLASS
|
||||
uri = self.geturi()
|
||||
dl = DELETE(uri, dc)
|
||||
if dc.is_collection(uri):
|
||||
res=dl.delcol()
|
||||
res = dl.delcol()
|
||||
else:
|
||||
res=dl.delone()
|
||||
res = dl.delone()
|
||||
|
||||
if res:
|
||||
self.send_status(207,body=res)
|
||||
self.send_status(207, body=res)
|
||||
else:
|
||||
self.send_status(204)
|
||||
|
||||
def do_PUT(self):
|
||||
dc=self.IFACE_CLASS
|
||||
dc = self.IFACE_CLASS
|
||||
|
||||
# read the body
|
||||
body=None
|
||||
body = None
|
||||
if self.headers.has_key("Content-Length"):
|
||||
l=self.headers['Content-Length']
|
||||
body=self.rfile.read(atoi(l))
|
||||
uri=self.geturi()
|
||||
l = self.headers['Content-Length']
|
||||
body = self.rfile.read(atoi(l))
|
||||
uri = self.geturi()
|
||||
|
||||
ct=None
|
||||
ct = None
|
||||
if self.headers.has_key("Content-Type"):
|
||||
ct=self.headers['Content-Type']
|
||||
ct = self.headers['Content-Type']
|
||||
try:
|
||||
dc.put(uri,body,ct)
|
||||
except DAV_Error, (ec,dd):
|
||||
dc.put(uri, body, ct)
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_status(ec)
|
||||
return
|
||||
self.send_status(201)
|
||||
|
@ -291,84 +291,84 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
""" copy one resource to another """
|
||||
try:
|
||||
self.copymove(COPY)
|
||||
except DAV_Error, (ec,dd):
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_status(ec)
|
||||
|
||||
def do_MOVE(self):
|
||||
""" move one resource to another """
|
||||
try:
|
||||
self.copymove(MOVE)
|
||||
except DAV_Error, (ec,dd):
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_status(ec)
|
||||
|
||||
def copymove(self,CLASS):
|
||||
def copymove(self, CLASS):
|
||||
""" common method for copying or moving objects """
|
||||
dc=self.IFACE_CLASS
|
||||
dc = self.IFACE_CLASS
|
||||
|
||||
# get the source URI
|
||||
source_uri=self.geturi()
|
||||
source_uri = self.geturi()
|
||||
|
||||
# get the destination URI
|
||||
dest_uri=self.headers['Destination']
|
||||
dest_uri=urllib.unquote(dest_uri)
|
||||
dest_uri = self.headers['Destination']
|
||||
dest_uri = urllib.unquote(dest_uri)
|
||||
|
||||
# Overwrite?
|
||||
overwrite=1
|
||||
result_code=204
|
||||
overwrite = 1
|
||||
result_code = 204
|
||||
if self.headers.has_key("Overwrite"):
|
||||
if self.headers['Overwrite']=="F":
|
||||
overwrite=None
|
||||
result_code=201
|
||||
|
||||
# instanciate ACTION class
|
||||
cp=CLASS(dc,source_uri,dest_uri,overwrite)
|
||||
cp = CLASS(dc, source_uri, dest_uri, overwrite)
|
||||
|
||||
# Depth?
|
||||
d="infinity"
|
||||
d = "infinity"
|
||||
if self.headers.has_key("Depth"):
|
||||
d=self.headers['Depth']
|
||||
d = self.headers['Depth']
|
||||
|
||||
if d!="0" and d!="infinity":
|
||||
self.send_status(400)
|
||||
return
|
||||
|
||||
if d=="0":
|
||||
res=cp.single_action()
|
||||
res = cp.single_action()
|
||||
self.send_status(res)
|
||||
return
|
||||
|
||||
# now it only can be "infinity" but we nevertheless check for a collection
|
||||
if dc.is_collection(source_uri):
|
||||
try:
|
||||
res=cp.tree_action()
|
||||
except DAV_Error, (ec,dd):
|
||||
res = cp.tree_action()
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_status(ec)
|
||||
return
|
||||
else:
|
||||
try:
|
||||
res=cp.single_action()
|
||||
except DAV_Error, (ec,dd):
|
||||
res = cp.single_action()
|
||||
except DAV_Error, (ec, dd):
|
||||
self.send_status(ec)
|
||||
return
|
||||
|
||||
if res:
|
||||
self.send_body_chunks(res,207,STATUS_CODES[207],STATUS_CODES[207],
|
||||
self.send_body_chunks(res, 207, STATUS_CODES[207], STATUS_CODES[207],
|
||||
ctype='text/xml; charset="utf-8"')
|
||||
else:
|
||||
self.send_status(result_code)
|
||||
|
||||
def get_userinfo(self,user,pw):
|
||||
def get_userinfo(self, user, pw):
|
||||
""" Dummy method which lets all users in """
|
||||
|
||||
return 1
|
||||
|
||||
def send_status(self,code=200,mediatype='text/xml; charset="utf-8"', \
|
||||
msg=None,body=None):
|
||||
def send_status(self, code=200, mediatype='text/xml; charset="utf-8"', \
|
||||
msg=None, body=None):
|
||||
|
||||
if not msg: msg=STATUS_CODES[code]
|
||||
self.send_body(body,code,STATUS_CODES[code],msg,mediatype)
|
||||
if not msg: msg = STATUS_CODES[code]
|
||||
self.send_body(body, code, STATUS_CODES[code], msg, mediatype)
|
||||
|
||||
def send_notFound(self,descr,uri):
|
||||
def send_notFound(self, descr, uri):
|
||||
body = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:response xmlns:D="DAV:">
|
||||
<D:href>%s</D:href>
|
||||
|
@ -376,4 +376,6 @@ class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||
<D:responsedescription>%s</D:responsedescription>
|
||||
</D:response>
|
||||
"""
|
||||
return self.send_status(404,descr, body=body % (uri,descr))
|
||||
return self.send_status(404, descr, body=body % (uri, descr))
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -14,7 +14,7 @@ import urlparse
|
|||
from utils import create_treelist, is_prefix
|
||||
from errors import *
|
||||
|
||||
def deltree(dc,uri,exclude={}):
|
||||
def deltree(dc, uri, exclude={}):
|
||||
""" delete a tree of resources
|
||||
|
||||
dc -- dataclass to use
|
||||
|
@ -30,22 +30,22 @@ def deltree(dc,uri,exclude={}):
|
|||
|
||||
"""
|
||||
|
||||
tlist=create_treelist(dc,uri)
|
||||
result={}
|
||||
tlist = create_treelist(dc,uri)
|
||||
result = {}
|
||||
|
||||
for i in range(len(tlist),0,-1):
|
||||
problem_uris=result.keys()
|
||||
element=tlist[i-1]
|
||||
problem_uris = result.keys()
|
||||
element = tlist[i-1]
|
||||
|
||||
# test here, if an element is a prefix of an uri which
|
||||
# generated an error before.
|
||||
# note that we walk here from childs to parents, thus
|
||||
# we cannot delete a parent if a child made a problem.
|
||||
# (see example in 8.6.2.1)
|
||||
ok=1
|
||||
ok = 1
|
||||
for p in problem_uris:
|
||||
if is_prefix(element,p):
|
||||
ok=None
|
||||
ok = None
|
||||
break
|
||||
|
||||
if not ok: continue
|
||||
|
@ -53,7 +53,7 @@ def deltree(dc,uri,exclude={}):
|
|||
# here we test for the exclude list which is the other way round!
|
||||
for p in exclude.keys():
|
||||
if is_prefix(p,element):
|
||||
ok=None
|
||||
ok = None
|
||||
break
|
||||
|
||||
if not ok: continue
|
||||
|
@ -62,11 +62,11 @@ def deltree(dc,uri,exclude={}):
|
|||
try:
|
||||
delone(dc,element)
|
||||
except DAV_Error, (ec,dd):
|
||||
result[element]=ec
|
||||
result[element] = ec
|
||||
|
||||
return result
|
||||
|
||||
def delone(dc,uri):
|
||||
def delone(dc, uri):
|
||||
""" delete a single object """
|
||||
if dc.is_collection(uri):
|
||||
dc.rmcol(uri) # should be empty
|
||||
|
@ -79,7 +79,7 @@ def delone(dc,uri):
|
|||
|
||||
# helper function
|
||||
|
||||
def copy(dc,src,dst):
|
||||
def copy(dc, src, dst):
|
||||
""" only copy the element
|
||||
|
||||
This is just a helper method factored out from copy and
|
||||
|
@ -101,13 +101,13 @@ def copy(dc,src,dst):
|
|||
|
||||
# the main functions
|
||||
|
||||
def copyone(dc,src,dst,overwrite=None):
|
||||
def copyone(dc, src, dst, overwrite=None):
|
||||
""" copy one resource to a new destination """
|
||||
|
||||
if overwrite and dc.exists(dst):
|
||||
delres=deltree(dc,dst)
|
||||
delres = deltree(dc,dst)
|
||||
else:
|
||||
delres={}
|
||||
delres = {}
|
||||
|
||||
# if we cannot delete everything, then do not copy!
|
||||
if delres: return delres
|
||||
|
@ -117,7 +117,7 @@ def copyone(dc,src,dst,overwrite=None):
|
|||
except DAV_Error, (ec,dd):
|
||||
return ec
|
||||
|
||||
def copytree(dc,src,dst,overwrite=None):
|
||||
def copytree(dc, src, dst, overwrite=None):
|
||||
""" copy a tree of resources to another location
|
||||
|
||||
dc -- dataclass to use
|
||||
|
@ -133,32 +133,32 @@ def copytree(dc,src,dst,overwrite=None):
|
|||
|
||||
# first delete the destination resource
|
||||
if overwrite and dc.exists(dst):
|
||||
delres=deltree(dc,dst)
|
||||
delres = deltree(dc,dst)
|
||||
else:
|
||||
delres={}
|
||||
delres = {}
|
||||
|
||||
# if we cannot delete everything, then do not copy!
|
||||
if delres: return delres
|
||||
|
||||
# get the tree we have to copy
|
||||
tlist=create_treelist(dc,src)
|
||||
result={}
|
||||
tlist = create_treelist(dc,src)
|
||||
result = {}
|
||||
|
||||
# prepare destination URIs (get the prefix)
|
||||
dpath=urlparse.urlparse(dst)[2]
|
||||
dpath = urlparse.urlparse(dst)[2]
|
||||
|
||||
for element in tlist:
|
||||
problem_uris=result.keys()
|
||||
problem_uris = result.keys()
|
||||
|
||||
# now URIs get longer and longer thus we have
|
||||
# to test if we had a parent URI which we were not
|
||||
# able to copy in problem_uris which is the prefix
|
||||
# of the actual element. If it is, then we cannot
|
||||
# copy this as well but do not generate another error.
|
||||
ok=1
|
||||
ok = 1
|
||||
for p in problem_uris:
|
||||
if is_prefix(p,element):
|
||||
ok=None
|
||||
ok = None
|
||||
break
|
||||
|
||||
if not ok: continue
|
||||
|
@ -167,14 +167,14 @@ def copytree(dc,src,dst,overwrite=None):
|
|||
# the actual source URI. -> actual_dst
|
||||
# ("subtract" the base src from the URI and prepend the
|
||||
# dst prefix to it.)
|
||||
esrc=replace(element,src,"")
|
||||
actual_dst=dpath+esrc
|
||||
esrc = replace(element,src,"")
|
||||
actual_dst = dpath+esrc
|
||||
|
||||
# now copy stuff
|
||||
try:
|
||||
copy(dc,element,actual_dst)
|
||||
except DAV_Error, (ec,dd):
|
||||
result[element]=ec
|
||||
result[element] = ec
|
||||
|
||||
return result
|
||||
|
||||
|
@ -185,7 +185,7 @@ def copytree(dc,src,dst,overwrite=None):
|
|||
###
|
||||
|
||||
|
||||
def moveone(dc,src,dst,overwrite=None):
|
||||
def moveone(dc, src, dst, overwrite=None):
|
||||
""" move a single resource
|
||||
|
||||
This is done by first copying it and then deleting
|
||||
|
@ -198,7 +198,7 @@ def moveone(dc,src,dst,overwrite=None):
|
|||
# then delete it
|
||||
dc.rm(src)
|
||||
|
||||
def movetree(dc,src,dst,overwrite=None):
|
||||
def movetree(dc, src, dst, overwrite=None):
|
||||
""" move a collection
|
||||
|
||||
This is done by first copying it and then deleting
|
||||
|
@ -209,10 +209,11 @@ def movetree(dc,src,dst,overwrite=None):
|
|||
"""
|
||||
|
||||
# first copy it
|
||||
res=copytree(dc,src,dst,overwrite)
|
||||
res = copytree(dc,src,dst,overwrite)
|
||||
|
||||
# then delete it
|
||||
res=deltree(dc,src,exclude=res)
|
||||
res = deltree(dc,src,exclude=res)
|
||||
|
||||
return res
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -47,11 +47,11 @@ class COPY:
|
|||
"""
|
||||
|
||||
|
||||
def __init__(self,dataclass,src_uri,dst_uri,overwrite):
|
||||
self.__dataclass=dataclass
|
||||
self.__src=src_uri
|
||||
self.__dst=dst_uri
|
||||
self.__overwrite=overwrite
|
||||
def __init__(self, dataclass, src_uri, dst_uri, overwrite):
|
||||
self.__dataclass = dataclass
|
||||
self.__src = src_uri
|
||||
self.__dst = dst_uri
|
||||
self.__overwrite = overwrite
|
||||
|
||||
|
||||
def single_action(self):
|
||||
|
@ -62,16 +62,16 @@ class COPY:
|
|||
|
||||
"""
|
||||
|
||||
dc=self.__dataclass
|
||||
base=self.__src
|
||||
dc = self.__dataclass
|
||||
base = self.__src
|
||||
|
||||
### some basic tests
|
||||
# test if dest exists and overwrite is false
|
||||
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
|
||||
# test if src and dst are the same
|
||||
# (we assume that both uris are on the same server!)
|
||||
ps=urlparse.urlparse(self.__src)[2]
|
||||
pd=urlparse.urlparse(self.__dst)[2]
|
||||
ps = urlparse.urlparse(self.__src)[2]
|
||||
pd = urlparse.urlparse(self.__dst)[2]
|
||||
if ps==pd: raise DAV_Error, 403
|
||||
|
||||
return dc.copyone(self.__src,self.__dst,self.__overwrite)
|
||||
|
@ -84,20 +84,20 @@ class COPY:
|
|||
Here we return a multistatus xml element.
|
||||
|
||||
"""
|
||||
dc=self.__dataclass
|
||||
base=self.__src
|
||||
dc = self.__dataclass
|
||||
base = self.__src
|
||||
|
||||
### some basic tests
|
||||
# test if dest exists and overwrite is false
|
||||
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
|
||||
# test if src and dst are the same
|
||||
# (we assume that both uris are on the same server!)
|
||||
ps=urlparse.urlparse(self.__src)[2]
|
||||
pd=urlparse.urlparse(self.__dst)[2]
|
||||
ps = urlparse.urlparse(self.__src)[2]
|
||||
pd = urlparse.urlparse(self.__dst)[2]
|
||||
if ps==pd: raise DAV_Error, 403
|
||||
|
||||
|
||||
result=dc.copytree(self.__src,self.__dst,self.__overwrite)
|
||||
result = dc.copytree(self.__src,self.__dst,self.__overwrite)
|
||||
#result=copytree(dc,self.__src,self.__dst,self.__overwrite)
|
||||
|
||||
if not result: return None
|
||||
|
@ -109,25 +109,26 @@ class COPY:
|
|||
###
|
||||
|
||||
doc = Document(None)
|
||||
ms=doc.createElement("D:multistatus")
|
||||
ms = doc.createElement("D:multistatus")
|
||||
ms.setAttribute("xmlns:D","DAV:")
|
||||
doc.appendChild(ms)
|
||||
|
||||
for el,ec in result.items():
|
||||
re=doc.createElement("D:response")
|
||||
hr=doc.createElement("D:href")
|
||||
st=doc.createElement("D:status")
|
||||
huri=doc.createTextNode(quote_uri(el))
|
||||
t=doc.createTextNode(gen_estring(ec))
|
||||
re = doc.createElement("D:response")
|
||||
hr = doc.createElement("D:href")
|
||||
st = doc.createElement("D:status")
|
||||
huri = doc.createTextNode(quote_uri(el))
|
||||
t = doc.createTextNode(gen_estring(ec))
|
||||
st.appendChild(t)
|
||||
hr.appendChild(huri)
|
||||
re.appendChild(hr)
|
||||
re.appendChild(st)
|
||||
ms.appendChild(re)
|
||||
|
||||
sfile=StringIO()
|
||||
ext.PrettyPrint(doc,stream=sfile)
|
||||
s=sfile.getvalue()
|
||||
sfile = StringIO()
|
||||
ext.PrettyPrint(doc,stream = sfile)
|
||||
s = sfile.getvalue()
|
||||
sfile.close()
|
||||
return s
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -47,11 +47,11 @@ class MOVE:
|
|||
"""
|
||||
|
||||
|
||||
def __init__(self,dataclass,src_uri,dst_uri,overwrite):
|
||||
self.__dataclass=dataclass
|
||||
self.__src=src_uri
|
||||
self.__dst=dst_uri
|
||||
self.__overwrite=overwrite
|
||||
def __init__(self, dataclass, src_uri, dst_uri, overwrite):
|
||||
self.__dataclass = dataclass
|
||||
self.__src = src_uri
|
||||
self.__dst = dst_uri
|
||||
self.__overwrite = overwrite
|
||||
|
||||
|
||||
def single_action(self):
|
||||
|
@ -62,16 +62,16 @@ class MOVE:
|
|||
|
||||
"""
|
||||
|
||||
dc=self.__dataclass
|
||||
base=self.__src
|
||||
dc = self.__dataclass
|
||||
base = self.__src
|
||||
|
||||
### some basic tests
|
||||
# test if dest exists and overwrite is false
|
||||
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
|
||||
# test if src and dst are the same
|
||||
# (we assume that both uris are on the same server!)
|
||||
ps=urlparse.urlparse(self.__src)[2]
|
||||
pd=urlparse.urlparse(self.__dst)[2]
|
||||
ps = urlparse.urlparse(self.__src)[2]
|
||||
pd = urlparse.urlparse(self.__dst)[2]
|
||||
if ps==pd: raise DAV_Error, 403
|
||||
|
||||
return dc.moveone(self.__src,self.__dst,self.__overwrite)
|
||||
|
@ -82,21 +82,22 @@ class MOVE:
|
|||
Here we return a multistatus xml element.
|
||||
|
||||
"""
|
||||
dc=self.__dataclass
|
||||
base=self.__src
|
||||
dc = self.__dataclass
|
||||
base = self.__src
|
||||
|
||||
### some basic tests
|
||||
# test if dest exists and overwrite is false
|
||||
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
|
||||
# test if src and dst are the same
|
||||
# (we assume that both uris are on the same server!)
|
||||
ps=urlparse.urlparse(self.__src)[2]
|
||||
pd=urlparse.urlparse(self.__dst)[2]
|
||||
ps = urlparse.urlparse(self.__src)[2]
|
||||
pd = urlparse.urlparse(self.__dst)[2]
|
||||
if ps==pd: raise DAV_Error, 403
|
||||
|
||||
result=dc.movetree(self.__src,self.__dst,self.__overwrite)
|
||||
result = dc.movetree(self.__src,self.__dst,self.__overwrite)
|
||||
if not result: return None
|
||||
|
||||
# create the multistatus XML element
|
||||
return make_xmlresponse(result)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -32,15 +32,15 @@ from davcmd import deltree
|
|||
|
||||
class DELETE:
|
||||
|
||||
def __init__(self,uri,dataclass):
|
||||
self.__dataclass=dataclass
|
||||
self.__uri=uri
|
||||
def __init__(self, uri, dataclass):
|
||||
self.__dataclass = dataclass
|
||||
self.__uri = uri
|
||||
|
||||
def delcol(self):
|
||||
""" delete a collection """
|
||||
|
||||
dc=self.__dataclass
|
||||
result=dc.deltree(self.__uri)
|
||||
dc = self.__dataclass
|
||||
result = dc.deltree(self.__uri)
|
||||
|
||||
if not len(result.items()):
|
||||
return None # everything ok
|
||||
|
@ -51,8 +51,8 @@ class DELETE:
|
|||
def delone(self):
|
||||
""" delete a resource """
|
||||
|
||||
dc=self.__dataclass
|
||||
result=dc.delone(self.__uri)
|
||||
dc = self.__dataclass
|
||||
result = dc.delone(self.__uri)
|
||||
|
||||
if not result: return None
|
||||
if not len(result.items()):
|
||||
|
@ -61,3 +61,4 @@ class DELETE:
|
|||
# create the result element
|
||||
return make_xmlresponse(result)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -12,11 +12,11 @@ class DAV_Error(Exception):
|
|||
2. the error result element, e.g. a <multistatus> element
|
||||
"""
|
||||
|
||||
def __init__(self,*args):
|
||||
def __init__(self, *args):
|
||||
if len(args)==1:
|
||||
self.args=(args[0],"")
|
||||
self.args = (args[0],"")
|
||||
else:
|
||||
self.args=args
|
||||
self.args = args
|
||||
|
||||
class DAV_Secret(DAV_Error):
|
||||
""" the user is not allowed to know anything about it
|
||||
|
@ -32,9 +32,9 @@ class DAV_Secret(DAV_Error):
|
|||
class DAV_NotFound(DAV_Error):
|
||||
""" a requested property was not found for a resource """
|
||||
|
||||
def __init__(self,*args):
|
||||
def __init__(self, *args):
|
||||
if len(args):
|
||||
if isinstance(args[0],list):
|
||||
if isinstance(args[0], list):
|
||||
stre = "Path %s not found!"%('/'.join(args[0]))
|
||||
else:
|
||||
stre = args[0]
|
||||
|
@ -47,10 +47,11 @@ class DAV_NotFound(DAV_Error):
|
|||
class DAV_Forbidden(DAV_Error):
|
||||
""" a method on a resource is not allowed """
|
||||
|
||||
def __init__(self,*args):
|
||||
def __init__(self, *args):
|
||||
if len(args):
|
||||
DAV_Error.__init__(self,403,args[0])
|
||||
else:
|
||||
DAV_Error.__init__(self,403)
|
||||
pass
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -36,10 +36,10 @@ class dav_interface:
|
|||
# the first item is the namespace URI and the second one
|
||||
# the method prefix
|
||||
# e.g. for DAV:getcontenttype we call dav_getcontenttype()
|
||||
M_NS={"DAV:" : "_get_dav",
|
||||
M_NS = {"DAV:" : "_get_dav",
|
||||
"NS2" : "ns2" }
|
||||
|
||||
def get_propnames(self,uri):
|
||||
def get_propnames(self, uri):
|
||||
""" return the property names allowed for the given URI
|
||||
|
||||
In this method we simply return the above defined properties
|
||||
|
@ -50,14 +50,14 @@ class dav_interface:
|
|||
"""
|
||||
return self.PROPS
|
||||
|
||||
def get_prop2(self,uri,ns,pname):
|
||||
def get_prop2(self, uri, ns, pname):
|
||||
""" return the value of a property
|
||||
"""
|
||||
if lower(ns)=="dav:": return self.get_dav(uri,pname)
|
||||
|
||||
raise DAV_NotFound
|
||||
|
||||
def get_prop(self,uri,ns,propname):
|
||||
def get_prop(self, uri, ns, propname):
|
||||
""" return the value of a given property
|
||||
|
||||
uri -- uri of the object to get the property of
|
||||
|
@ -65,17 +65,17 @@ class dav_interface:
|
|||
pname -- name of the property
|
||||
"""
|
||||
if self.M_NS.has_key(ns):
|
||||
prefix=self.M_NS[ns]
|
||||
prefix = self.M_NS[ns]
|
||||
else:
|
||||
print "No namespace:",ns, "( for prop:", propname,")"
|
||||
raise DAV_NotFound
|
||||
mname=prefix+"_"+propname
|
||||
mname = prefix+"_"+propname
|
||||
if not hasattr(self,mname):
|
||||
raise DAV_NotFound
|
||||
|
||||
try:
|
||||
m=getattr(self,mname)
|
||||
r=m(uri)
|
||||
m = getattr(self,mname)
|
||||
r = m(uri)
|
||||
return r
|
||||
except AttributeError, e:
|
||||
print 'Property %s not supported' % propname
|
||||
|
@ -86,7 +86,7 @@ class dav_interface:
|
|||
### DATA methods (for GET and PUT)
|
||||
###
|
||||
|
||||
def get_data(self,uri):
|
||||
def get_data(self, uri):
|
||||
""" return the content of an object
|
||||
|
||||
return data or raise an exception
|
||||
|
@ -94,7 +94,7 @@ class dav_interface:
|
|||
"""
|
||||
raise DAV_NotFound
|
||||
|
||||
def put(self,uri,data):
|
||||
def put(self, uri, data):
|
||||
""" write an object to the repository
|
||||
|
||||
return a result code or raise an exception
|
||||
|
@ -106,17 +106,17 @@ class dav_interface:
|
|||
### Methods for DAV properties
|
||||
###
|
||||
|
||||
def _get_dav_creationdate(self,uri):
|
||||
def _get_dav_creationdate(self, uri):
|
||||
""" return the creationdate of a resource """
|
||||
d=self.get_creationdate(uri)
|
||||
d = self.get_creationdate(uri)
|
||||
# format it
|
||||
if isinstance(d, int) or isinstance(d, float):
|
||||
d = time.localtimetime(d)
|
||||
return time.strftime("%Y-%m-%dT%H:%M:%S%Z",d)
|
||||
|
||||
def _get_dav_getlastmodified(self,uri):
|
||||
def _get_dav_getlastmodified(self, uri):
|
||||
""" return the last modified date of a resource """
|
||||
d=self.get_lastmodified(uri)
|
||||
d = self.get_lastmodified(uri)
|
||||
if isinstance(d, int) or isinstance(d, float):
|
||||
d = time.localtime(d)
|
||||
# format it
|
||||
|
@ -127,11 +127,11 @@ class dav_interface:
|
|||
### OVERRIDE THESE!
|
||||
###
|
||||
|
||||
def get_creationdate(self,uri):
|
||||
def get_creationdate(self, uri):
|
||||
""" return the creationdate of the resource """
|
||||
return time.time()
|
||||
|
||||
def get_lastmodified(self,uri):
|
||||
def get_lastmodified(self, uri):
|
||||
""" return the last modification date of the resource """
|
||||
return time.time()
|
||||
|
||||
|
@ -142,7 +142,7 @@ class dav_interface:
|
|||
|
||||
### methods for deleting a resource
|
||||
|
||||
def rmcol(self,uri):
|
||||
def rmcol(self, uri):
|
||||
""" delete a collection
|
||||
|
||||
This should not delete any children! This is automatically done
|
||||
|
@ -153,7 +153,7 @@ class dav_interface:
|
|||
"""
|
||||
raise DAV_NotFound
|
||||
|
||||
def rm(self,uri):
|
||||
def rm(self, uri):
|
||||
""" delete a single resource
|
||||
|
||||
return a success code or raise an exception
|
||||
|
@ -210,27 +210,27 @@ class dav_interface:
|
|||
|
||||
### MOVE handlers
|
||||
|
||||
def moveone(self,src,dst,overwrite):
|
||||
def moveone(self, src, dst, overwrite):
|
||||
""" move one resource with Depth=0 """
|
||||
return moveone(self,src,dst,overwrite)
|
||||
return moveone(self, src, dst, overwrite)
|
||||
|
||||
def movetree(self,src,dst,overwrite):
|
||||
def movetree(self, src, dst, overwrite):
|
||||
""" move a collection with Depth=infinity """
|
||||
return movetree(self,src,dst,overwrite)
|
||||
return movetree(self, src, dst, overwrite)
|
||||
|
||||
### COPY handlers
|
||||
|
||||
def copyone(self,src,dst,overwrite):
|
||||
def copyone(self, src, dst, overwrite):
|
||||
""" copy one resource with Depth=0 """
|
||||
return copyone(self,src,dst,overwrite)
|
||||
return copyone(self, src, dst, overwrite)
|
||||
|
||||
def copytree(self,src,dst,overwrite):
|
||||
def copytree(self, src, dst, overwrite):
|
||||
""" copy a collection with Depth=infinity """
|
||||
return copytree(self,src,dst,overwrite)
|
||||
return copytree(self, src, dst, overwrite)
|
||||
|
||||
|
||||
### low level copy methods (you only need these for method 2)
|
||||
def copy(self,src,dst):
|
||||
def copy(self, src, dst):
|
||||
""" copy a resource with depth==0
|
||||
|
||||
You don't need to bother about overwrite or not.
|
||||
|
@ -241,7 +241,7 @@ class dav_interface:
|
|||
return 201
|
||||
|
||||
|
||||
def copycol(self,src,dst):
|
||||
def copycol(self, src, dst):
|
||||
""" copy a resource with depth==infinity
|
||||
|
||||
You don't need to bother about overwrite or not.
|
||||
|
@ -253,11 +253,12 @@ class dav_interface:
|
|||
|
||||
### some utility functions you need to implement
|
||||
|
||||
def exists(self,uri):
|
||||
def exists(self, uri):
|
||||
""" return 1 or None depending on if a resource exists """
|
||||
return None # no
|
||||
|
||||
def is_collection(self,uri):
|
||||
def is_collection(self, uri):
|
||||
""" return 1 or None depending on if a resource is a collection """
|
||||
return None # no
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -18,8 +18,8 @@
|
|||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
from xml.dom import ext
|
||||
from xml.dom.Document import Document
|
||||
|
@ -45,9 +45,9 @@ class PROPFIND:
|
|||
|
||||
It will set the following instance vars:
|
||||
|
||||
request_class : ALLPROP | PROPNAME | PROP
|
||||
proplist : list of properties
|
||||
nsmap : map of namespaces
|
||||
request_class: ALLPROP | PROPNAME | PROP
|
||||
proplist: list of properties
|
||||
nsmap: map of namespaces
|
||||
|
||||
The list of properties will contain tuples of the form
|
||||
(element name, ns_prefix, ns_uri)
|
||||
|
@ -55,20 +55,19 @@ class PROPFIND:
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self, uri, dataclass, depth):
|
||||
self.request_type = None
|
||||
self.nsmap = {}
|
||||
self.proplist = {}
|
||||
self.default_ns = None
|
||||
self.__dataclass = dataclass
|
||||
self.__depth = str(depth)
|
||||
self.__uri = uri
|
||||
self.use_full_urls = True
|
||||
self.__has_body = None # did we parse a body?
|
||||
|
||||
def __init__(self,uri,dataclass,depth):
|
||||
self.request_type=None
|
||||
self.nsmap={}
|
||||
self.proplist={}
|
||||
self.default_ns=None
|
||||
self.__dataclass=dataclass
|
||||
self.__depth=str(depth)
|
||||
self.__uri=uri
|
||||
self.use_full_urls=True
|
||||
self.__has_body=None # did we parse a body?
|
||||
|
||||
def read_propfind(self,xml_doc):
|
||||
self.request_type,self.proplist,self.namespaces=utils.parse_propfind(xml_doc)
|
||||
def read_propfind(self, xml_doc):
|
||||
self.request_type,self.proplist,self.namespaces = utils.parse_propfind(xml_doc)
|
||||
|
||||
# a violation of the expected logic: client (korganizer) will ask for DAV:resourcetype
|
||||
# but we also have to return the http://groupdav.org/:resourcetype property!
|
||||
|
@ -114,41 +113,41 @@ class PROPFIND:
|
|||
def create_propname(self):
|
||||
""" create a multistatus response for the prop names """
|
||||
|
||||
dc=self.__dataclass
|
||||
dc = self.__dataclass
|
||||
# create the document generator
|
||||
doc = Document(None)
|
||||
ms=doc.createElement("D:multistatus")
|
||||
ms = doc.createElement("D:multistatus")
|
||||
ms.setAttribute("xmlns:D","DAV:")
|
||||
doc.appendChild(ms)
|
||||
|
||||
if self.__depth=="0":
|
||||
pnames=dc.get_propnames(self.__uri)
|
||||
re=self.mk_propname_response(self.__uri,pnames,doc)
|
||||
pnames = dc.get_propnames(self.__uri)
|
||||
re = self.mk_propname_response(self.__uri,pnames,doc)
|
||||
ms.appendChild(re)
|
||||
|
||||
elif self.__depth=="1":
|
||||
pnames=dc.get_propnames(self.__uri)
|
||||
re=self.mk_propname_response(self.__uri,pnames,doc)
|
||||
pnames = dc.get_propnames(self.__uri)
|
||||
re = self.mk_propname_response(self.__uri,pnames,doc)
|
||||
ms.appendChild(re)
|
||||
|
||||
for newuri in dc.get_childs(self.__uri):
|
||||
pnames=dc.get_propnames(newuri)
|
||||
re=self.mk_propname_response(newuri,pnames,doc)
|
||||
pnames = dc.get_propnames(newuri)
|
||||
re = self.mk_propname_response(newuri,pnames,doc)
|
||||
ms.appendChild(re)
|
||||
# *** depth=="infinity"
|
||||
|
||||
sfile=StringIO()
|
||||
ext.PrettyPrint(doc,stream=sfile)
|
||||
s=sfile.getvalue()
|
||||
sfile = StringIO()
|
||||
ext.PrettyPrint(doc,stream = sfile)
|
||||
s = sfile.getvalue()
|
||||
sfile.close()
|
||||
return s
|
||||
|
||||
def create_allprop(self):
|
||||
""" return a list of all properties """
|
||||
self.proplist={}
|
||||
self.namespaces=[]
|
||||
self.proplist = {}
|
||||
self.namespaces = []
|
||||
for ns,plist in self.__dataclass.get_propnames(self.__uri).items():
|
||||
self.proplist[ns]=plist
|
||||
self.proplist[ns] = plist
|
||||
self.namespaces.append(ns)
|
||||
|
||||
return self.create_prop()
|
||||
|
@ -178,32 +177,32 @@ class PROPFIND:
|
|||
|
||||
# create the document generator
|
||||
doc = Document(None)
|
||||
ms=doc.createElement("D:multistatus")
|
||||
ms = doc.createElement("D:multistatus")
|
||||
ms.setAttribute("xmlns:D","DAV:")
|
||||
doc.appendChild(ms)
|
||||
|
||||
if self.__depth=="0":
|
||||
gp,bp=self.get_propvalues(self.__uri)
|
||||
res=self.mk_prop_response(self.__uri,gp,bp,doc)
|
||||
gp,bp = self.get_propvalues(self.__uri)
|
||||
res = self.mk_prop_response(self.__uri,gp,bp,doc)
|
||||
ms.appendChild(res)
|
||||
|
||||
elif self.__depth=="1":
|
||||
gp,bp=self.get_propvalues(self.__uri)
|
||||
res=self.mk_prop_response(self.__uri,gp,bp,doc)
|
||||
gp,bp = self.get_propvalues(self.__uri)
|
||||
res = self.mk_prop_response(self.__uri,gp,bp,doc)
|
||||
ms.appendChild(res)
|
||||
|
||||
try:
|
||||
for newuri in self.__dataclass.get_childs(self.__uri):
|
||||
gp,bp=self.get_propvalues(newuri)
|
||||
res=self.mk_prop_response(newuri,gp,bp,doc)
|
||||
gp,bp = self.get_propvalues(newuri)
|
||||
res = self.mk_prop_response(newuri,gp,bp,doc)
|
||||
ms.appendChild(res)
|
||||
except DAV_NotFound:
|
||||
# If no children, never mind.
|
||||
pass
|
||||
|
||||
sfile=StringIO()
|
||||
ext.PrettyPrint(doc,stream=sfile)
|
||||
s=sfile.getvalue()
|
||||
sfile = StringIO()
|
||||
ext.PrettyPrint(doc,stream = sfile)
|
||||
s = sfile.getvalue()
|
||||
sfile.close()
|
||||
return s
|
||||
|
||||
|
@ -215,32 +214,32 @@ class PROPFIND:
|
|||
propnames should have the format {NS1 : [prop1, prop2, ...], NS2: ...}
|
||||
|
||||
"""
|
||||
re=doc.createElement("D:response")
|
||||
re = doc.createElement("D:response")
|
||||
|
||||
# write href information
|
||||
href=doc.createElement("D:href")
|
||||
href = doc.createElement("D:href")
|
||||
if self.use_full_urls:
|
||||
huri=doc.createTextNode(uri)
|
||||
huri = doc.createTextNode(uri)
|
||||
else:
|
||||
uparts=urlparse.urlparse(uri)
|
||||
fileloc=uparts[2]
|
||||
huri=doc.createTextNode(urllib.quote(fileloc.encode('utf8')))
|
||||
uparts = urlparse.urlparse(uri)
|
||||
fileloc = uparts[2]
|
||||
huri = doc.createTextNode(urllib.quote(fileloc.encode('utf8')))
|
||||
href.appendChild(huri)
|
||||
re.appendChild(href)
|
||||
|
||||
ps=doc.createElement("D:propstat")
|
||||
nsnum=0
|
||||
ps = doc.createElement("D:propstat")
|
||||
nsnum = 0
|
||||
|
||||
for ns,plist in propnames.items():
|
||||
# write prop element
|
||||
pr=doc.createElement("D:prop")
|
||||
nsp="ns"+str(nsnum)
|
||||
pr = doc.createElement("D:prop")
|
||||
nsp = "ns"+str(nsnum)
|
||||
pr.setAttribute("xmlns:"+nsp,ns)
|
||||
nsnum=nsnum+1
|
||||
nsnum = nsnum+1
|
||||
|
||||
# write propertynames
|
||||
for p in plist:
|
||||
pe=doc.createElement(nsp+":"+p)
|
||||
pe = doc.createElement(nsp+":"+p)
|
||||
pr.appendChild(pe)
|
||||
|
||||
ps.appendChild(pr)
|
||||
|
@ -257,33 +256,33 @@ class PROPFIND:
|
|||
one, that means).
|
||||
|
||||
"""
|
||||
re=doc.createElement("D:response")
|
||||
re = doc.createElement("D:response")
|
||||
# append namespaces to response
|
||||
nsnum=0
|
||||
nsnum = 0
|
||||
for nsname in self.namespaces:
|
||||
re.setAttribute("xmlns:ns"+str(nsnum),nsname)
|
||||
nsnum=nsnum+1
|
||||
nsnum = nsnum+1
|
||||
|
||||
# write href information
|
||||
href=doc.createElement("D:href")
|
||||
href = doc.createElement("D:href")
|
||||
if self.use_full_urls:
|
||||
huri=doc.createTextNode(uri)
|
||||
huri = doc.createTextNode(uri)
|
||||
else:
|
||||
uparts=urlparse.urlparse(uri)
|
||||
fileloc=uparts[2]
|
||||
huri=doc.createTextNode(urllib.quote(fileloc.encode('utf8')))
|
||||
uparts = urlparse.urlparse(uri)
|
||||
fileloc = uparts[2]
|
||||
huri = doc.createTextNode(urllib.quote(fileloc.encode('utf8')))
|
||||
href.appendChild(huri)
|
||||
re.appendChild(href)
|
||||
|
||||
# write good properties
|
||||
if good_props and len(good_props.items()):
|
||||
ps=doc.createElement("D:propstat")
|
||||
ps = doc.createElement("D:propstat")
|
||||
|
||||
gp=doc.createElement("D:prop")
|
||||
gp = doc.createElement("D:prop")
|
||||
for ns in good_props.keys():
|
||||
ns_prefix="ns"+str(self.namespaces.index(ns))+":"
|
||||
for p,v in good_props[ns].items():
|
||||
pe=doc.createElement(ns_prefix+str(p))
|
||||
pe = doc.createElement(ns_prefix+str(p))
|
||||
if v == None:
|
||||
pass
|
||||
elif ns=='DAV:' and p=="resourcetype":
|
||||
|
@ -294,15 +293,15 @@ class PROPFIND:
|
|||
ve=doc.createElement(ns_prefix+v[0])
|
||||
pe.appendChild(ve)
|
||||
else:
|
||||
ve=doc.createTextNode(utf8str(v))
|
||||
ve = doc.createTextNode(utf8str(v))
|
||||
pe.appendChild(ve)
|
||||
|
||||
gp.appendChild(pe)
|
||||
if gp.hasChildNodes():
|
||||
re.appendChild(ps)
|
||||
ps.appendChild(gp)
|
||||
s=doc.createElement("D:status")
|
||||
t=doc.createTextNode("HTTP/1.1 200 OK")
|
||||
s = doc.createElement("D:status")
|
||||
t = doc.createTextNode("HTTP/1.1 200 OK")
|
||||
s.appendChild(t)
|
||||
ps.appendChild(s)
|
||||
re.appendChild(ps)
|
||||
|
@ -312,20 +311,20 @@ class PROPFIND:
|
|||
|
||||
# write a propstat for each error code
|
||||
for ecode in bad_props.keys():
|
||||
ps=doc.createElement("D:propstat")
|
||||
ps = doc.createElement("D:propstat")
|
||||
re.appendChild(ps)
|
||||
bp=doc.createElement("D:prop")
|
||||
bp = doc.createElement("D:prop")
|
||||
ps.appendChild(bp)
|
||||
|
||||
for ns in bad_props[ecode].keys():
|
||||
ns_prefix="ns"+str(self.namespaces.index(ns))+":"
|
||||
ns_prefix = "ns"+str(self.namespaces.index(ns))+":"
|
||||
|
||||
for p in bad_props[ecode][ns]:
|
||||
pe=doc.createElement(ns_prefix+str(p))
|
||||
pe = doc.createElement(ns_prefix+str(p))
|
||||
bp.appendChild(pe)
|
||||
|
||||
s=doc.createElement("D:status")
|
||||
t=doc.createTextNode(utils.gen_estring(ecode))
|
||||
s = doc.createElement("D:status")
|
||||
t = doc.createTextNode(utils.gen_estring(ecode))
|
||||
s.appendChild(t)
|
||||
ps.appendChild(s)
|
||||
re.appendChild(ps)
|
||||
|
@ -342,20 +341,20 @@ class PROPFIND:
|
|||
found or the user is not allowed to read them.
|
||||
|
||||
"""
|
||||
good_props={}
|
||||
bad_props={}
|
||||
good_props = {}
|
||||
bad_props = {}
|
||||
|
||||
for (ns,plist) in self.proplist.items():
|
||||
good_props[ns]={}
|
||||
bad_props={}
|
||||
good_props[ns] = {}
|
||||
bad_props = {}
|
||||
ec = 0
|
||||
for prop in plist:
|
||||
try:
|
||||
ec = 0
|
||||
r=self.__dataclass.get_prop(uri,ns,prop)
|
||||
good_props[ns][prop]=r
|
||||
r = self.__dataclass.get_prop(uri,ns,prop)
|
||||
good_props[ns][prop] = r
|
||||
except DAV_Error, error_code:
|
||||
ec=error_code[0]
|
||||
ec = error_code[0]
|
||||
|
||||
# ignore props with error_code if 0 (invisible)
|
||||
if ec==0: continue
|
||||
|
@ -364,9 +363,11 @@ class PROPFIND:
|
|||
if bad_props[ec].has_key(ns):
|
||||
bad_props[ec][ns].append(prop)
|
||||
else:
|
||||
bad_props[ec][ns]=[prop]
|
||||
bad_props[ec][ns] = [prop]
|
||||
else:
|
||||
bad_props[ec]={ns:[prop]}
|
||||
bad_props[ec] = {ns:[prop]}
|
||||
|
||||
return good_props, bad_props
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -27,7 +27,7 @@ AUTHOR = 'Simon Pamies <s.pamies@banality.de>'
|
|||
|
||||
def gen_estring(ecode):
|
||||
""" generate an error string from the given code """
|
||||
ec=atoi(str(ecode))
|
||||
ec = atoi(str(ecode))
|
||||
if STATUS_CODES.has_key(ec):
|
||||
return "HTTP/1.1 %s %s" %(ec,STATUS_CODES[ec])
|
||||
else:
|
||||
|
@ -46,20 +46,20 @@ def parse_propfind(xml_doc):
|
|||
doc = PyExpat.Reader().fromString(xml_doc)
|
||||
snit = doc.createNodeIterator(doc, NodeFilter.NodeFilter.SHOW_ELEMENT, None, None)
|
||||
|
||||
request_type=None
|
||||
props={}
|
||||
namespaces=[]
|
||||
request_type = None
|
||||
props = {}
|
||||
namespaces = []
|
||||
|
||||
while 1:
|
||||
curr_elem = snit.nextNode()
|
||||
if not curr_elem: break
|
||||
ename=fname=lower(curr_elem.nodeName)
|
||||
ename=fname = lower(curr_elem.nodeName)
|
||||
if ":" in fname:
|
||||
ename=split(fname,":")[1]
|
||||
if ename=="prop": request_type=RT_PROP; continue
|
||||
ename = split(fname,":")[1]
|
||||
if ename=="prop": request_type = RT_PROP; continue
|
||||
if ename=="propfind": continue
|
||||
if ename=="allprop": request_type=RT_ALLPROP; continue
|
||||
if ename=="propname": request_type=RT_PROPNAME; continue
|
||||
if ename=="allprop": request_type = RT_ALLPROP; continue
|
||||
if ename=="propname": request_type = RT_PROPNAME; continue
|
||||
|
||||
# rest should be names of attributes
|
||||
|
||||
|
@ -67,13 +67,13 @@ def parse_propfind(xml_doc):
|
|||
if props.has_key(ns):
|
||||
props[ns].append(ename)
|
||||
else:
|
||||
props[ns]=[ename]
|
||||
props[ns] = [ename]
|
||||
namespaces.append(ns)
|
||||
|
||||
return request_type,props,namespaces
|
||||
|
||||
|
||||
def create_treelist(dataclass,uri):
|
||||
def create_treelist(dataclass, uri):
|
||||
""" create a list of resources out of a tree
|
||||
|
||||
This function is used for the COPY, MOVE and DELETE methods
|
||||
|
@ -83,23 +83,23 @@ def create_treelist(dataclass,uri):
|
|||
It will return the flattened tree as list
|
||||
|
||||
"""
|
||||
queue=[uri]
|
||||
list=[uri]
|
||||
queue = [uri]
|
||||
list = [uri]
|
||||
while len(queue):
|
||||
element=queue[-1]
|
||||
element = queue[-1]
|
||||
if dataclass.is_collection(element):
|
||||
childs=dataclass.get_childs(element)
|
||||
childs = dataclass.get_childs(element)
|
||||
else:
|
||||
childs=[]
|
||||
childs = []
|
||||
if len(childs):
|
||||
list=list+childs
|
||||
list = list+childs
|
||||
# update queue
|
||||
del queue[-1]
|
||||
if len(childs):
|
||||
queue=queue+childs
|
||||
queue = queue+childs
|
||||
return list
|
||||
|
||||
def is_prefix(uri1,uri2):
|
||||
def is_prefix(uri1, uri2):
|
||||
""" returns 1 of uri1 is a prefix of uri2 """
|
||||
if uri2[:len(uri1)]==uri1:
|
||||
return 1
|
||||
|
@ -111,50 +111,51 @@ def quote_uri(uri):
|
|||
import urlparse
|
||||
import urllib
|
||||
|
||||
up=urlparse.urlparse(uri)
|
||||
np=urllib.quote(up[2])
|
||||
return urlparse.urlunparse((up[0],up[1],np,up[3],up[4],up[5]))
|
||||
up = urlparse.urlparse(uri)
|
||||
np = urllib.quote(up[2])
|
||||
return urlparse.urlunparse((up[0], up[1], np, up[3], up[4], up[5]))
|
||||
|
||||
def get_uriparentpath(uri):
|
||||
""" extract the uri path and remove the last element """
|
||||
up=urlparse.urlparse(uri)
|
||||
return joinfields(split(up[2],"/")[:-1],"/")
|
||||
up = urlparse.urlparse(uri)
|
||||
return joinfields(split(up[2], "/")[:-1], "/")
|
||||
|
||||
def get_urifilename(uri):
|
||||
""" extract the uri path and return the last element """
|
||||
up=urlparse.urlparse(uri)
|
||||
return split(up[2],"/")[-1]
|
||||
up = urlparse.urlparse(uri)
|
||||
return split(up[2], "/")[-1]
|
||||
|
||||
def get_parenturi(uri):
|
||||
""" return the parent of the given resource"""
|
||||
up=urlparse.urlparse(uri)
|
||||
np=joinfields(split(up[2],"/")[:-1],"/")
|
||||
return urlparse.urlunparse((up[0],up[1],np,up[3],up[4],up[5]))
|
||||
up = urlparse.urlparse(uri)
|
||||
np = joinfields(split(up[2], "/")[:-1], "/")
|
||||
return urlparse.urlunparse((up[0], up[1], np, up[3], up[4], up[5]))
|
||||
|
||||
### XML utilities
|
||||
|
||||
def make_xmlresponse(result):
|
||||
""" construct a response from a dict of uri:error_code elements """
|
||||
doc = Document(None)
|
||||
ms=doc.createElement("D:multistatus")
|
||||
ms.setAttribute("xmlns:D","DAV:")
|
||||
ms = doc.createElement("D:multistatus")
|
||||
ms.setAttribute("xmlns:D", "DAV:")
|
||||
doc.appendChild(ms)
|
||||
|
||||
for el,ec in result.items():
|
||||
re=doc.createElement("D:response")
|
||||
hr=doc.createElement("D:href")
|
||||
st=doc.createElement("D:status")
|
||||
huri=doc.createTextNode(quote_uri(el))
|
||||
t=doc.createTextNode(gen_estring(ec))
|
||||
for el, ec in result.items():
|
||||
re = doc.createElement("D:response")
|
||||
hr = doc.createElement("D:href")
|
||||
st = doc.createElement("D:status")
|
||||
huri = doc.createTextNode(quote_uri(el))
|
||||
t = doc.createTextNode(gen_estring(ec))
|
||||
st.appendChild(t)
|
||||
hr.appendChild(huri)
|
||||
re.appendChild(hr)
|
||||
re.appendChild(st)
|
||||
ms.appendChild(re)
|
||||
|
||||
sfile=StringIO()
|
||||
ext.PrettyPrint(doc,stream=sfile)
|
||||
s=sfile.getvalue()
|
||||
sfile = StringIO()
|
||||
ext.PrettyPrint(doc, stream = sfile)
|
||||
s = sfile.getvalue()
|
||||
sfile.close()
|
||||
return s
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -36,7 +36,8 @@ import time
|
|||
try:
|
||||
import vobject
|
||||
except ImportError:
|
||||
raise osv.except_osv('vobject Import Error!','Please install python-vobject from http://vobject.skyhouseconsulting.com/')
|
||||
raise osv.except_osv('vobject Import Error!','Please install python-vobject \
|
||||
from http://vobject.skyhouseconsulting.com/')
|
||||
|
||||
# O-1 Optional and can come only once
|
||||
# O-n Optional and can come more than once
|
||||
|
@ -44,6 +45,12 @@ except ImportError:
|
|||
# R-n Required and can come more than once
|
||||
|
||||
def uid2openobjectid(cr, uidval, oomodel, rdate):
|
||||
""" UID To Open Object Id
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uidval: Get USerId vale
|
||||
@oomodel: Open Object ModelName
|
||||
@param rdate: Get Recurrent Date
|
||||
"""
|
||||
__rege = re.compile(r'OpenObject-([\w|\.]+)_([0-9]+)@(\w+)$')
|
||||
wematch = __rege.match(uidval.encode('utf8'))
|
||||
if not wematch:
|
||||
|
@ -67,10 +74,21 @@ def uid2openobjectid(cr, uidval, oomodel, rdate):
|
|||
return (False, None)
|
||||
|
||||
def openobjectid2uid(cr, uidval, oomodel):
|
||||
""" Open Object Id To UId
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uidval: Get USerId vale
|
||||
@oomodel: Open Object ModelName """
|
||||
|
||||
value = 'OpenObject-%s_%s@%s' % (oomodel, uidval, cr.dbname)
|
||||
return value
|
||||
|
||||
def get_attribute_mapping(cr, uid, calname, context={}):
|
||||
""" Attribute Mapping with Basic calendar fields and lines
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param calname: Get Calendar name
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
|
@ -100,6 +118,10 @@ def get_attribute_mapping(cr, uid, calname, context={}):
|
|||
return res
|
||||
|
||||
def map_data(cr, uid, obj):
|
||||
""" Map Data
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,"""
|
||||
|
||||
vals = {}
|
||||
for map_dict in obj.__attribute__:
|
||||
map_val = obj.ical_get(map_dict, 'value')
|
||||
|
@ -149,11 +171,23 @@ class CalDAV(object):
|
|||
|
||||
|
||||
def ical_set(self, name, value, type):
|
||||
""" set calendar Attribute
|
||||
@param self: The object pointer,
|
||||
@param name: Get Attribute Name
|
||||
@param value: Get Attribute Value
|
||||
@param type: Get Attribute Type
|
||||
"""
|
||||
if name in self.__attribute__ and self.__attribute__[name]:
|
||||
self.__attribute__[name][type] = value
|
||||
return True
|
||||
|
||||
def ical_get(self, name, type):
|
||||
""" Get calendar Attribute
|
||||
@param self: The object pointer,
|
||||
@param name: Get Attribute Name
|
||||
@param type: Get Attribute Type
|
||||
"""
|
||||
|
||||
if self.__attribute__.get(name):
|
||||
val = self.__attribute__.get(name).get(type, None)
|
||||
valtype = self.__attribute__.get(name).get('type', None)
|
||||
|
@ -168,12 +202,23 @@ class CalDAV(object):
|
|||
return self.__attribute__.get(name, None)
|
||||
|
||||
def ical_reset(self, type):
|
||||
""" Reset Calendar Attribute
|
||||
@param self: The object pointer,
|
||||
@param type: Get Attribute Type
|
||||
"""
|
||||
|
||||
for name in self.__attribute__:
|
||||
if self.__attribute__[name]:
|
||||
self.__attribute__[name][type] = None
|
||||
return True
|
||||
|
||||
def parse_ics(self, cr, uid, child, cal_children=None, context=None):
|
||||
""" parse calendaring and scheduling information
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
att_data = []
|
||||
for cal_data in child.getChildren():
|
||||
if cal_data.name.lower() == 'attendee':
|
||||
|
@ -205,6 +250,12 @@ class CalDAV(object):
|
|||
return vals
|
||||
|
||||
def create_ics(self, cr, uid, datas, name, ical, context=None):
|
||||
""" create calendaring and scheduling information
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
if not datas:
|
||||
return
|
||||
timezones = []
|
||||
|
@ -280,6 +331,14 @@ class CalDAV(object):
|
|||
return vevent
|
||||
|
||||
def check_import(self, cr, uid, vals, context={}):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param vals: Get Values
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
ids = []
|
||||
model_obj = self.pool.get(context.get('model'))
|
||||
recur_pool = {}
|
||||
|
@ -311,6 +370,14 @@ class CalDAV(object):
|
|||
return ids
|
||||
|
||||
def export_cal(self, cr, uid, datas, vobj=None, context={}):
|
||||
""" Export Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param datas: Get Data's for caldav
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
try:
|
||||
self.__attribute__ = get_attribute_mapping(cr, uid, self._calname, context)
|
||||
ical = vobject.iCalendar()
|
||||
|
@ -320,6 +387,14 @@ class CalDAV(object):
|
|||
raise osv.except_osv(('Error !'), (str(e)))
|
||||
|
||||
def import_cal(self, cr, uid, content, data_id=None, context=None):
|
||||
""" Import Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param data_id: Get Data’s ID or False
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
ical_data = base64.decodestring(content)
|
||||
self.__attribute__ = get_attribute_mapping(cr, uid, self._calname, context)
|
||||
parsedCal = vobject.readOne(ical_data)
|
||||
|
@ -335,6 +410,7 @@ class CalDAV(object):
|
|||
self.ical_reset('value')
|
||||
return res
|
||||
|
||||
|
||||
class Calendar(CalDAV, osv.osv):
|
||||
_name = 'basic.calendar'
|
||||
_description = 'Calendar'
|
||||
|
@ -366,6 +442,14 @@ class Calendar(CalDAV, osv.osv):
|
|||
}
|
||||
|
||||
def export_cal(self, cr, uid, ids, vobj='vevent', context={}):
|
||||
""" Export Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of calendar’s IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
cal = self.browse(cr, uid, ids[0])
|
||||
ical = vobject.iCalendar()
|
||||
for line in cal.line_ids:
|
||||
|
@ -382,6 +466,14 @@ class Calendar(CalDAV, osv.osv):
|
|||
return ical.serialize()
|
||||
|
||||
def import_cal(self, cr, uid, content, data_id=None, context=None):
|
||||
""" Import Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param data_id: Get Data’s ID or False
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
vals = []
|
||||
|
@ -410,9 +502,13 @@ class Calendar(CalDAV, osv.osv):
|
|||
return {}
|
||||
Calendar()
|
||||
|
||||
|
||||
class basic_calendar_line(osv.osv):
|
||||
""" Calendar Lines """
|
||||
|
||||
_name = 'basic.calendar.lines'
|
||||
_description = 'Calendar Lines'
|
||||
|
||||
_columns = {
|
||||
'name': fields.selection([('vevent', 'Event'), ('vtodo', 'TODO'), \
|
||||
('valarm', 'Alarm'), \
|
||||
|
@ -430,6 +526,14 @@ class basic_calendar_line(osv.osv):
|
|||
}
|
||||
|
||||
def create(self, cr, uid, vals, context={}):
|
||||
""" create calendar's line
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param vals: Get the Values
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
cr.execute("Select count(id) from basic_calendar_lines \
|
||||
where name='%s' and calendar_id=%s" % (vals.get('name'), vals.get('calendar_id')))
|
||||
res = cr.fetchone()
|
||||
|
@ -441,6 +545,7 @@ line "%s" more than once' % (vals.get('name'))))
|
|||
|
||||
basic_calendar_line()
|
||||
|
||||
|
||||
class basic_calendar_attribute(osv.osv):
|
||||
_name = 'basic.calendar.attributes'
|
||||
_description = 'Calendar attributes'
|
||||
|
@ -454,7 +559,10 @@ class basic_calendar_attribute(osv.osv):
|
|||
|
||||
basic_calendar_attribute()
|
||||
|
||||
|
||||
class basic_calendar_fields(osv.osv):
|
||||
""" Calendar fields """
|
||||
|
||||
_name = 'basic.calendar.fields'
|
||||
_description = 'Calendar fields'
|
||||
|
||||
|
@ -476,6 +584,13 @@ class basic_calendar_fields(osv.osv):
|
|||
}
|
||||
|
||||
def check_line(self, cr, uid, vals, name, context=None):
|
||||
""" check calendar's line
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param vals: Get Values
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
f_obj = self.pool.get('ir.model.fields')
|
||||
field = f_obj.browse(cr, uid, vals['field_id'], context=context)
|
||||
relation = field.relation
|
||||
|
@ -489,6 +604,14 @@ class basic_calendar_fields(osv.osv):
|
|||
return True
|
||||
|
||||
def create(self, cr, uid, vals, context={}):
|
||||
""" Create Calendar's fields
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param vals: Get Values
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
cr.execute('select name from basic_calendar_attributes \
|
||||
where id=%s' % (vals.get('name')))
|
||||
name = cr.fetchone()
|
||||
|
@ -504,6 +627,14 @@ class basic_calendar_fields(osv.osv):
|
|||
return super(basic_calendar_fields, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
""" write Calendar's fields
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param vals: Get Values
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
if not vals:
|
||||
return
|
||||
for id in ids:
|
||||
|
@ -522,6 +653,7 @@ class basic_calendar_fields(osv.osv):
|
|||
|
||||
basic_calendar_fields()
|
||||
|
||||
|
||||
class Event(CalDAV, osv.osv_memory):
|
||||
_name = 'basic.calendar.event'
|
||||
_calname = 'vevent'
|
||||
|
@ -560,11 +692,21 @@ class Event(CalDAV, osv.osv_memory):
|
|||
'duration': None, # Use: O-1, Type: DURATION, Specifies a positive duration of time.
|
||||
'dtend': None, # Use: O-1, Type: DATE-TIME, Specifies the date and time that a calendar component ends.
|
||||
}
|
||||
|
||||
def export_cal(self, cr, uid, datas, vobj='vevent', context={}):
|
||||
""" Export calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param datas: Get datas
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
return super(Event, self).export_cal(cr, uid, datas, 'vevent', context=context)
|
||||
|
||||
Event()
|
||||
|
||||
|
||||
class ToDo(CalDAV, osv.osv_memory):
|
||||
_name = 'basic.calendar.todo'
|
||||
_calname = 'vtodo'
|
||||
|
@ -605,14 +747,24 @@ class ToDo(CalDAV, osv.osv_memory):
|
|||
}
|
||||
|
||||
def export_cal(self, cr, uid, datas, vobj='vevent', context={}):
|
||||
""" Export Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param datas: Get datas
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
return super(ToDo, self).export_cal(cr, uid, datas, 'vtodo', context=context)
|
||||
|
||||
ToDo()
|
||||
|
||||
|
||||
class Journal(CalDAV):
|
||||
__attribute__ = {
|
||||
}
|
||||
|
||||
|
||||
class FreeBusy(CalDAV):
|
||||
__attribute__ = {
|
||||
'contact': None, # Use: O-1, Type: Text, Represent contact information or alternately a reference to contact information associated with the calendar component.
|
||||
|
@ -645,6 +797,13 @@ class Timezone(CalDAV, osv.osv_memory):
|
|||
}
|
||||
|
||||
def get_name_offset(self, cr, uid, tzid, context={}):
|
||||
""" Get Name Offset value
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
mytz = pytz.timezone(tzid.title())
|
||||
mydt = datetime.now(tz=mytz)
|
||||
offset = mydt.utcoffset()
|
||||
|
@ -655,6 +814,14 @@ class Timezone(CalDAV, osv.osv_memory):
|
|||
return (mydt.tzname(), realoffset)
|
||||
|
||||
def export_cal(self, cr, uid, model, tzid, ical, context={}):
|
||||
""" Export Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param model: Get Model's name
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
ctx = context.copy()
|
||||
ctx.update({'model': model})
|
||||
cal_tz = ical.add('vtimezone')
|
||||
|
@ -668,6 +835,14 @@ class Timezone(CalDAV, osv.osv_memory):
|
|||
return ical
|
||||
|
||||
def import_cal(self, cr, uid, ical_data, context=None):
|
||||
""" Import Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ical_data: Get calendar's data
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
for child in ical_data.getChildren():
|
||||
if child.name.lower() == 'tzid':
|
||||
tzname = child.value
|
||||
|
@ -695,6 +870,15 @@ class Alarm(CalDAV, osv.osv_memory):
|
|||
}
|
||||
|
||||
def export_cal(self, cr, uid, model, alarm_id, vevent, context={}):
|
||||
""" Export Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param model: Get Model's name
|
||||
@param alarm_id: Get Alarm's Id
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
valarm = vevent.add('valarm')
|
||||
alarm_object = self.pool.get(model)
|
||||
alarm_data = alarm_object.read(cr, uid, alarm_id, [])
|
||||
|
@ -721,6 +905,14 @@ class Alarm(CalDAV, osv.osv_memory):
|
|||
return vevent
|
||||
|
||||
def import_cal(self, cr, uid, ical_data, context=None):
|
||||
""" Import Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ical_data: Get calendar's Data
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
ctx = context.copy()
|
||||
ctx.update({'model': context.get('model', None)})
|
||||
self.__attribute__ = get_attribute_mapping(cr, uid, self._calname, ctx)
|
||||
|
@ -755,6 +947,7 @@ class Alarm(CalDAV, osv.osv_memory):
|
|||
|
||||
Alarm()
|
||||
|
||||
|
||||
class Attendee(CalDAV, osv.osv_memory):
|
||||
_name = 'basic.calendar.attendee'
|
||||
_calname = 'attendee'
|
||||
|
@ -774,6 +967,14 @@ class Attendee(CalDAV, osv.osv_memory):
|
|||
}
|
||||
|
||||
def import_cal(self, cr, uid, ical_data, context=None):
|
||||
""" Import Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ical_data: Get calendar's Data
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
ctx = context.copy()
|
||||
ctx.update({'model': context.get('model', None)})
|
||||
self.__attribute__ = get_attribute_mapping(cr, uid, self._calname, ctx)
|
||||
|
@ -789,6 +990,15 @@ class Attendee(CalDAV, osv.osv_memory):
|
|||
return vals
|
||||
|
||||
def export_cal(self, cr, uid, model, attendee_ids, vevent, context={}):
|
||||
""" Export Calendar
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param model: Get model's name
|
||||
@param attendee_ids: Get Attendee's Id
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
attendee_object = self.pool.get(model)
|
||||
ctx = context.copy()
|
||||
ctx.update({'model': model})
|
||||
|
@ -814,5 +1024,4 @@ class Attendee(CalDAV, osv.osv_memory):
|
|||
|
||||
Attendee()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import heapq
|
||||
|
||||
|
@ -10,8 +31,8 @@ def memoize(maxsize):
|
|||
def wrapper(*args):
|
||||
key = repr(args)
|
||||
# performance crap
|
||||
_cache=cache
|
||||
_heap=heap
|
||||
_cache = cache
|
||||
_heap = heap
|
||||
_heappop = heapq.heappop
|
||||
_heappush = heapq.heappush
|
||||
_time = time.time
|
||||
|
@ -20,13 +41,13 @@ def memoize(maxsize):
|
|||
if not _cache.has_key(key):
|
||||
if _cursize == _maxsize:
|
||||
# pop oldest element
|
||||
(_,oldkey) = _heappop(_heap)
|
||||
(_, oldkey) = _heappop(_heap)
|
||||
_cache.pop(oldkey)
|
||||
else:
|
||||
_cursize += 1
|
||||
# insert this element
|
||||
_cache[key] = f(*args)
|
||||
_heappush(_heap,(_time(),key))
|
||||
_heappush(_heap, (_time(), key))
|
||||
wrapper.misses += 1
|
||||
else:
|
||||
wrapper.hits += 1
|
||||
|
@ -37,3 +58,5 @@ def memoize(maxsize):
|
|||
return wrapper
|
||||
return decorating_function
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -50,7 +50,7 @@ class tinydav_handler(dav_interface):
|
|||
"""
|
||||
PROPS={'DAV:': dav_interface.PROPS['DAV:'], }
|
||||
|
||||
M_NS={ "DAV:" : dav_interface.M_NS['DAV:'], }
|
||||
M_NS={ "DAV:": dav_interface.M_NS['DAV:'], }
|
||||
|
||||
def __init__(self, parent, verbose=False):
|
||||
self.db_name = False
|
||||
|
@ -65,7 +65,7 @@ class tinydav_handler(dav_interface):
|
|||
if not dbname:
|
||||
cr.close()
|
||||
return props
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if node:
|
||||
props.update(node.get_dav_props(cr))
|
||||
cr.close()
|
||||
|
@ -79,18 +79,18 @@ class tinydav_handler(dav_interface):
|
|||
pname -- name of the property
|
||||
"""
|
||||
if self.M_NS.has_key(ns):
|
||||
return dav_interface.get_prop(self,uri,ns,propname)
|
||||
return dav_interface.get_prop(self, uri, ns, propname)
|
||||
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
if uri[-1]=='/':uri = uri[:-1]
|
||||
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
|
||||
if not dbname:
|
||||
cr.close()
|
||||
raise DAV_NotFound
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
cr.close()
|
||||
raise DAV_NotFound
|
||||
res = node.get_dav_eprop(cr,ns,propname)
|
||||
res = node.get_dav_eprop(cr, ns, propname)
|
||||
cr.close()
|
||||
return res
|
||||
|
||||
|
@ -101,10 +101,10 @@ class tinydav_handler(dav_interface):
|
|||
return self.baseuri+ '/'.join(ajoin)
|
||||
|
||||
def uri2local(self, uri):
|
||||
uparts=urlparse.urlparse(uri)
|
||||
reluri=uparts[2]
|
||||
uparts = urlparse.urlparse(uri)
|
||||
reluri = uparts[2]
|
||||
if reluri and reluri[-1]=="/":
|
||||
reluri=reluri[:-1]
|
||||
reluri = reluri[:-1]
|
||||
return reluri
|
||||
|
||||
#
|
||||
|
@ -135,29 +135,29 @@ class tinydav_handler(dav_interface):
|
|||
return None
|
||||
return pool.get('basic.calendar').get_calendar_object(cr, uid, uri)
|
||||
|
||||
def get_data(self,uri):
|
||||
def get_data(self, uri):
|
||||
self.parent.log_message('GET: %s' % uri)
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
|
||||
try:
|
||||
if not dbname:
|
||||
raise DAV_Error, 409
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
raise DAV_NotFound(uri2)
|
||||
try:
|
||||
datas = node.get_data(cr, uid)
|
||||
except TypeError,e:
|
||||
except TypeError, e:
|
||||
import traceback
|
||||
self.parent.log_error("GET typeError: %s", str(e))
|
||||
self.parent.log_message("Exc: %s",traceback.format_exc())
|
||||
self.parent.log_message("Exc: %s", traceback.format_exc())
|
||||
raise DAV_Forbidden
|
||||
except IndexError,e :
|
||||
except IndexError, e :
|
||||
self.parent.log_error("GET IndexError: %s", str(e))
|
||||
raise DAV_NotFound(uri2)
|
||||
except Exception,e:
|
||||
except Exception, e:
|
||||
import traceback
|
||||
self.parent.log_error("GET exception: %s",str(e))
|
||||
self.parent.log_error("GET exception: %s", str(e))
|
||||
self.parent.log_message("Exc: %s", traceback.format_exc())
|
||||
raise DAV_Error, 409
|
||||
return datas
|
||||
|
@ -165,7 +165,7 @@ class tinydav_handler(dav_interface):
|
|||
cr.close()
|
||||
|
||||
@memoize(CACHE_SIZE)
|
||||
def _get_dav_resourcetype(self,uri):
|
||||
def _get_dav_resourcetype(self, uri):
|
||||
""" return type of object """
|
||||
self.parent.log_message('get RT: %s' % uri)
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
|
@ -173,21 +173,21 @@ class tinydav_handler(dav_interface):
|
|||
try:
|
||||
if not dbname:
|
||||
return COLLECTION
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
raise DAV_NotFound(uri2)
|
||||
return OBJECT
|
||||
finally:
|
||||
cr.close()
|
||||
|
||||
def _get_dav_displayname(self,uri):
|
||||
def _get_dav_displayname(self, uri):
|
||||
self.parent.log_message('get DN: %s' % uri)
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
|
||||
if not dbname:
|
||||
cr.close()
|
||||
return COLLECTION
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
cr.close()
|
||||
raise DAV_NotFound(uri2)
|
||||
|
@ -195,7 +195,7 @@ class tinydav_handler(dav_interface):
|
|||
return node.displayname
|
||||
|
||||
@memoize(CACHE_SIZE)
|
||||
def _get_dav_getcontentlength(self,uri):
|
||||
def _get_dav_getcontentlength(self, uri):
|
||||
""" return the content length of an object """
|
||||
self.parent.log_message('get length: %s' % uri)
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
|
@ -213,7 +213,7 @@ class tinydav_handler(dav_interface):
|
|||
return str(result)
|
||||
|
||||
@memoize(CACHE_SIZE)
|
||||
def _get_dav_getetag(self,uri):
|
||||
def _get_dav_getetag(self, uri):
|
||||
""" return the ETag of an object """
|
||||
self.parent.log_message('get etag: %s' % uri)
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
|
@ -231,7 +231,7 @@ class tinydav_handler(dav_interface):
|
|||
return str(result)
|
||||
|
||||
@memoize(CACHE_SIZE)
|
||||
def get_lastmodified(self,uri):
|
||||
def get_lastmodified(self, uri):
|
||||
""" return the last modified date of the object """
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
today = time.time()
|
||||
|
@ -239,18 +239,18 @@ class tinydav_handler(dav_interface):
|
|||
try:
|
||||
if not dbname:
|
||||
return today
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
raise DAV_NotFound(uri2)
|
||||
if node.write_date:
|
||||
return time.mktime(time.strptime(node.write_date,'%Y-%m-%d %H:%M:%S'))
|
||||
return time.mktime(time.strptime(node.write_date, '%Y-%m-%d %H:%M:%S'))
|
||||
else:
|
||||
return today
|
||||
finally:
|
||||
cr.close()
|
||||
|
||||
@memoize(CACHE_SIZE)
|
||||
def get_creationdate(self,uri):
|
||||
def get_creationdate(self, uri):
|
||||
""" return the last modified date of the object """
|
||||
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
|
@ -258,11 +258,11 @@ class tinydav_handler(dav_interface):
|
|||
try:
|
||||
if not dbname:
|
||||
raise DAV_Error, 409
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
raise DAV_NotFound(uri2)
|
||||
if node.create_date:
|
||||
result = time.strptime(node.create_date,'%Y-%m-%d %H:%M:%S')
|
||||
result = time.strptime(node.create_date, '%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
result = time.gmtime()
|
||||
return result
|
||||
|
@ -270,14 +270,14 @@ class tinydav_handler(dav_interface):
|
|||
cr.close()
|
||||
|
||||
@memoize(CACHE_SIZE)
|
||||
def _get_dav_getcontenttype(self,uri):
|
||||
def _get_dav_getcontenttype(self, uri):
|
||||
self.parent.log_message('get contenttype: %s' % uri)
|
||||
if uri[-1]=='/':uri=uri[:-1]
|
||||
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
|
||||
try:
|
||||
if not dbname:
|
||||
return 'httpd/unix-directory'
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if not node:
|
||||
raise DAV_NotFound(uri2)
|
||||
result = node.mimetype
|
||||
|
@ -290,13 +290,13 @@ class tinydav_handler(dav_interface):
|
|||
|
||||
def put(self, uri, data, content_type=None):
|
||||
""" put the object into the filesystem """
|
||||
self.parent.log_message('Putting %s (%d), %s'%( misc.ustr(uri), len(data), content_type))
|
||||
self.parent.log_message('Putting %s (%d), %s'%(misc.ustr(uri), len(data), content_type))
|
||||
parent='/'.join(uri.split('/')[:-1])
|
||||
cr, uid, pool,dbname, uri2 = self.get_cr(uri)
|
||||
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
|
||||
if not dbname:
|
||||
raise DAV_Forbidden
|
||||
try:
|
||||
node = self.uri2object(cr,uid,pool, uri2[:])
|
||||
node = self.uri2object(cr, uid, pool, uri2[:])
|
||||
except:
|
||||
node = False
|
||||
|
||||
|
@ -305,31 +305,31 @@ class tinydav_handler(dav_interface):
|
|||
else:
|
||||
try:
|
||||
node.set_data(cr, uid, data)
|
||||
except Exception,e:
|
||||
except Exception, e:
|
||||
import traceback
|
||||
self.parent.log_error("Cannot save :%s", str(e))
|
||||
self.parent.log_message("Exc: %s",traceback.format_exc())
|
||||
self.parent.log_message("Exc: %s", traceback.format_exc())
|
||||
raise DAV_Forbidden
|
||||
|
||||
cr.commit()
|
||||
cr.close()
|
||||
return 201
|
||||
|
||||
|
||||
|
||||
|
||||
def exists(self,uri):
|
||||
def exists(self, uri):
|
||||
""" test if a resource exists """
|
||||
result = False
|
||||
cr, uid, pool,dbname, uri2 = self.get_cr(uri)
|
||||
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
|
||||
if not dbname:
|
||||
cr.close()
|
||||
return True
|
||||
try:
|
||||
node = self.uri2object(cr,uid,pool, uri2)
|
||||
node = self.uri2object(cr, uid, pool, uri2)
|
||||
if node:
|
||||
result = True
|
||||
except:
|
||||
pass
|
||||
cr.close()
|
||||
return result
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -26,6 +26,7 @@ import tools
|
|||
import time
|
||||
import base64
|
||||
|
||||
|
||||
class node_calendar(object):
|
||||
def __init__(self, path, context, calendar):
|
||||
self.path = path
|
||||
|
@ -49,22 +50,23 @@ class node_calendar(object):
|
|||
calendar_obj = pooler.get_pool(cr.dbname).get('basic.calendar')
|
||||
return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id)
|
||||
|
||||
def get_etag(self,cr):
|
||||
def get_etag(self, cr):
|
||||
""" Get a tag, unique per object + modification.
|
||||
|
||||
see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """
|
||||
return self._get_ttag(cr) + ':' + self._get_wtag(cr)
|
||||
|
||||
def _get_wtag(self,cr):
|
||||
def _get_wtag(self, cr):
|
||||
""" Return the modification time as a unique, compact string """
|
||||
if self.write_date:
|
||||
wtime = time.mktime(time.strptime(self.write_date,'%Y-%m-%d %H:%M:%S'))
|
||||
wtime = time.mktime(time.strptime(self.write_date, '%Y-%m-%d %H:%M:%S'))
|
||||
else: wtime = time.time()
|
||||
return str(wtime)
|
||||
|
||||
def _get_ttag(self,cr):
|
||||
def _get_ttag(self, cr):
|
||||
return 'calendar-%d' % self.calendar_id
|
||||
|
||||
|
||||
class Calendar(osv.osv):
|
||||
_inherit = 'basic.calendar'
|
||||
|
||||
|
@ -81,3 +83,5 @@ class Calendar(osv.osv):
|
|||
calendar = self.browse(cr, uid, calendar_id)
|
||||
return node_calendar(uri, context, calendar)
|
||||
Calendar()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4
|
|
@ -1,9 +1,7 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright P. Christeas <p_christ@hol.gr> 2008,2009
|
||||
#
|
||||
#
|
||||
# WARNING: This program as such is intended to be used by professional
|
||||
# programmers who take the whole responsability of assessing all potential
|
||||
# consequences resulting from its eventual inadequacies and bugs
|
||||
|
@ -33,14 +31,15 @@ from tools.config import config
|
|||
from DAV.WebDAVServer import DAVRequestHandler
|
||||
from service.websrv_lib import HTTPDir,FixSendError
|
||||
|
||||
class DAVHandler(FixSendError,DAVRequestHandler):
|
||||
|
||||
class DAVHandler(FixSendError, DAVRequestHandler):
|
||||
verbose = False
|
||||
|
||||
def get_userinfo(self,user,pw):
|
||||
def get_userinfo(self, user, pw):
|
||||
return False
|
||||
|
||||
def _log(self, message):
|
||||
netsvc.Logger().notifyChannel("webdav",netsvc.LOG_DEBUG,message)
|
||||
netsvc.Logger().notifyChannel("webdav", netsvc.LOG_DEBUG, message)
|
||||
|
||||
def handle(self):
|
||||
pass
|
||||
|
@ -50,30 +49,30 @@ class DAVHandler(FixSendError,DAVRequestHandler):
|
|||
|
||||
def setup(self):
|
||||
davpath = '/calendar/'
|
||||
self.baseuri = "http://%s:%d%s"% (self.server.server_name,self.server.server_port,davpath)
|
||||
self.baseuri = "http://%s:%d%s"% (self.server.server_name, self.server.server_port, davpath)
|
||||
self.IFACE_CLASS = tinydav_handler(self)
|
||||
pass
|
||||
|
||||
def log_message(self, format, *args):
|
||||
netsvc.Logger().notifyChannel('webdav',netsvc.LOG_DEBUG_RPC,format % args)
|
||||
netsvc.Logger().notifyChannel('webdav', netsvc.LOG_DEBUG_RPC, format % args)
|
||||
|
||||
def log_error(self, format, *args):
|
||||
netsvc.Logger().notifyChannel('webdav',netsvc.LOG_WARNING,format % args)
|
||||
netsvc.Logger().notifyChannel('webdav', netsvc.LOG_WARNING, format % args)
|
||||
|
||||
|
||||
try:
|
||||
from service.http_server import reg_http_service,OpenERPAuthProvider
|
||||
from service.http_server import reg_http_service, OpenERPAuthProvider
|
||||
davpath = '/calendar/'
|
||||
handler = DAVHandler
|
||||
handler.verbose = config.get_misc('webdav','verbose',True)
|
||||
handler.debug = config.get_misc('webdav','debug',True)
|
||||
reg_http_service(HTTPDir(davpath,DAVHandler,OpenERPAuthProvider()))
|
||||
netsvc.Logger().notifyChannel('webdav',netsvc.LOG_INFO,"WebDAV service registered at path: %s/ "% davpath)
|
||||
handler.verbose = config.get_misc('webdav', 'verbose', True)
|
||||
handler.debug = config.get_misc('webdav', 'debug', True)
|
||||
reg_http_service(HTTPDir(davpath, DAVHandler, OpenERPAuthProvider()))
|
||||
netsvc.Logger().notifyChannel('webdav', netsvc.LOG_INFO, "WebDAV service registered at path: %s/ "% davpath)
|
||||
except Exception, e:
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('webdav', netsvc.LOG_ERROR, 'Cannot launch webdav: %s' % e)
|
||||
|
||||
#eof
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -53,14 +53,15 @@ class calendar_event_export(osv.osv_memory):
|
|||
|
||||
_name = "calendar.event.export"
|
||||
_description = "Event Export"
|
||||
|
||||
_columns = {
|
||||
'file_path':fields.binary('Save ICS file', filters='*.ics', required=True),
|
||||
'name':fields.char('File name', size=34, required=True, help='Save in .ics format')
|
||||
}
|
||||
|
||||
_defaults={
|
||||
'name':_process_export_ics_name,
|
||||
'file_path':_process_export_ics
|
||||
_defaults = {
|
||||
'name': _process_export_ics_name,
|
||||
'file_path': _process_export_ics
|
||||
}
|
||||
|
||||
calendar_event_export()
|
||||
|
|
|
@ -42,6 +42,7 @@ class calendar_event_import(osv.osv_memory):
|
|||
@param ids: List of calendar event import’s IDs
|
||||
@return: dictionary of calendar evet import window with Import successful msg.
|
||||
"""
|
||||
|
||||
for data in self.read(cr, uid, ids):
|
||||
model = data.get('model', 'basic.calendar')
|
||||
model_obj = self.pool.get(model)
|
||||
|
@ -66,11 +67,13 @@ class calendar_event_import(osv.osv_memory):
|
|||
|
||||
_name = "calendar.event.import"
|
||||
_description = "Event Import"
|
||||
|
||||
_columns = {
|
||||
'file_path': fields.binary('Select ICS file', filters='*.ics', required=True),
|
||||
'msg': fields.text('', readonly=True),
|
||||
}
|
||||
_defaults={
|
||||
|
||||
_defaults = {
|
||||
'msg':lambda *a:'Import Sucessful'
|
||||
}
|
||||
|
||||
|
|
|
@ -76,11 +76,13 @@ class calendar_event_subscribe(osv.osv_memory):
|
|||
|
||||
_name = "calendar.event.subscribe"
|
||||
_description = "Event subscribe"
|
||||
|
||||
_columns = {
|
||||
'url_path': fields.char('Provide path for remote calendar', size=124, required=True),
|
||||
'msg': fields.text('', readonly=True),
|
||||
|
||||
}
|
||||
_defaults={
|
||||
_defaults = {
|
||||
'msg':lambda *a:'Import Sucessful.'
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,14 @@ class crm_meeting(osv.osv):
|
|||
_inherit = 'crm.meeting'
|
||||
|
||||
def export_cal(self, cr, uid, ids, context={}):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of CRM Meeting’s IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
ids = map(lambda x: base_calendar.base_calendar_id2real_id(x), ids)
|
||||
event_data = self.read(cr, uid, ids)
|
||||
event_obj = self.pool.get('basic.calendar.event')
|
||||
|
@ -35,6 +43,15 @@ class crm_meeting(osv.osv):
|
|||
return ical.serialize()
|
||||
|
||||
def import_cal(self, cr, uid, data, data_id=None, context={}):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param data: Get Data of CRM Meetings
|
||||
@param data_id: calendar's Id
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
event_obj = self.pool.get('basic.calendar.event')
|
||||
vals = event_obj.import_cal(cr, uid, data, context=context)
|
||||
return self.check_import(cr, uid, vals, context=context)
|
||||
|
|
Loading…
Reference in New Issue