You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(35) |
Apr
(15) |
May
(46) |
Jun
(17) |
Jul
(11) |
Aug
(7) |
Sep
|
Oct
|
Nov
(6) |
Dec
|
---|
From: <luc...@us...> - 2003-05-10 00:25:31
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv26864 Modified Files: zaurusutils.py Log Message: Support for writing files without temp file (plus minor fixes). Index: zaurusutils.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/zaurusutils.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** zaurusutils.py 7 May 2003 20:36:49 -0000 1.4 --- zaurusutils.py 10 May 2003 00:25:28 -0000 1.5 *************** *** 24,27 **** --- 24,28 ---- import ftplib,tempfile import string,re + import time # TODO: Move these strings elsewhere *************** *** 53,57 **** ftpconn.retrbinary("RETR " + path, readBlock) except Exception, e: ! ftpconn.quit() raise ZaurusUtilError("readFile(): error retrieving file '" + path + "' from the Zaurus: " + str(e) ) try: --- 54,61 ---- ftpconn.retrbinary("RETR " + path, readBlock) except Exception, e: ! try: ! ftpconn.quit() ! except: ! ftpconn.close() raise ZaurusUtilError("readFile(): error retrieving file '" + path + "' from the Zaurus: " + str(e) ) try: *************** *** 63,66 **** --- 67,121 ---- + def writeFile(zaurus, path, contents): + """ + Writes a file to the Zaurus (via FTP). The "zaurus" parameter contains + a Zaurus device object (used for retrieving IP address etc.). + """ + + #tempfilename = tempfile.mktemp() + #try: + # file = open( tempfilename, "wb" ) + #except Exception, e: + # raise ZaurusCalendarException("writeFile(): Could not write XML to a temporary file: " + str(e) ) + #file.write( contents ) + #file.close() + #try: + # file = open( tempfilename, "rb" ) + #except Exception, e: + # raise DatebookError( "writeFile(): error opening temp file: " + str(e) ) + + ftpconn = ftplib.FTP() + #ftpconn.set_debuglevel(10) + try: + ftpconn.connect( zaurus.ip_address, zaurus.ftp_port ) + ftpconn.login( zaurus.user, zaurus.password ) + except Exception, e: + raise ZaurusUtilError("writeFile(): error connecting to the Zaurus: " + str(e)) + try: + index = [0] + contentsLen = len(contents) + class Writer: + def read(self, size): + #print "writing (" + str(size) + ")" + if index[0] >= contentsLen: + return "" # EOF + retVal = contents[index[0]:index[0]+size] + index[0] += size + #print "writing " + str(len(retVal)) + " bytes" + return retVal + ftpconn.storbinary("STOR " + path, Writer()) + except Exception, e: + try: + ftpconn.quit() + except: + ftpconn.close() + raise ZaurusUtilError("writeFile(): error writing file '" + path + "' to the Zaurus: " + str(e) ) + try: + ftpconn.quit() + except: + ftpconn.close() + #file.close() + + # XXX: change these if more escaping/unescaping needs to be done # a dictionary mapping escaped -> unescaped *************** *** 85,89 **** def zaurusEscape( text ): ! """Escapes the text for zaurus-style XML""" return escaper.sub(lambda mo: unescapedDict[mo.string[mo.start():mo.end()]], text) --- 140,146 ---- def zaurusEscape( text ): ! """ ! Escapes the text for zaurus-style XML. ! """ return escaper.sub(lambda mo: unescapedDict[mo.string[mo.start():mo.end()]], text) *************** *** 91,100 **** def zaurusUnescape( text ): """ ! Unescapes the supplied text from the Zaurus ! Assumes that it is properly escaped in the first place """ return unescaper.sub(lambda mo: escapedDict[mo.string[mo.start():mo.end()]], text) def getCategories(zaurus): """ --- 148,158 ---- def zaurusUnescape( text ): """ ! Unescapes the supplied text from the Zaurus. ! Assumes that it is properly escaped in the first place. """ return unescaper.sub(lambda mo: escapedDict[mo.string[mo.start():mo.end()]], text) + def getCategories(zaurus): """ *************** *** 183,186 **** --- 241,245 ---- if(pair): key,value = string.split(pair,"=\"") + key = key.strip() entryDict[key] = zaurusUnescape(value) dictList.append(entryDict) |
From: <luc...@us...> - 2003-05-10 00:23:59
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv26375 Added Files: zauruscontacts.py Log Message: Add contacts support. --- NEW FILE: zauruscontacts.py --- #!/usr/bin/env python # # zXSync application for dealing with contacts on the Zaurus. # # Copyright (C) 2003 Geoff Beier <ge...@mo...> # Copyright (C) 2003 Andreas Junghans <aj...@lu...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # $Id: zauruscontacts.py,v 1.1 2003/05/10 00:23:56 lucidcake Exp $ from util import qcop, zaurusutils import time from zxsync.pluginbase import DeviceApplication, PluginError from zxsync import syncbase import zxsync.vcard ADDRESSBOOK_DIR = "Applications/addressbook" ADDRESSBOOK_FILE = "addressbook.xml" RID_START = 10 BIRTHDAY = "Birthday" BUSINESS_CITY = "BusinessCity" BUSINESS_COUNTRY = "BusinessCountry" BUSINESS_FAX = "BusinessFax" BUSINESS_MOBILE = "BusinessMobile" BUSINESS_PAGER = "BusinessPager" BUSINESS_PHONE = "BusinessPhone" BUSINESS_STATE = "BusinessState" BUSINESS_STREET = "BusinessStreet" BUSINESS_WEB_PAGE = "BusinessWebPage" BUSINESS_ZIP = "BusinessZip" CATEGORIES = "Categories" COMPANY = "Company" DEFAULT_EMAIL = "DefaultEmail" EMAILS = "Emails" FILE_AS = "FileAs" FIRST_NAME = "FirstName" HOME_CITY = "HomeCity" HOME_COUNTRY = "HomeCountry" HOME_FAX = "HomeFax" HOME_MOBILE = "HomeMobile" HOME_PHONE = "HomePhone" HOME_STATE = "HomeState" HOME_STREET = "HomeStreet" HOME_WEB_PAGE = "HomeWebPage" HOME_ZIP = "HomeZip" JOB_TITLE = "JobTitle" LAST_NAME = "LastName" MIDDLE_NAME = "MiddleName" NICKNAME = "Nickname" NOTES = "Notes" SUFFIX = "Suffix" TITLE = "Title" UID = "Uid" X_ZAURUS_BIRTHDAY = "X-ZAURUS-BIRTHDAY" X_ZAURUS_CATEGORIES = "X-ZAURUS-CATEGORIES" X_ZAURUS_UNKNOWN = "X-ZAURUS-UNKNOWN-" DATE_FORMATS = ("%m/%d/%Y", "%d/%m/%Y", "%d.%m.%Y", "%m.%d.%Y", "%Y-%m-%d", "%m/%d/%y", "%d/%m/%y", "%d.%m.%y", "%m.%d.%y") def getValue(dict, key): """ Returns a value from a dictionary or None if the given key is not found in there. This will also remove the value from the dictionary. The purpose of this is to remove all fields that are processed and leave only the ones that are not recognized in the end. """ try: retVal = dict[key] del dict[key] except KeyError: return None return zaurusutils.zaurusUnescape(retVal) def addField(xmlString, fieldName, value): """ Adds a field to an XML string (as attribute value). If the value is None or "", nothing is added. """ if value == None or value == "": return xmlString return xmlString + fieldName + '="' + zaurusutils.zaurusEscape(value) + '" ' class ZaurusContactsError(PluginError): """ Exception class for contacts. """ pass class ZaurusContacts(DeviceApplication): """ An application class used to read and write contact information from and to the Zaurus. """ def __init__(self, zaurusDevice): """ Initializes the application. """ # Retain a reference to the Zaurus device object so we can get our # settings. self.zaurus = zaurusDevice def getId(self): """ Returns the id of this application. """ return syncbase.CONTACTS_APP_ID; def getDataFormat(self): """ Returns the data format used by this application. """ return syncbase.VCARD_DATA_FORMAT; def beginSync(self): """ Starts the sync operation. """ # display start sync message on the Zaurus startSync = qcop.QCOPFunction("QPE/System","startSync") startSync.addarg("QString","Contacts") # this should come from the core... perhaps the API needs to change here self.zaurus.qcopConn.send(startSync) # instruct the z to write all entries to "disk" flush = qcop.QCOPFunction("QPE/Application/datebook","flush") self.zaurus.qcopConn.send(flush) return syncbase.WRITE_ALL def endSync(self): """ Finish the sync operation. """ # tell calendar to reload any changes reloadcmd = qcop.QCOPFunction("QPE/Application/datebook","reload") self.zaurus.qcopConn.send(reloadcmd) # kill the sync message stopSync = qcop.QCOPFunction("QPE/System","stopSync") self.zaurus.qcopConn.send(stopSync) def readAllEntries(self): """ Reads all entries of this application. """ retVal = [] rawContacts = zaurusutils.readFile(self.zaurus, self.zaurus.homedir + "/" + ADDRESSBOOK_DIR + "/" + ADDRESSBOOK_FILE) allContacts = zaurusutils.xml2dictlist(rawContacts.decode("UTF-8"), "Contact") for contact in allContacts: personVCard = zxsync.vcard.VCard(getValue(contact, UID)); # N field personVCard.setName( getValue(contact, LAST_NAME), getValue(contact, FIRST_NAME), getValue(contact, MIDDLE_NAME), getValue(contact, TITLE), getValue(contact, SUFFIX) ) # FN field personVCard.setFormattedName(getValue(contact, FILE_AS)) # NICKNAME field personVCard.setNickname(getValue(contact, NICKNAME)) # BDAY field # This is a problem since the Zaurus simply stores this as # text... # For now, just try a number of different formats. This may # produce wrong results, but that's better than nothing. birthdayValue = getValue(contact, BIRTHDAY) personVCard.replaceOrRemoveChild(X_ZAURUS_BIRTHDAY, "", zxsync.vcard.convertToInternalValue(birthdayValue)) # preserve the original string value birthdayTuple = None for format in DATE_FORMATS: try: birthdayTuple = time.strptime(birthdayValue, format) break; except: pass if birthdayTuple != None: personVCard.setBirthday(time.mktime(birthdayTuple)) birthdaySeconds = time.mktime(birthdayTuple) # ADR fields personVCard.addAddress(None, None, getValue(contact, BUSINESS_STREET), getValue(contact, BUSINESS_CITY), getValue(contact, BUSINESS_STATE), getValue(contact, BUSINESS_ZIP), getValue(contact, BUSINESS_COUNTRY), None, [zxsync.vcard.WORK]) personVCard.addAddress(None, None, getValue(contact, HOME_STREET), getValue(contact, HOME_CITY), getValue(contact, HOME_STATE), getValue(contact, HOME_ZIP), getValue(contact, HOME_COUNTRY), None, [zxsync.vcard.HOME]) # TEL fields personVCard.addPhoneNumber(getValue(contact, BUSINESS_PHONE), [zxsync.vcard.WORK]) personVCard.addPhoneNumber(getValue(contact, BUSINESS_FAX), [zxsync.vcard.WORK, zxsync.vcard.FAX]) personVCard.addPhoneNumber(getValue(contact, BUSINESS_MOBILE), [zxsync.vcard.WORK, zxsync.vcard.CELL]) personVCard.addPhoneNumber(getValue(contact, BUSINESS_PAGER), [zxsync.vcard.WORK, zxsync.vcard.PAGER]) personVCard.addPhoneNumber(getValue(contact, HOME_PHONE), [zxsync.vcard.HOME]) personVCard.addPhoneNumber(getValue(contact, HOME_FAX), [zxsync.vcard.HOME, zxsync.vcard.FAX]) personVCard.addPhoneNumber(getValue(contact, HOME_MOBILE), [zxsync.vcard.HOME, zxsync.vcard.CELL]) personVCard.normalize() retVal.append(personVCard) # EMAIL fields emails = getValue(contact, EMAILS) if emails != None: emails = emails.split(" ") defaultEmail = getValue(contact, DEFAULT_EMAIL) for email in emails: if email == defaultEmail: emailTypes = [zxsync.vcard.INTERNET, zxsync.vcard.PREF] else: emailTypes = [zxsync.vcard.INTERNET] personVCard.addEmailAddress(email, emailTypes) # NOTE fields personVCard.addNote(getValue(contact, NOTES)) # ORG fields personVCard.addOrganization(getValue(contact, COMPANY)) # TITLE fields personVCard.addTitle(getValue(contact, JOB_TITLE)) # URL fields homeURL = getValue(contact, HOME_WEB_PAGE) workURL = getValue(contact, BUSINESS_WEB_PAGE) personVCard.addURL(homeURL) personVCard.addURL(workURL) personVCard.addHomeURL(homeURL) personVCard.addWorkURL(workURL) # unrecognized fields try: del contact["rid"] except: pass try: del contact["rinfo"] except: pass for key in contact: personVCard.replaceOrRemoveChild(X_ZAURUS_UNKNOWN + key, "", zxsync.vcard.convertToInternalValue(contact[key])) #print allContacts return retVal def writeAllEntries(self, entries): """ Writes all entries to the device. """ currentRid = RID_START entriesXML = "<Contacts>\n" for entry in entries: currentRid = currentRid + 1 #if currentRid >= 14: # currentRid -= 1 # break entryXML = '<Contact rid="' + str(currentRid) + '" rinfo="1" ' # UID field entryXML = addField(entryXML, UID, entry.getUID().getValue()) # N field nameField = entry.getName() if nameField != None: nameValue = nameField.getValue() entryXML = addField(entryXML, LAST_NAME, nameValue[0][0]) entryXML = addField(entryXML, FIRST_NAME, nameValue[1][0]) entryXML = addField(entryXML, MIDDLE_NAME, nameValue[2][0]) entryXML = addField(entryXML, TITLE, nameValue[3][0]) entryXML = addField(entryXML, SUFFIX, nameValue[4][0]) # FN field formattedNameField = entry.getFormattedName() if formattedNameField != None: entryXML = addField(entryXML, FILE_AS, formattedNameField.getValue()) # NICKNAME field nicknameField = entry.getNickname() if nicknameField != None: entryXML = addField(entryXML, NICKNAME, nicknameField.getValue()[0]) # BDAY field birthdayField = entry.getChildWithId(X_ZAURUS_BIRTHDAY) if birthdayField != None: entryXML = addField(entryXML, BIRTHDAY, birthdayField.getValue()) else: birthdayField = entry.getBirthday() if birthdayField != None: birthdayValue = birthdayField.getValue() birthdayTuple = time.strptime(birthdayValue, "%Y-%m-%dT%H:%M:%SZ") birthdaySeconds = time.mktime(birthdayTuple) - time.timezone birthdayTuple = time.localtime(birthdaySeconds) birthdayValue = time.strftime(DATE_FORMATS[0], birthdayTuple) entryXML = addField(entryXML, BIRTHDAY, birthdayValue) # ADR fields addressFields = entry.getAddresses() for addressField in addressFields: addressValue = addressField.getValue() addressTypes = addressField.getTypes() if zxsync.vcard.WORK in addressTypes: entryXML = addField(entryXML, BUSINESS_STREET, addressValue[2][0]) entryXML = addField(entryXML, BUSINESS_CITY, addressValue[3][0]) entryXML = addField(entryXML, BUSINESS_STATE, addressValue[4][0]) entryXML = addField(entryXML, BUSINESS_ZIP, addressValue[5][0]) entryXML = addField(entryXML, BUSINESS_COUNTRY, addressValue[6][0]) if zxsync.vcard.HOME in addressTypes: entryXML = addField(entryXML, HOME_STREET, addressValue[2][0]) entryXML = addField(entryXML, HOME_CITY, addressValue[3][0]) entryXML = addField(entryXML, HOME_STATE, addressValue[4][0]) entryXML = addField(entryXML, HOME_ZIP, addressValue[5][0]) entryXML = addField(entryXML, HOME_COUNTRY, addressValue[6][0]) # TEL fields phoneFields = entry.getPhoneNumbers() for phoneField in phoneFields: phoneValue = phoneField.getValue() phoneTypes = phoneField.getTypes() if zxsync.vcard.HOME in phoneTypes: phoneAdded = 0 if zxsync.vcard.FAX in phoneTypes: entryXML = addField(entryXML, HOME_FAX, phoneValue) phoneAdded = 1 if zxsync.vcard.CELL in phoneTypes: entryXML = addField(entryXML, HOME_MOBILE, phoneValue) phoneAdded = 1 if zxsync.vcard.VOICE in phoneTypes or not phoneAdded: entryXML = addField(entryXML, HOME_PHONE, phoneValue) if zxsync.vcard.WORK in phoneTypes: phoneAdded = 0 if zxsync.vcard.FAX in phoneTypes: entryXML = addField(entryXML, BUSINESS_FAX, phoneValue) phoneAdded = 1 if zxsync.vcard.CELL in phoneTypes: entryXML = addField(entryXML, BUSINESS_MOBILE, phoneValue) phoneAdded = 1 if zxsync.vcard.PAGER in phoneTypes: entryXML = addField(entryXML, BUSINESS_PAGER, phoneValue) phoneAdded = 1 if zxsync.vcard.VOICE in phoneTypes or not phoneAdded: entryXML = addField(entryXML, BUSINESS_PHONE, phoneValue) # EMAIL fields emailFields = entry.getEmailAddresses() emails = "" defaultAdded = 0 for emailField in emailFields: if emails != "": emails += " " emailValue = emailField.getValue() emailTypes = emailField.getTypes() emails += emailValue if zxsync.vcard.PREF in emailTypes and not defaultAdded: entryXML = addField(entryXML, DEFAULT_EMAIL, emailValue) defaultAdded = 1 entryXML = addField(entryXML, EMAILS, emails) # NOTE fields noteFields = entry.getNotes() if len(noteFields) > 0: entryXML = addField(entryXML, NOTES, noteFields[0].getValue()) # ORG fields orgFields = entry.getOrganizations() if len(orgFields) > 0: entryXML = addField(entryXML, COMPANY, orgFields[0].getValue()[0]) # TITLE fields titleFields = entry.getTitles() if len(titleFields) > 0: entryXML = addField(entryXML, JOB_TITLE, titleFields[0].getValue()) # URL fields homeURL = None workURL = None homeURLFields = entry.getHomeURLs() if len(homeURLFields) > 0: homeURL = homeURLFields[0].getValue() entryXML = addField(entryXML, HOME_WEB_PAGE, homeURL) workURLFields = entry.getWorkURLs() if len(workURLFields) > 0: workURL = workURLFields[0].getValue() entryXML = addField(entryXML, BUSINESS_WEB_PAGE, workURL) if homeURL == None: urlFields = entry.getURLs() for urlField in urlFields: url = urlField.getValue() if url != workURL: entryXML = addField(entryXML, HOME_WEB_PAGE, url) break # unrecognized fields allFields = entry.getChildren() for field in allFields: fieldId = field.getId() if fieldId != None: if fieldId.find(X_ZAURUS_UNKNOWN) == 0: entryXML = addField(entryXML, fieldId[len(X_ZAURUS_UNKNOWN):], field.getValue()) entriesXML += entryXML entriesXML += "/>\n" entriesXML += "</Contacts>\n" zaurusXML = '<?xml version="1.0" encoding="UTF-8"?>' zaurusXML += '<!DOCTYPE Addressbook ><AddressBook>\n' # This typo comes from the Zaurus! zaurusXML += '<RIDMax>\n' + str(currentRid) + '\n</RIDMax>\n' zaurusXML += '<Groups>\n</Groups>\n' zaurusXML += entriesXML zaurusXML += '</AddressBook>\n' zaurusutils.writeFile(self.zaurus, self.zaurus.homedir + "/" + ADDRESSBOOK_DIR + "/" + ADDRESSBOOK_FILE, zaurusXML.encode("UTF-8")) |
From: <luc...@us...> - 2003-05-10 00:22:07
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv25868 Modified Files: contacts.py Log Message: Various fixes and improvements (mostly making the code simpler). Index: contacts.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/contacts.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** contacts.py 24 Apr 2003 21:58:45 -0000 1.1 --- contacts.py 10 May 2003 00:22:05 -0000 1.2 *************** *** 25,28 **** --- 25,29 ---- import zxsync.vcard import zxsync.syncbase + import time X_PREF = "X-PREF" *************** *** 80,86 **** # NICKNAME field ! nickname = person.valueForProperty(addressbook.kABNicknameProperty) ! if nickname != None: ! personVCard.setNickname(nickname) # BDAY field --- 81,85 ---- # NICKNAME field ! personVCard.setNickname(person.valueForProperty(addressbook.kABNicknameProperty)) # BDAY field *************** *** 118,126 **** value = phoneNumbers.valueAtIndex(index) if label == addressbook.kABPhoneWorkLabel: ! phoneTypes = [zxsync.vcard.WORK] elif label == addressbook.kABPhoneHomeLabel: ! phoneTypes = [zxsync.vcard.HOME] elif label == addressbook.kABPhoneMobileLabel: ! phoneTypes = [zxsync.vcard.CELL] elif label == addressbook.kABPhoneMainLabel: phoneTypes = [X_PREF] --- 117,126 ---- value = phoneNumbers.valueAtIndex(index) if label == addressbook.kABPhoneWorkLabel: ! phoneTypes = [zxsync.vcard.WORK, zxsync.vcard.VOICE] elif label == addressbook.kABPhoneHomeLabel: ! phoneTypes = [zxsync.vcard.HOME, zxsync.vcard.VOICE] elif label == addressbook.kABPhoneMobileLabel: ! phoneTypes = [zxsync.vcard.CELL, zxsync.vcard.HOME] ! # default cell to home elif label == addressbook.kABPhoneMainLabel: phoneTypes = [X_PREF] *************** *** 130,143 **** phoneTypes = [zxsync.vcard.WORK, zxsync.vcard.FAX] elif label == addressbook.kABPhonePagerLabel: ! phoneTypes = [zxsync.vcard.PAGER] else: ! phoneTypes = [] # do not use the vCard default of ["voice"] ! # since OS X's address book simply doesn't ! # distinguish between voice and modem ! # (or video or other things); ! # consequently, the "voice" type is ignored ! # when writing phone numbers (the number is ! # still written, but with no specific ! # "voice" label) if index == primaryIndex: phoneTypes.append(zxsync.vcard.PREF) --- 130,137 ---- phoneTypes = [zxsync.vcard.WORK, zxsync.vcard.FAX] elif label == addressbook.kABPhonePagerLabel: ! phoneTypes = [zxsync.vcard.PAGER, zxsync.vcard.WORK] ! # default pager to work else: ! phoneTypes = [zxsync.vcard.VOICE] if index == primaryIndex: phoneTypes.append(zxsync.vcard.PREF) *************** *** 164,185 **** # NOTE fields ! note = person.valueForProperty(addressbook.kABNoteProperty) ! if note != None: ! personVCard.addNote(note) # ORG fields ! org = person.valueForProperty(addressbook.kABOrganizationProperty) ! if org != None: ! personVCard.addOrganization(org) # TITLE fields ! title = person.valueForProperty(addressbook.kABJobTitleProperty) ! if title != None: ! personVCard.addTitle(title) # URL fields ! url = person.valueForProperty(addressbook.kABHomePageProperty) ! if url != None: ! personVCard.addURL(url) # X-AIM fields --- 158,171 ---- # NOTE fields ! personVCard.addNote(person.valueForProperty(addressbook.kABNoteProperty)) # ORG fields ! personVCard.addOrganization(person.valueForProperty(addressbook.kABOrganizationProperty)) # TITLE fields ! personVCard.addTitle(person.valueForProperty(addressbook.kABJobTitleProperty)) # URL fields ! personVCard.addURL(person.valueForProperty(addressbook.kABHomePageProperty)) # X-AIM fields *************** *** 318,322 **** --- 304,312 ---- birthdayValue = birthdayField.getValue() birthdayTuple = time.strptime(birthdayValue, "%Y-%m-%dT%H:%M:%SZ") + print birthdayTuple + print time.timezone birthdaySeconds = time.mktime(birthdayTuple) - time.timezone + print time.localtime(birthdaySeconds) + print time.gmtime(birthdaySeconds) birthdayValue = addressbook.CFDate(birthdaySeconds) setOrRemoveValue(record, birthdayValue, addressbook.kABBirthdayProperty) *************** *** 325,371 **** addressFields = vCard.getAddresses() addresses = None ! if len(addressFields) > 0: ! for addressField in addressFields: ! addressValue = addressField.getValue() ! addressTypes = addressField.getTypes() ! address = {} ! # Note: no support for po box and extended address ! street = addressValue[2][0] # Note: only one street supported ! if street != "": ! address[addressbook.kABAddressStreetKey] = street ! city = addressValue[3][0] # Note: only one city supported ! if city != "": ! address[addressbook.kABAddressCityKey] = city ! state = addressValue[4][0] # Note: only one state supported ! if state != "": ! address[addressbook.kABAddressStateKey] = state ! zip = addressValue[5][0] # Note: only one zip supported ! if zip != "": ! address[addressbook.kABAddressZIPKey] = zip ! country = addressValue[6][0] # Note: only one country supported ! if country != "": ! address[addressbook.kABAddressCountryKey] = country ! countryCode = addressValue[7][0] # Note: only one country code supported ! if countryCode != "": ! address[addressbook.kABAddressCountryCodeKey] = countryCode ! if len(address) > 0: ! if addresses == None: ! addresses = addressbook.ABMutableMultiValue() ! addressAdded = 0 ! for addressType in addressTypes: ! label = None ! if addressType == zxsync.vcard.HOME: ! label = addressbook.kABAddressHomeLabel ! elif addressType == zxsync.vcard.WORK: ! label = addressbook.kABAddressWorkLabel ! if label != None: ! identifier = addresses.addValue(address, label) ! addressAdded = 1 ! if zxsync.vcard.PREF in addressTypes: ! addresses.setPrimaryIdentifier(identifier) ! if not addressAdded: ! identifier = addresses.addValue(address, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in addressTypes: ! addresses.setPrimaryIdentifier(identifier) setOrRemoveValue(record, addresses, addressbook.kABAddressProperty) --- 315,353 ---- addressFields = vCard.getAddresses() addresses = None ! for addressField in addressFields: ! addressValue = addressField.getValue() ! addressTypes = addressField.getTypes() ! address = {} ! # Note: no support for po box and extended address ! street = addressValue[2][0] # Note: only one street supported ! if street != "": ! address[addressbook.kABAddressStreetKey] = street ! city = addressValue[3][0] # Note: only one city supported ! if city != "": ! address[addressbook.kABAddressCityKey] = city ! state = addressValue[4][0] # Note: only one state supported ! if state != "": ! address[addressbook.kABAddressStateKey] = state ! zip = addressValue[5][0] # Note: only one zip supported ! if zip != "": ! address[addressbook.kABAddressZIPKey] = zip ! country = addressValue[6][0] # Note: only one country supported ! if country != "": ! address[addressbook.kABAddressCountryKey] = country ! countryCode = addressValue[7][0] # Note: only one country code supported ! if countryCode != "": ! address[addressbook.kABAddressCountryCodeKey] = countryCode ! if len(address) > 0: ! if addresses == None: ! addresses = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in addressTypes: ! identifier = addresses.addValue(address, addressbook.kABAddressHomeLabel) ! if zxsync.vcard.WORK in addressTypes: ! identifier = addresses.addValue(address, addressbook.kABAddressWorkLabel) ! if identifier == None: ! identifier = addresses.addValue(address, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in addressTypes: ! addresses.setPrimaryIdentifier(identifier) setOrRemoveValue(record, addresses, addressbook.kABAddressProperty) *************** *** 373,401 **** phoneFields = vCard.getPhoneNumbers() phoneNumbers = None ! if len(phoneFields) > 0: ! for phoneField in phoneFields: ! phoneValue = phoneField.getValue() ! phoneTypes = phoneField.getTypes() ! if phoneNumbers == None: ! phoneNumbers = addressbook.ABMutableMultiValue() ! phoneAdded = 0 ! for phoneType in phoneTypes: ! label = None ! if phoneType == X_PREF: ! # special handling for OS X's main phone number ! label = addressbook.kABPhoneMainLabel ! elif phoneType == zxsync.vcard.HOME: ! label = addressbook.kABPhoneHomeLabel ! elif phoneType == zxsync.vcard.WORK: ! label = addressbook.kABPhoneWorkLabel ! if label != None: ! identifier = phoneNumbers.addValue(phoneValue, label) ! phoneAdded = 1 ! if zxsync.vcard.PREF in phoneTypes: ! phoneNumbers.setPrimaryIdentifier(identifier) ! if not phoneAdded: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in phoneTypes: ! phoneNumbers.setPrimaryIdentifier(identifier) setOrRemoveValue(record, phoneNumbers, addressbook.kABPhoneProperty) --- 355,392 ---- phoneFields = vCard.getPhoneNumbers() phoneNumbers = None ! for phoneField in phoneFields: ! phoneValue = phoneField.getValue() ! phoneTypes = phoneField.getTypes() ! if phoneNumbers == None: ! phoneNumbers = addressbook.ABMutableMultiValue() ! identifier = None ! if X_PREF in phoneTypes: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhoneMainLabel) ! if zxsync.vcard.HOME in phoneTypes: ! identifier = None ! if zxsync.vcard.FAX in phoneTypes: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhoneHomeFAXLabel) ! if zxsync.vcard.VOICE in phoneTypes or ( ! identifier == None and ! (not (zxsync.vcard.CELL in phoneTypes)) and ! (not (zxsync.vcard.PAGER in phoneTypes))): ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhoneHomeLabel) ! if zxsync.vcard.WORK in phoneTypes: ! identifier = None ! if zxsync.vcard.FAX in phoneTypes: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhoneWorkFAXLabel) ! if zxsync.vcard.VOICE in phoneTypes or ( ! identifier == None and ! (not (zxsync.vcard.CELL in phoneTypes)) and ! (not (zxsync.vcard.PAGER in phoneTypes))): ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhoneWorkLabel) ! if zxsync.vcard.CELL in phoneTypes: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhoneMobileLabel) ! if zxsync.vcard.PAGER in phoneTypes: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABPhonePagerLabel) ! if identifier == None: ! identifier = phoneNumbers.addValue(phoneValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in phoneTypes: ! phoneNumbers.setPrimaryIdentifier(identifier) setOrRemoveValue(record, phoneNumbers, addressbook.kABPhoneProperty) *************** *** 403,428 **** emailFields = vCard.getEmailAddresses() emailAddresses = None ! if len(emailFields) > 0: ! for emailField in emailFields: ! emailValue = emailField.getValue() ! emailTypes = emailField.getTypes() ! if emailAddresses == None: ! emailAddresses = addressbook.ABMutableMultiValue() ! emailAdded = 0 ! for emailType in emailTypes: ! label = None ! if emailType == zxsync.vcard.HOME: ! label = addressbook.kABEmailHomeLabel ! elif emailType == zxsync.vcard.WORK: ! label = addressbook.kABEmailWorkLabel ! if label != None: ! identifier = emailAddresses.addValue(emailValue, label) ! emailAdded = 1 ! if zxsync.vcard.PREF in emailTypes: ! emailAddresses.setPrimaryIdentifier(identifier) ! if not emailAdded: ! identifier = emailAddresses.addValue(emailValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in emailTypes: ! emailAddresses.setPrimaryIdentifier(identifier) setOrRemoveValue(record, emailAddresses, addressbook.kABEmailProperty) --- 394,411 ---- emailFields = vCard.getEmailAddresses() emailAddresses = None ! for emailField in emailFields: ! emailValue = emailField.getValue() ! emailTypes = emailField.getTypes() ! if emailAddresses == None: ! emailAddresses = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in emailTypes: ! identifier = emailAddresses.addValue(emailValue, addressbook.kABEmailHomeLabel) ! if zxsync.vcard.WORK in emailTypes: ! identifier = emailAddresses.addValue(emailValue, addressbook.kABEmailWorkLabel) ! if identifier == None: ! identifier = emailAddresses.addValue(emailValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in emailTypes: ! emailAddresses.setPrimaryIdentifier(identifier) setOrRemoveValue(record, emailAddresses, addressbook.kABEmailProperty) *************** *** 467,486 **** if aim == None: aim = addressbook.ABMutableMultiValue() ! aimAdded = 0 ! for aimType in aimTypes: ! label = None ! if aimType == zxsync.vcard.HOME: ! label = addressbook.kABAIMHomeLabel ! elif aimType == zxsync.vcard.WORK: ! label = addressbook.kABAIMWorkLabel ! if label != None: ! identifier = aim.addValue(aimValue, label) ! aimAdded = 1 ! if zxsync.vcard.PREF in aimTypes: ! aim.setPrimaryIdentifier(identifier) ! if not aimAdded: identifier = aim.addValue(aimValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in aimTypes: ! aim.setPrimaryIdentifier(identifier) setOrRemoveValue(record, aim, addressbook.kABAIMInstantProperty) --- 450,462 ---- if aim == None: aim = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in aimTypes: ! identifier = aim.addValue(aimValue, addressbook.kABAIMHomeLabel) ! if zxsync.vcard.WORK in aimTypes: ! identifier = aim.addValue(aimValue, addressbook.kABAIMWorkLabel) ! if identifier == None: identifier = aim.addValue(aimValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in aimTypes: ! aim.setPrimaryIdentifier(identifier) setOrRemoveValue(record, aim, addressbook.kABAIMInstantProperty) *************** *** 493,512 **** if icq == None: icq = addressbook.ABMutableMultiValue() ! icqAdded = 0 ! for icqType in icqTypes: ! label = None ! if icqType == zxsync.vcard.HOME: ! label = addressbook.kABICQHomeLabel ! elif icqType == zxsync.vcard.WORK: ! label = addressbook.kABICQWorkLabel ! if label != None: ! identifier = icq.addValue(icqValue, label) ! icqAdded = 1 ! if zxsync.vcard.PREF in icqTypes: ! icq.setPrimaryIdentifier(identifier) ! if not icqAdded: ! identifier = icq.addValue(icqValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in icqTypes: ! icq.setPrimaryIdentifier(identifier) setOrRemoveValue(record, icq, addressbook.kABICQInstantProperty) --- 469,481 ---- if icq == None: icq = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in icqTypes: ! identifier = icq.addValue(icqValue, kABICQHomeLabel) ! if zxsync.vcard.WORK in icqTypes: ! identifier = icq.addValue(icqValue, kABICQWorkLabel) ! if identifier == None: ! identifier = icq.addValue(icqValue, kABOtherLabel) ! if zxsync.vcard.PREF in icqTypes: ! icq.setPrimaryIdentifier(identifier) setOrRemoveValue(record, icq, addressbook.kABICQInstantProperty) *************** *** 519,538 **** if jabber == None: jabber = addressbook.ABMutableMultiValue() ! jabberAdded = 0 ! for jabberType in jabberTypes: ! label = None ! if jabberType == zxsync.vcard.HOME: ! label = addressbook.kABJabberHomeLabel ! elif jabberType == zxsync.vcard.WORK: ! label = addressbook.kABJabberWorkLabel ! if label != None: ! identifier = jabber.addValue(jabberValue, label) ! jabberAdded = 1 ! if zxsync.vcard.PREF in jabberTypes: ! jabber.setPrimaryIdentifier(identifier) ! if not jabberAdded: ! identifier = jabber.addValue(jabberValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in jabberTypes: ! jabber.setPrimaryIdentifier(identifier) setOrRemoveValue(record, jabber, addressbook.kABJabberInstantProperty) --- 488,500 ---- if jabber == None: jabber = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in jabberTypes: ! identifier = jabber.addValue(jabberValue, kABJabberHomeLabel) ! if zxsync.vcard.WORK in jabberTypes: ! identifier = jabber.addValue(jabberValue, kABJabberWorkLabel) ! if identifier == None: ! identifier = jabber.addValue(jabberValue, kABOtherLabel) ! if zxsync.vcard.PREF in jabberTypes: ! jabber.setPrimaryIdentifier(identifier) setOrRemoveValue(record, jabber, addressbook.kABJabberInstantProperty) *************** *** 545,564 **** if msn == None: msn = addressbook.ABMutableMultiValue() ! msnAdded = 0 ! for msnType in msnTypes: ! label = None ! if msnType == zxsync.vcard.HOME: ! label = addressbook.kABMSNHomeLabel ! elif msnType == zxsync.vcard.WORK: ! label = addressbook.kABMSNWorkLabel ! if label != None: ! identifier = msn.addValue(msnValue, label) ! msnAdded = 1 ! if zxsync.vcard.PREF in msnTypes: ! msn.setPrimaryIdentifier(identifier) ! if not msnAdded: ! identifier = msn.addValue(msnValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in msnTypes: ! msn.setPrimaryIdentifier(identifier) setOrRemoveValue(record, msn, addressbook.kABMSNInstantProperty) --- 507,519 ---- if msn == None: msn = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in msnTypes: ! identifier = msn.addValue(msnValue, kABMSNHomeLabel) ! if zxsync.vcard.WORK in msnTypes: ! identifier = msn.addValue(msnValue, kABMSNWorkLabel) ! if identifier == None: ! identifier = msn.addValue(msnValue, kABOtherLabel) ! if zxsync.vcard.PREF in msnTypes: ! msn.setPrimaryIdentifier(identifier) setOrRemoveValue(record, msn, addressbook.kABMSNInstantProperty) *************** *** 571,590 **** if yahoo == None: yahoo = addressbook.ABMutableMultiValue() ! yahooAdded = 0 ! for yahooType in yahooTypes: ! label = None ! if yahooType == zxsync.vcard.HOME: ! label = addressbook.kABYahooHomeLabel ! elif yahooType == zxsync.vcard.WORK: ! label = addressbook.kABYahooWorkLabel ! if label != None: ! identifier = yahoo.addValue(yahooValue, label) ! yahooAdded = 1 ! if zxsync.vcard.PREF in yahooTypes: ! yahoo.setPrimaryIdentifier(identifier) ! if not yahooAdded: ! identifier = yahoo.addValue(yahooValue, addressbook.kABOtherLabel) ! if zxsync.vcard.PREF in yahooTypes: ! yahoo.setPrimaryIdentifier(identifier) setOrRemoveValue(record, yahoo, addressbook.kABYahooInstantProperty) --- 526,538 ---- if yahoo == None: yahoo = addressbook.ABMutableMultiValue() ! identifier = None ! if zxsync.vcard.HOME in yahooTypes: ! identifier = yahoo.addValue(yahooValue, kABYahooHomeLabel) ! if zxsync.vcard.WORK in yahooTypes: ! identifier = yahoo.addValue(yahooValue, kABYahooWorkLabel) ! if identifier == None: ! identifier = yahoo.addValue(yahooValue, kABOtherLabel) ! if zxsync.vcard.PREF in yahooTypes: ! yahoo.setPrimaryIdentifier(identifier) setOrRemoveValue(record, yahoo, addressbook.kABYahooInstantProperty) |
From: <luc...@us...> - 2003-05-10 00:17:53
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv24094 Modified Files: vcard.py Log Message: Some fixes plus support for separate home and work URLs. Index: vcard.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/vcard.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** vcard.py 24 Apr 2003 21:50:03 -0000 1.3 --- vcard.py 10 May 2003 00:17:50 -0000 1.4 *************** *** 83,86 **** --- 83,88 ---- X_MSN = "X-MSN" X_MSN_DEFAULT = "" + X_URL_HOME = "X-URL-HOME" + X_URL_WORK = "X-URL-WORK" X_YAHOO = "X-YAHOO" X_YAHOO_DEFAULT = "" *************** *** 683,687 **** newMailerValue = convertToInternalValue(mailer) if newMailerValue != MAILER_DEFAULT: ! self.addChild(VCardField(MAILER, convertToInternalValue(mailer))) --- 685,689 ---- newMailerValue = convertToInternalValue(mailer) if newMailerValue != MAILER_DEFAULT: ! self.addChild(VCardField(MAILER, newMailerValue)) *************** *** 748,752 **** newTitleValue = convertToInternalValue(title) if newTitleValue != TITLE_DEFAULT: ! self.addChild(VCardField(TITLE, convertToInternalValue(title))) --- 750,754 ---- newTitleValue = convertToInternalValue(title) if newTitleValue != TITLE_DEFAULT: ! self.addChild(VCardField(TITLE, newTitleValue)) *************** *** 767,771 **** newRoleValue = convertToInternalValue(role) if newRoleValue != ROLE_DEFAULT: ! self.addChild(VCardField(ROLE, convertToInternalValue(role))) --- 769,773 ---- newRoleValue = convertToInternalValue(role) if newRoleValue != ROLE_DEFAULT: ! self.addChild(VCardField(ROLE, newRoleValue)) *************** *** 883,887 **** newNoteValue = convertToInternalValue(note) if newNoteValue != NOTE_DEFAULT: ! self.addChild(VCardField(NOTE, convertToInternalValue(note))) --- 885,889 ---- newNoteValue = convertToInternalValue(note) if newNoteValue != NOTE_DEFAULT: ! self.addChild(VCardField(NOTE, newNoteValue)) *************** *** 992,995 **** --- 994,1029 ---- + def getHomeURLs(self): + """ + Returns the X-URL-HOME fields of this vCard. + """ + return self.getChildrenWithId(X_URL_HOME) + + + def addHomeURL(self, url): + """ + Adds an X-URL-HOME field to this vCard. + """ + newURLValue = convertToInternalValue(url) + if newURLValue != URL_DEFAULT: + self.addChild(VCardField(X_URL_HOME, newURLValue)) + + + def getWorkURLs(self): + """ + Returns the X-URL-WORK fields of this vCard. + """ + return self.getChildrenWithId(X_URL_WORK) + + + def addWorkURL(self, url): + """ + Adds an X-URL-WORK field to this vCard. + """ + newURLValue = convertToInternalValue(url) + if newURLValue != URL_DEFAULT: + self.addChild(VCardField(X_URL_WORK, newURLValue)) + + def getClassification(self): """ *************** *** 1203,1205 **** --- 1237,1244 ---- self.normalizeField(TEL) self.normalizeField(EMAIL) + self.normalizeField(X_AIM) + self.normalizeField(X_ICQ) + self.normalizeField(X_JABBER) + self.normalizeField(X_MSN) + self.normalizeField(X_YAHOO) |
From: <luc...@us...> - 2003-05-10 00:16:43
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv23634 Modified Files: engine.py Log Message: Various fixes. Most importantly, the sync is now done one app at a time. Index: engine.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/engine.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** engine.py 7 May 2003 20:38:23 -0000 1.5 --- engine.py 10 May 2003 00:16:38 -0000 1.6 *************** *** 174,185 **** Handles an error by delegating it to the global context. """ ! globalContext.handleError(fatal, message, arguments) ! ! ! def resetSyncInfo(self): ! """ ! Resets the internal information regarding a sync. ! """ ! self.conflictList = [] --- 174,178 ---- Handles an error by delegating it to the global context. """ ! globalContext.handleError(fatal, message, *arguments) *************** *** 189,193 **** """ self.cancelSync() - self.resetSyncInfo() for deviceInfo in self.devices: try: --- 182,185 ---- *************** *** 272,280 **** ! def beginSync(self): """ ! Begins a a sync operation. """ - self.resetSyncInfo() for deviceInfo in self.devices: device = deviceInfo.device --- 264,271 ---- ! def beginSync(self, appToSync): """ ! Begins a a sync operation for the specified application. """ for deviceInfo in self.devices: device = deviceInfo.device *************** *** 285,324 **** for appInfo in deviceInfo.apps: deviceApp = appInfo.app ! if appInfo.syncStarted: ! appInfo.syncStarted = 0 try: ! deviceApp.endSync() except: ! self.handleError(0, i18n["END_SYNC_FAILED"], deviceInfo.plugin.__name__); ! try: ! writeMode = deviceApp.beginSync() ! appInfo.syncStarted = 1 ! except: ! self.handleError(1, i18n["BEGIN_SYNC_FAILED"], deviceInfo.plugin.__name__); ! # fatal; don't continue syncing ! oldFatalDefault = globalContext.fatalDefault ! globalContext.fatalDefault = READ_ERRORS_ARE_FATAL ! try: ! deviceEntries = deviceApp.readAllEntries() ! removeList = [] ! for deviceEntry in deviceEntries: ! if not deviceEntry.isValid(): ! print "Invalid entry:", deviceEntry ! removeList.append(deviceEntry) ! for removeEntry in removeList: ! deviceEntries.remove(removeEntry) ! newApp = syncbase.Application(deviceApp.getId()) ! newApp.setSource(deviceApp) ! newApp.setWriteMode(writeMode) ! newApp.addChildren(deviceEntries) ! deviceInfo.data.append(newApp) ! deviceInfo.entriesRead += len(deviceEntries) ! except: globalContext.fatalDefault = oldFatalDefault - self.handleError(1, i18n["READ_ALL_FAILED"], deviceInfo.plugin.__name__); - # fatal: we either got (1) an unexpected exception or - # (2) the plugin called handleError() with fatal == true - # or (3) the default for read errors is fatal - globalContext.fatalDefault = oldFatalDefault --- 276,316 ---- for appInfo in deviceInfo.apps: deviceApp = appInfo.app ! if deviceApp.getId() == appToSync: ! if appInfo.syncStarted: ! appInfo.syncStarted = 0 ! try: ! deviceApp.endSync() ! except: ! self.handleError(0, i18n["END_SYNC_FAILED"], deviceInfo.plugin.__name__); try: ! writeMode = deviceApp.beginSync() ! appInfo.syncStarted = 1 except: ! self.handleError(1, i18n["BEGIN_SYNC_FAILED"], deviceInfo.plugin.__name__); ! # fatal; don't continue syncing ! oldFatalDefault = globalContext.fatalDefault ! globalContext.fatalDefault = READ_ERRORS_ARE_FATAL ! try: ! deviceEntries = deviceApp.readAllEntries() ! removeList = [] ! for deviceEntry in deviceEntries: ! if not deviceEntry.isValid(): ! print "Invalid entry:", deviceEntry ! removeList.append(deviceEntry) ! for removeEntry in removeList: ! deviceEntries.remove(removeEntry) ! newApp = syncbase.Application(deviceApp.getId()) ! newApp.setSource(deviceApp) ! newApp.setWriteMode(writeMode) ! newApp.addChildren(deviceEntries) ! deviceInfo.data.append(newApp) ! deviceInfo.entriesRead += len(deviceEntries) ! except: ! globalContext.fatalDefault = oldFatalDefault ! self.handleError(1, i18n["READ_ALL_FAILED"], deviceInfo.plugin.__name__); ! # fatal: we either got (1) an unexpected exception or ! # (2) the plugin called handleError() with fatal == true ! # or (3) the default for read errors is fatal globalContext.fatalDefault = oldFatalDefault *************** *** 359,363 **** ! def syncData(self, checkConflictsOnly): """ Perform a sync operation. Data is only actually changed during this --- 351,355 ---- ! def syncData(self, checkConflictsOnly, appToSync): """ Perform a sync operation. Data is only actually changed during this *************** *** 366,394 **** for deviceInfo in self.devices: for syncApp in deviceInfo.data: ! matchingApps = self.findMatchingApps(syncApp) ! # also finds the current app ! entries = syncApp.getChildren() ! ! # case 1: something has to be added ! syncMode = syncApp.getSyncMode() ! if syncMode == syncbase.SYNC_TO or syncMode == syncbase.SYNC_BOTH: ! additionalEntries = self.findAdditionalEntries(entries) ! for additionalEntry in additionalEntries: ! newEntry = additionalEntry.clone() ! newEntry.setParent(syncApp) ! # this does _not_ add the new entry to the app's ! # list of children ! deviceInfo.addList.append(newEntry) ! ! #for entry in entries: ! # matchingEntries = self.findMatchingEntries(matchingApps, entry) ! # # also finds the current entry ! # fields = entry.getChildren() ! # for field in fields: ! # matchingFields = self.findMatchingFields(matchingEntries, field) ! # # also finds the current field ! # # case 1: field must be deleted ! # if field.getSyncMode() == syncbase.TO ! #print len(entries), "entries found for app", syncApp.getId(), "in", deviceInfo.plugin.__name__ if not checkConflictsOnly: --- 358,387 ---- for deviceInfo in self.devices: for syncApp in deviceInfo.data: ! if syncApp.getSource().getId() == appToSync: ! matchingApps = self.findMatchingApps(syncApp) ! # also finds the current app ! entries = syncApp.getChildren() ! ! # case 1: something has to be added ! syncMode = syncApp.getSyncMode() ! if syncMode == syncbase.SYNC_TO or syncMode == syncbase.SYNC_BOTH: ! additionalEntries = self.findAdditionalEntries(entries) ! for additionalEntry in additionalEntries: ! newEntry = additionalEntry.clone() ! newEntry.setParent(syncApp) ! # this does _not_ add the new entry to the app's ! # list of children ! deviceInfo.addList.append(newEntry) ! ! #for entry in entries: ! # matchingEntries = self.findMatchingEntries(matchingApps, entry) ! # # also finds the current entry ! # fields = entry.getChildren() ! # for field in fields: ! # matchingFields = self.findMatchingFields(matchingEntries, field) ! # # also finds the current field ! # # case 1: field must be deleted ! # if field.getSyncMode() == syncbase.TO ! #print len(entries), "entries found for app", syncApp.getId(), "in", deviceInfo.plugin.__name__ if not checkConflictsOnly: *************** *** 400,408 **** entry.getParent().addChild(entry) for syncApp in deviceInfo.data: ! if syncApp.getWriteMode() == syncbase.WRITE_SINGLE: ! for entry in deviceInfo.addList: ! syncApp.getSource().addEntry(entry) ! else: ! syncApp.getSource().writeAllEntries(syncApp.getChildren()) except: globalContext.fatalDefault = oldFatalDefault --- 393,402 ---- entry.getParent().addChild(entry) for syncApp in deviceInfo.data: ! if syncApp.getSource().getId() == appToSync: ! if syncApp.getWriteMode() == syncbase.WRITE_SINGLE: ! for entry in deviceInfo.addList: ! syncApp.getSource().addEntry(entry) ! else: ! syncApp.getSource().writeAllEntries(syncApp.getChildren()) except: globalContext.fatalDefault = oldFatalDefault *************** *** 429,438 **** ! def endSync(self): """ Ends a sync operation. """ ! self.cancelSync() ! # FIXME: to be changed (ending is not the same as cancelling) --- 423,440 ---- ! def endSync(self, appToSync): """ Ends a sync operation. """ ! for deviceInfo in self.devices: ! for appInfo in deviceInfo.apps: ! if appInfo.app.getId() == appToSync: ! if appInfo.syncStarted: ! appInfo.syncStarted = 0 ! deviceApp = appInfo.app ! try: ! deviceApp.endSync() ! except: ! self.handleError(0, i18n["END_SYNC_FAILED"], deviceInfo.plugin.__name__) *************** *** 460,465 **** engine.findPlugins(pluginsDir) engine.findDevices(settings) ! engine.beginSync() ! engine.syncData(0) print print "Plugins" --- 462,471 ---- engine.findPlugins(pluginsDir) engine.findDevices(settings) ! engine.beginSync(syncbase.CALENDAR_APP_ID) ! engine.syncData(0, syncbase.CALENDAR_APP_ID) ! engine.endSync(syncbase.CALENDAR_APP_ID) ! engine.beginSync(syncbase.CONTACTS_APP_ID) ! engine.syncData(0, syncbase.CONTACTS_APP_ID) ! engine.endSync(syncbase.CONTACTS_APP_ID) print print "Plugins" *************** *** 484,488 **** print ";", deviceInfo.addList print - engine.cancelSync() engine.resetDevices() --- 490,493 ---- |
From: <luc...@us...> - 2003-05-07 20:38:26
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv5821 Modified Files: engine.py Log Message: Fixed incorrect message key Index: engine.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/engine.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** engine.py 6 May 2003 17:26:55 -0000 1.4 --- engine.py 7 May 2003 20:38:23 -0000 1.5 *************** *** 36,40 **** "ERROR_MESSAGE": "MESSAGE", "ERROR_TYPE": "TYPE", ! "GET_APPLICATION_IDS_FAILED": "Retrieving applications for a device provided by plugin %1 failed", "FREE_DEVICE_FAILED": "Freeing a device provided by plugin %1 failed", "INIT_DEVICE_FAILED": "Initializing a device provided by plugin %1 failed", --- 36,40 ---- "ERROR_MESSAGE": "MESSAGE", "ERROR_TYPE": "TYPE", ! "GET_APPLICATIONS_FAILED": "Retrieving applications for a device provided by plugin %1 failed", "FREE_DEVICE_FAILED": "Freeing a device provided by plugin %1 failed", "INIT_DEVICE_FAILED": "Initializing a device provided by plugin %1 failed", |
From: <luc...@us...> - 2003-05-07 20:36:53
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv5112 Modified Files: zaurusutils.py Log Message: Added a readFile() function for generic FTP read access Index: zaurusutils.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/zaurusutils.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** zaurusutils.py 7 May 2003 00:32:07 -0000 1.3 --- zaurusutils.py 7 May 2003 20:36:49 -0000 1.4 *************** *** 4,7 **** --- 4,8 ---- # # Copyright (C) 2003 Geoff Beier <ge...@mo...> + # Copyright (C) 2003 Andreas Junghans <aj...@lu...> # # This library is free software; you can redistribute it and/or *************** *** 32,35 **** --- 33,65 ---- this module""" pass + + + def readFile(zaurus, path): + """ + Reads a file from the Zaurus (via FTP). The "zaurus" parameter contains + a Zaurus device object (used for retrieving IP address etc.). + """ + + ftpconn = ftplib.FTP() + try: + ftpconn.connect( zaurus.ip_address, zaurus.ftp_port ) + ftpconn.login( zaurus.user, zaurus.password ) + except Exception, e: + raise ZaurusUtilError("readFile(): error connecting to the Zaurus: " + str(e)) + try: + contents = [""] + def readBlock(block): + contents[0] += block + ftpconn.retrbinary("RETR " + path, readBlock) + except Exception, e: + ftpconn.quit() + raise ZaurusUtilError("readFile(): error retrieving file '" + path + "' from the Zaurus: " + str(e) ) + try: + ftpconn.quit() + except: + ftpconn.close() + + return contents[0] + # XXX: change these if more escaping/unescaping needs to be done |
From: <luc...@us...> - 2003-05-07 20:31:39
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv2682 Modified Files: qcop.py Log Message: Make the timeout more portable: The return value of connect_ex is not the same across platforms, and select will report failure anyway (so no real need to check connect_ex's return value) Index: qcop.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/qcop.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** qcop.py 6 May 2003 17:36:37 -0000 1.2 --- qcop.py 7 May 2003 20:31:36 -0000 1.3 *************** *** 171,181 **** self.zsock.setblocking(0) ret = self.zsock.connect_ex((self.remotehost, self.remoteport)) ! xx, xxx, xxxx = (None, None, None) ! if ret == 36: ! xx, xxx, xxxx = select.select([], [self.zsock], [], 5.0) ! else: ! raise QCOPError, "cannot connect" if not xx and not xxx and not xxxx: ! raise QCOPError, "timeout occured" self.zsock.setblocking(1) except Exception, msg: --- 171,177 ---- self.zsock.setblocking(0) ret = self.zsock.connect_ex((self.remotehost, self.remoteport)) ! xx, xxx, xxxx = select.select([], [self.zsock], [], 5.0) if not xx and not xxx and not xxxx: ! raise QCOPError, "cannot connect to Zaurus" self.zsock.setblocking(1) except Exception, msg: *************** *** 184,188 **** except: pass ! print msg raise # self.zsock.connect((self.remotehost, self.remoteport)) --- 180,184 ---- except: pass ! #print msg raise # self.zsock.connect((self.remotehost, self.remoteport)) |
From: <gb...@us...> - 2003-05-07 00:32:11
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv12640 Modified Files: zaurusutils.py Log Message: removed apostrophe unescaping again... inadvertently reenabled it before the last checkin Index: zaurusutils.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/zaurusutils.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** zaurusutils.py 7 May 2003 00:11:51 -0000 1.2 --- zaurusutils.py 7 May 2003 00:32:07 -0000 1.3 *************** *** 38,42 **** '"':'"', # the z does not escape apostrophes ! ''':"'", '<':'<', '>':'>' } --- 38,42 ---- '"':'"', # the z does not escape apostrophes ! #''':"'", '<':'<', '>':'>' } |
From: <gb...@us...> - 2003-05-07 00:11:55
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv6655/util Modified Files: datebook.py zaurusutils.py Log Message: implement escape/unescape, restore previously removed "note" field on the Z Index: datebook.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/datebook.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** datebook.py 5 May 2003 06:38:54 -0000 1.4 --- datebook.py 7 May 2003 00:11:51 -0000 1.5 *************** *** 198,205 **** summary = entry.getField("SUMMARY") if( summary ): ! xmlEntry += " description=\"" + summary + "\"" location = entry.getField("LOCATION") if( location ): ! xmlEntry += " location=\"" + location + "\"" # first try the zaurus category, then try to map the iCal category, then use the default # this doesn't look elegant, but it's because I don't know of any c-style assignment shortcut --- 198,205 ---- summary = entry.getField("SUMMARY") if( summary ): ! xmlEntry += " description=\"" + zaurusutils.zaurusEscape(summary) + "\"" location = entry.getField("LOCATION") if( location ): ! xmlEntry += " location=\"" + zaurusutils.zaurusEscape(location) + "\"" # first try the zaurus category, then try to map the iCal category, then use the default # this doesn't look elegant, but it's because I don't know of any c-style assignment shortcut *************** *** 251,255 **** --- 251,259 ---- enddt = icalToUnixTime(enddt) xmlEntry += " end=\"" + enddt + "\"" + note = entry.getField("DESCRIPTION") + if( note ): + xmlEntry += " note=\"" + zaurusutils.zaurusEscape(note) + "\"" xmlEntry += " />\n" + print xmlEntry return xmlEntry Index: zaurusutils.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/zaurusutils.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** zaurusutils.py 5 May 2003 06:38:23 -0000 1.1 --- zaurusutils.py 7 May 2003 00:11:51 -0000 1.2 *************** *** 33,40 **** pass def zaurusEscape( text ): """Escapes the text for zaurus-style XML""" ! ### XXX:Not implemented yet ! return text def zaurusUnescape( text ): --- 33,61 ---- pass + # XXX: change these if more escaping/unescaping needs to be done + # a dictionary mapping escaped -> unescaped + escapedDict = { '&':'&', + '"':'"', + # the z does not escape apostrophes + ''':"'", + '<':'<', + '>':'>' } + # a dictionary mapping unescaped -> escaped + unescapedDict = { '&':'&', + '"':'"', + # the z does not escape apostrophes + #"'":''', + '<':'<', + '>':'>' } + + # compile these once for reuse many times + escaper = re.compile("(%s)" % "|".join(map(re.escape, unescapedDict.keys()))) + unescaper = re.compile("(%s)" % "|".join(map(re.escape, escapedDict.keys()))) + + def zaurusEscape( text ): """Escapes the text for zaurus-style XML""" ! return escaper.sub(lambda mo: unescapedDict[mo.string[mo.start():mo.end()]], text) ! def zaurusUnescape( text ): *************** *** 44,49 **** Assumes that it is properly escaped in the first place """ ! # XXX:Not implemented yet ! return text def getCategories(zaurus): --- 65,69 ---- Assumes that it is properly escaped in the first place """ ! return unescaper.sub(lambda mo: escapedDict[mo.string[mo.start():mo.end()]], text) def getCategories(zaurus): |
From: <luc...@us...> - 2003-05-06 17:46:40
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv32112 Modified Files: osxplugin.py Log Message: Remove debug statements (not really a worthy commit, but I want to have a clean state in my workspace ;-)) Index: osxplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/osxplugin.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** osxplugin.py 4 May 2003 20:30:44 -0000 1.5 --- osxplugin.py 6 May 2003 17:46:37 -0000 1.6 *************** *** 179,186 **** device = OSXDevice(settingsDict) devices.append(device) - - # test - #device.init() - #device.readAll("xy") return devices --- 179,182 ---- |
From: <luc...@us...> - 2003-05-06 17:45:09
|
Update of /cvsroot/zxsync/zXSync/plugins/osx In directory sc8-pr-cvs1:/tmp/cvs-serv31231 Modified Files: ipodplugin.py Log Message: Added default for iPodName ("iPod" seems reasonable) Index: ipodplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/osx/ipodplugin.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** ipodplugin.py 4 May 2003 20:30:04 -0000 1.3 --- ipodplugin.py 6 May 2003 17:45:05 -0000 1.4 *************** *** 34,37 **** --- 34,50 ---- + def iPodName(settings): + """ + Returns the name of the iPod. This is read from the settings or (if not + present) defaults to "iPod". + """ + try: + iPodName = settings["iPodName"] + except KeyError: + iPodName = "iPod" + + return iPodName + + class iPodPluginError(PluginError): """ *************** *** 51,58 **** """ self.settings = settings ! self.contactsPath = "/Volumes/" + self.settings["iPodName"] + "/Contacts" ! self.contactsBakPath = "/Volumes/" + self.settings["iPodName"] + "/Contacts.zxsync_bak" ! # the "iPodName" setting is guaranteed to exist (checked in the ! # probe() function) --- 64,69 ---- """ self.settings = settings ! self.contactsPath = "/Volumes/" + iPodName(self.settings) + "/Contacts" ! self.contactsBakPath = "/Volumes/" + iPodName(self.settings) + "/Contacts.zxsync_bak" *************** *** 175,179 **** ! def writeAll(self, entries): """ Writes all entries. --- 186,190 ---- ! def writeAllEntries(self, entries): """ Writes all entries. *************** *** 224,229 **** if sys.platform[:6] == "darwin": for settingsDict in settings: ! iPodName = settingsDict["iPodName"] ! if os.path.exists("/Volumes/" + iPodName + "/iPod_Control"): device = iPodDevice(settingsDict) devices.append(device) --- 235,239 ---- if sys.platform[:6] == "darwin": for settingsDict in settings: ! if os.path.exists("/Volumes/" + iPodName(settingsDict) + "/iPod_Control"): device = iPodDevice(settingsDict) devices.append(device) |
From: <luc...@us...> - 2003-05-06 17:43:31
|
Update of /cvsroot/zxsync/zXSync/doc/xsl/html In directory sc8-pr-cvs1:/tmp/cvs-serv30578 Modified Files: zxsync.xsl Log Message: Make the logo a link to the start page Index: zxsync.xsl =================================================================== RCS file: /cvsroot/zxsync/zXSync/doc/xsl/html/zxsync.xsl,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** zxsync.xsl 4 May 2003 20:12:08 -0000 1.2 --- zxsync.xsl 6 May 2003 17:43:28 -0000 1.3 *************** *** 10,14 **** </div> <div class="zxsync-logo"> ! <img src="../images/zxsync.png" width="96" height="106" border="0" alt="zXSync Logo"/> </div> <div class="sync-action"> --- 10,15 ---- </div> <div class="zxsync-logo"> ! <a href="index.html"> ! <img src="../images/zxsync.png" width="96" height="106" border="0" alt="zXSync Logo"/></a> </div> <div class="sync-action"> |
From: <luc...@us...> - 2003-05-06 17:42:29
|
Update of /cvsroot/zxsync/zXSync/doc In directory sc8-pr-cvs1:/tmp/cvs-serv30214 Modified Files: apidoc.xml Log Message: Added section about vevents Index: apidoc.xml =================================================================== RCS file: /cvsroot/zxsync/zXSync/doc/apidoc.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** apidoc.xml 4 May 2003 20:12:52 -0000 1.3 --- apidoc.xml 6 May 2003 17:42:25 -0000 1.4 *************** *** 615,619 **** <para> For internally handling contact information, zXSync uses a Python ! representation of vCards (described in RFC 2426). <classname>zxsync.vcard.VCard</classname> is an <link linkend="entry"><classname>Entry</classname></link> sub --- 615,620 ---- <para> For internally handling contact information, zXSync uses a Python ! representation of vCards (described in ! <ulink url="http://www.ietf.org/rfc/rfc2426.txt">RFC 2426</ulink>). <classname>zxsync.vcard.VCard</classname> is an <link linkend="entry"><classname>Entry</classname></link> sub *************** *** 629,632 **** --- 630,653 ---- </para> </section> <!-- vcard --> + + <section id="vevent"> + <title>iCalendar support classes</title> + <para> + For internally handling calendar information, zXSync uses a + Python representation of iCalendar events (described in + <ulink url="http://www.ietf.org/rfc/rfc2445.txt">RFC 2445</ulink>). + <classname>zxsync.vevent.VEvent</classname> is an + <link linkend="entry"><classname>Entry</classname></link> sub + class for events, and + <classname>zxsync.vevent.VEventField</classname> is a + specialized version of + <link linkend="field"><classname>Field</classname></link>. + </para> + <para> + For detailed documentation of these classes, import them in an + interactive Python shell and use + <command>help(<classname>)</command>. + </para> + </section> <!-- vevent --> </article> |
From: <luc...@us...> - 2003-05-06 17:40:19
|
Update of /cvsroot/zxsync/zXSync/doc/css/html In directory sc8-pr-cvs1:/tmp/cvs-serv29428 Modified Files: docbook.css Log Message: - Minor fix for the logo - Added workaround for Camino bug (it's my current browser of choice, so it _has to_ look good in it ;-)) Index: docbook.css =================================================================== RCS file: /cvsroot/zxsync/zXSync/doc/css/html/docbook.css,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** docbook.css 4 May 2003 20:03:21 -0000 1.1 --- docbook.css 6 May 2003 17:40:15 -0000 1.2 *************** *** 1,5 **** body {font-size: 95%} ! div.zxsync-logo img {padding: 5px; border: 1px solid gray} div.sync-action {position: absolute; top: 1ex; left: 140px; padding-top: 5px} div.sourceforge-logo {position: absolute; right: 1ex; top: 1ex} --- 1,5 ---- body {font-size: 95%} ! div.zxsync-logo img {padding: 5px; border: 1px solid gray; background: white} div.sync-action {position: absolute; top: 1ex; left: 140px; padding-top: 5px} div.sourceforge-logo {position: absolute; right: 1ex; top: 1ex} *************** *** 15,19 **** body>div>div.section {margin-left:22ex; margin-bottom: 3ex} h1.title {position: absolute; top: 1ex; padding-top: 40px; left: 140px; display: inline; font-size: 180%; font-style: italic; margin-bottom:0; margin-top:0} ! h2.title {font-size: 120%; padding: 0.2ex; border: 1px solid gray; margin-top: 0.5ex; margin-bottom: 0; top: -1px; position: relative} h3.title {font-size: 110%; margin-bottom: 0} h3.author {display: none; margin-bottom:0ex; margin-top:1ex; font-size: 100%} --- 15,19 ---- body>div>div.section {margin-left:22ex; margin-bottom: 3ex} h1.title {position: absolute; top: 1ex; padding-top: 40px; left: 140px; display: inline; font-size: 180%; font-style: italic; margin-bottom:0; margin-top:0} ! h2.title {font-size: 120%; padding: 0.2ex; border: 1.09px solid gray; margin-top: 0.5ex; margin-bottom: 0; top: -1px; position: relative} h3.title {font-size: 110%; margin-bottom: 0} h3.author {display: none; margin-bottom:0ex; margin-top:1ex; font-size: 100%} |
From: <luc...@us...> - 2003-05-06 17:36:43
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv27970 Modified Files: qcop.py Log Message: Added timeout for connecting to the Zaurus (5 seconds hard-coded for now) Index: qcop.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/qcop.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** qcop.py 19 Mar 2003 05:02:32 -0000 1.1 --- qcop.py 6 May 2003 17:36:37 -0000 1.2 *************** *** 22,26 **** # $Id$ ! import socket,sys,re,string CRLF = "\r\n" --- 22,26 ---- # $Id$ ! import socket,sys,re,string,struct,select CRLF = "\r\n" *************** *** 166,170 **** # TODO: determine how to have the connect call time out self.zsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ! self.zsock.connect((self.remotehost, self.remoteport)) # retain the banner... it's useful debug info self.banner = self.zsock.recv(READSIZE) --- 166,190 ---- # TODO: determine how to have the connect call time out self.zsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ! # the following was adapted from a posting on comp.lang.python ! # by Jeff Blaine <jb...@sh...> ! try: ! self.zsock.setblocking(0) ! ret = self.zsock.connect_ex((self.remotehost, self.remoteport)) ! xx, xxx, xxxx = (None, None, None) ! if ret == 36: ! xx, xxx, xxxx = select.select([], [self.zsock], [], 5.0) ! else: ! raise QCOPError, "cannot connect" ! if not xx and not xxx and not xxxx: ! raise QCOPError, "timeout occured" ! self.zsock.setblocking(1) ! except Exception, msg: ! try: ! self.zsock.close() ! except: ! pass ! print msg ! raise ! # self.zsock.connect((self.remotehost, self.remoteport)) # retain the banner... it's useful debug info self.banner = self.zsock.recv(READSIZE) |
From: <luc...@us...> - 2003-05-06 17:34:46
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv27217 Modified Files: zaurusplugin.py Log Message: - Made defaults for the settings work (resulted in exceptions before) - Added support for context objects Index: zaurusplugin.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zaurusplugin.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** zaurusplugin.py 5 May 2003 06:37:21 -0000 1.4 --- zaurusplugin.py 6 May 2003 17:34:43 -0000 1.5 *************** *** 36,49 **** """Initialize fields in Zaurus object""" Device.__init__(self,zsettings) ! self.ip_address = zsettings["ip_address"] ! self.qcop_port = zsettings["qcop_port"] or 4243 ! self.ftp_port = zsettings["ftp_port"] or 4242 ! self.user = zsettings["user"] or "root" ! self.password = zsettings["password"] or "notused" # category mapping should be a dictionary mapping text values to # category names on the zaurus... e.g. categoryMap['Home'] = "Personal" # ultimately, this should be configurable on the UI ! self.categoryMap = zsettings["categoryMapping"] or None ! self.defaultCategory = zsettings["defaultCategory"] or None def probe(self): --- 36,70 ---- """Initialize fields in Zaurus object""" Device.__init__(self,zsettings) ! try: ! self.ip_address = zsettings["ip_address"] ! except KeyError: ! self.ip_address = "192.168.129.201" ! try: ! self.qcop_port = zsettings["qcop_port"] ! except KeyError: ! self.qcop_port = 4243 ! try: ! self.ftp_port = zsettings["ftp_port"] ! except KeyError: ! self.ftp_port = 4242 ! try: ! self.user = zsettings["user"] ! except KeyError: ! self.user = "root" ! try: ! self.password = zsettings["password"] ! except KeyError: ! self.password = "notused" # category mapping should be a dictionary mapping text values to # category names on the zaurus... e.g. categoryMap['Home'] = "Personal" # ultimately, this should be configurable on the UI ! try: ! self.categoryMap = zsettings["categoryMapping"] ! except KeyError: ! self.categoryMap = None ! try: ! self.defaultCategory = zsettings["defaultCategory"] ! except KeyError: ! self.defaultCategory = None def probe(self): *************** *** 64,68 **** return 1 ! def init(self): """Initiate a QCOP connection and get handshake and sync info""" try: --- 85,89 ---- return 1 ! def init(self, context): """Initiate a QCOP connection and get handshake and sync info""" try: *************** *** 116,120 **** # assume settings is a list of dictionaries for now... # one dictionary per device ! def probe( settings ): """return a list of Device objects --- 137,141 ---- # assume settings is a list of dictionaries for now... # one dictionary per device ! def probe( settings, context ): """return a list of Device objects |
From: <luc...@us...> - 2003-05-06 17:32:18
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus In directory sc8-pr-cvs1:/tmp/cvs-serv25957 Modified Files: zauruscalendar.py Log Message: Make the API more consistent (readAll -> readAllEntries) Index: zauruscalendar.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/zauruscalendar.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** zauruscalendar.py 5 May 2003 06:37:21 -0000 1.1 --- zauruscalendar.py 6 May 2003 17:32:13 -0000 1.2 *************** *** 68,72 **** self.zaurus.qcopConn.send(stopSync) ! def readAll(self): """Return all entries""" entries = [] --- 68,72 ---- self.zaurus.qcopConn.send(stopSync) ! def readAllEntries(self): """Return all entries""" entries = [] |
From: <luc...@us...> - 2003-05-06 17:31:27
|
Update of /cvsroot/zxsync/zXSync/plugins In directory sc8-pr-cvs1:/tmp/cvs-serv25570 Modified Files: caltest.py Log Message: Make the API more consistent (readAll -> readAllEntries) Index: caltest.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/caltest.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** caltest.py 5 May 2003 06:45:12 -0000 1.4 --- caltest.py 6 May 2003 17:31:24 -0000 1.5 *************** *** 79,83 **** print "Attempting sync operation..." app.beginSync() ! events = app.readAll() app.endSync() except: --- 79,83 ---- print "Attempting sync operation..." app.beginSync() ! events = app.readAllEntries() app.endSync() except: |
From: <luc...@us...> - 2003-05-06 17:28:24
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv24157 Modified Files: vevent.py Log Message: Fixed obvious typo Index: vevent.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/vevent.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** vevent.py 5 May 2003 06:40:49 -0000 1.1 --- vevent.py 6 May 2003 17:28:21 -0000 1.2 *************** *** 165,169 **** # be needed. (AFAICT, the devices discard enough information that a # table of matching UIDs might be the only way to go.) ! return(self.getField("UID") == none) def matches(self,other): --- 165,169 ---- # be needed. (AFAICT, the devices discard enough information that a # table of matching UIDs might be the only way to go.) ! return(self.getField("UID") != None) def matches(self,other): |
From: <luc...@us...> - 2003-05-06 17:26:58
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv23499 Modified Files: engine.py Log Message: - Fixed a bug when finding entries to add (entries from different apps got mixed up) - Fixed a typo (writeAll -> writeAllEntries) Index: engine.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/zxsync/engine.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** engine.py 4 May 2003 20:17:28 -0000 1.3 --- engine.py 6 May 2003 17:26:55 -0000 1.4 *************** *** 341,354 **** """ retVal = [] ! for deviceInfo in self.devices: ! for syncApp in deviceInfo.data: ! for entry in syncApp.getChildren(): ! matched = 0 ! for providedEntry in entries: ! if providedEntry.matches(entry): ! matched = 1 ! break ! if not matched: ! retVal.append(entry) return retVal --- 341,359 ---- """ retVal = [] ! if len(entries) > 0: ! appId = entries[0].getParent().getId() ! for deviceInfo in self.devices: ! for syncApp in deviceInfo.data: ! if syncApp.getId() == appId: ! for entry in syncApp.getChildren(): ! syncMode = entry.getSyncMode() ! if syncMode == syncbase.SYNC_FROM or syncMode == syncbase.SYNC_BOTH: ! matched = 0 ! for providedEntry in entries: ! if providedEntry.matches(entry): ! matched = 1 ! break ! if not matched: ! retVal.append(entry) return retVal *************** *** 399,403 **** syncApp.getSource().addEntry(entry) else: ! syncApp.getSource().writeAll(syncApp.getChildren()) except: globalContext.fatalDefault = oldFatalDefault --- 404,408 ---- syncApp.getSource().addEntry(entry) else: ! syncApp.getSource().writeAllEntries(syncApp.getChildren()) except: globalContext.fatalDefault = oldFatalDefault |
From: <gb...@us...> - 2003-05-05 06:45:16
|
Update of /cvsroot/zxsync/zXSync/plugins In directory sc8-pr-cvs1:/tmp/cvs-serv30737 Modified Files: caltest.py Log Message: for now, an "identity function" to test z datebook functionality Index: caltest.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/caltest.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** caltest.py 3 Apr 2003 00:31:05 -0000 1.3 --- caltest.py 5 May 2003 06:45:12 -0000 1.4 *************** *** 22,25 **** --- 22,26 ---- import os, sys + # a real "core" engine will need to make sure the "plugins" package # is in the path so that plugins can find base classes, etc. *************** *** 42,51 **** module = __import__(modname, globals(), locals(), ["probe"]) moduleDevices = module.__dict__["probe"](settings) ! print "Found", len(moduleDevices), "device(s) in", modname except Exception, msg: # insert some specific error handling here later; # for now, we assume that a failure means that # we tried to load something that isn't a plugin ! # print msg pass --- 43,52 ---- module = __import__(modname, globals(), locals(), ["probe"]) moduleDevices = module.__dict__["probe"](settings) ! #print "Found", len(moduleDevices), "device(s) in", modname except Exception, msg: # insert some specific error handling here later; # for now, we assume that a failure means that # we tried to load something that isn't a plugin ! print str(file) + ": " + str(msg) pass *************** *** 54,61 **** from zaurus.zaurusplugin import * ! goodsettings = {'ip_address':"192.168.129.201",'qcop_port':4243, 'ftp_port':4242,'user':"root",'password':"rootme", ! 'config_name':"Good Zaurus"} settingslist = [goodsettings] devices = probe(settingslist) --- 55,65 ---- from zaurus.zaurusplugin import * ! from zxsync import syncbase ! # a dictionary mapping ical calendar files to zaurus category names ! categoryDict = None goodsettings = {'ip_address':"192.168.129.201",'qcop_port':4243, 'ftp_port':4242,'user':"root",'password':"rootme", ! 'config_name':"Good Zaurus", 'categoryMapping':categoryDict, ! 'defaultCategory':None} settingslist = [goodsettings] devices = probe(settingslist) *************** *** 70,82 **** device.init() apps = device.getApplications() ! (calid,caltype) = apps[0] ! print "Found application " + calid ! device.beginSync( calid ) ! print device.readAll(calid) ! device.endSync(calid) except: print "Failed." raise ! print "Connected successfully." device.free() print "Zaurus Test Script finished normally." --- 74,98 ---- device.init() apps = device.getApplications() ! for app in apps: ! print "Found application with " + app.getId() ! if( app.getId() == syncbase.CALENDAR_APP_ID ): ! print "Attempting sync operation..." ! app.beginSync() ! events = app.readAll() ! app.endSync() except: print "Failed." raise ! print "Got events successfully." ! #for event in events: ! # print "BEGIN:VEVENT\n" + str(event) + "END:VEVENT" ! #apps = device.getApplications() ! # essentially behave as an identity function to make sure we're not destroying data on the z... ! for app in apps: ! if( app.getId() == syncbase.CALENDAR_APP_ID ): ! print "Attempting write operation..." ! app.beginSync() ! app.writeAllEntries(events) ! app.endSync() device.free() print "Zaurus Test Script finished normally." |
From: <gb...@us...> - 2003-05-05 06:40:52
|
Update of /cvsroot/zxsync/zXSync/zxsync In directory sc8-pr-cvs1:/tmp/cvs-serv28864 Added Files: vevent.py Log Message: enough of a vevent class to support ical and zaurus plugins --- NEW FILE: vevent.py --- #!/usr/bin/env python # # a zaurus calendar class for zXSync # # Copyright (C) 2003 Geoff Beier <ge...@mo...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # $Id: vevent.py,v 1.1 2003/05/05 06:40:49 gbeier Exp $ from syncbase import Entry from syncbase import Field # a list of standard-ish fields for printing a rep. plugins can use their own list STANDARD_FIELDS = [ "SEQUENCE","DTSTAMP","SUMMARY","RRULE","DTSTART","DTEND","STATUS","UID","DESCRIPTION"] # string constants for repeat rules YEARLY="YEARLY" MONTHLY="MONTHLY" WEEKLY="WEEKLY" DAILY="DAILY" class VEventField(Field): """a Field class that can handle properties as specified in RFC 2445""" def __init__(self, id = None, value = None, properties = {}): """ Initializes this field. """ self.properties = properties Field.__init__(self, id, value) def doClone(self, other): """ deep copy self to other and return other """ Field.doClone(self, other) for key in self.properties.keys(): other.properties[key] = self.properties['key'] return other def clone(self): """ Clone implementation for this class. """ return self.doClone(VEventField()) def getProperties(self): """ Returns properties Dictionary for this field """ return self.properties def getProperty(self,propName): """ Return the value for a particular property """ if( self.properties.has_key(propName) ): return self.properties[propName] else: return None def __repr__(self): #print "!!!__repr__" if self.properties != None: # XXX TODO: Consider sorting stringRep = self.id for key in self.properties.keys(): stringRep += ";" + key + "=" + vCalEscape(self.properties[key]) stringRep += ":" + vCalEscape(self.value) return stringRep else: return self.id + ":" + vCalEscape(self.value) def vCalEscape( text ): """ Escape text as required by rfc 2445 """ # XXX: Not implemented yet return text def vCalUnescape( text ): """ Unescape text that is already proprly escaped per rfc 2445 """ # XXX: Not implemented yet. return text class VEvent(Entry): """represents a vEvent entry on a vCalendar""" def __init__(self,id): Entry.__init__(self, id) self.addField("UID",id) def addField(self,fieldName,value): self.addChild( VEventField(fieldName,value) ) def replaceField(self,fieldName,value): self.replaceChild( VEventField(fieldName,value) ) def getField(self,fieldName): field = self.getChildWithId(fieldName) if( field ): return field.getValue() else: return None def setFieldProperty(self,fieldName,propertyName, propertyVal): """ set a property key/val pair for the first specified child field """ field = self.getChildWithId(fieldName) if( field ): field.setProperty(propertyName,propertyVal) else: field = VEventField( fieldName, None ) field.setProperty(propertyName,propertyVal) self.addChild(field) def addFieldWithProperties( self, fieldName, fieldValue, properties ): """ add a child field with the specified properties dictionary """ self.addChild(VEventField(fieldName,fieldValue,properties)) def getFieldProperty(self,field,propertyName): """ get the specified property value from the specified field """ field = self.getChildWithId(field) if( field ): return field.getProperty(propertyName) else: return None def deleteField(self,fieldName): self.removeChildWithId(fieldName) def clone(self): """ Clone implementation for this class. """ return self.doClone(VEvent()) def isValid(self): """ Can this match another entry? """ # The only field that can really be used to match a VEvent is its # UID. If devices mangle each others' UIDs, a fallback strategy will # be needed. (AFAICT, the devices discard enough information that a # table of matching UIDs might be the only way to go.) return(self.getField("UID") == none) def matches(self,other): """ Does this vEvent match another """ return( self.getField("UID") == other.getField("UID") ) def __repr__(self): """ Produce a reasonably standard vEvent """ rep = "" for field in STANDARD_FIELDS: vEventField = self.getChildWithId(field) # the RFC specifies CRLF line endings if vEventField: rep += str(vEventField)+"\r\n" return rep |
From: <gb...@us...> - 2003-05-05 06:38:57
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv28166 Modified Files: datebook.py Log Message: initial rudimentary zaurus datebook support Index: datebook.py =================================================================== RCS file: /cvsroot/zxsync/zXSync/plugins/zaurus/util/datebook.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** datebook.py 24 Mar 2003 03:50:48 -0000 1.3 --- datebook.py 5 May 2003 06:38:54 -0000 1.4 *************** *** 22,30 **** import qcop ! import ftplib,tempfile ! ! from xml.dom.minidom import parse ! datebookdir = "Applications/datebook" --- 22,32 ---- import qcop ! import zaurusutils import ftplib,tempfile ! import time ! import string, re ! from zxsync import vevent ! # Bring a very heavily used function into our namespace ! from zaurusutils import zaurusEscape datebookdir = "Applications/datebook" *************** *** 32,35 **** --- 34,50 ---- tempfilename = "" + # string constants for Zaurus frequencies + YEARLY="Yearly" + MONTHLYDAY="MonthlyDay" + MONTHLYDATE="MonthlyDate" + WEEKLY="Weekly" + DAILY="Daily" + + # ics days + DAYS = [ "SU", "MO", "TU", "WE", "TH", "FR", "SA" ] + + # starting zaurus record id... for some reason, not 0 :-) + RID_START = 10 + # declare a type for datebook exceptions class DatebookError( Exception ): *************** *** 37,42 **** def readDatebook( zaurus ): ! """Read all Datebook entries from the z""" conn = ftplib.FTP() try: --- 52,84 ---- + def writeDatebook( zaurus, xmlFile ): + """ + write the supplied temporary file to the zaurus datebook + """ + conn = ftplib.FTP() + try: + conn.connect( zaurus.ip_address, zaurus.ftp_port ) + conn.login( zaurus.user, zaurus.password ) + except Exception, e: + raise DatebookError( "writeDatebook(): error connecting to Zaurus: " + str(e) ) + try: + file = open( xmlFile, "rb" ) + except Exception, e: + conn.quit() + raise DatebookError( "writeDatebook(): error opening temp file: " + str(e) ) + try: + conn.storbinary( "STOR " + zaurus.homedir + "/" + datebookdir + "/" + datebookfile, file ) + except Exception, e: + print e + conn.quit() + raise DatebookError( "writeDatebook(): error putting file: " + str(e) ) + file.close + try: + conn.quit() + except Exception, e: + conn.close() + def readDatebook( zaurus ): ! """Read all Datebook entries from the z, and return them as a list of dictionaries""" conn = ftplib.FTP() try: *************** *** 68,71 **** caldata = file.read() file.close() ! return caldata --- 110,303 ---- caldata = file.read() file.close() ! return zaurusutils.xml2dictlist(caldata,"event") ! ! def unixToICALTime( secs ): ! """ ! Format a unix timestamp (from the z) as an ICAL DT field ! Assumes that times coming from the Z are in the local timezone. That is unfortunate, ! but the Z discards timezone information. ! """ ! return time.strftime("%Y%m%dT%H%M%SZ",time.localtime(int(secs))) ! ! def icalToUnixTime( timestamp ): ! """ ! Get a unix timestamp from an ICAL DT field. ! Assume it's local. ! """ ! if( (len(timestamp)-1) != timestamp.rfind("Z") ): ! timestamp += "Z" ! rv = "" ! try: ! parsed = time.strptime(timestamp,"%Y%m%dT%H%M%SZ") ! rv = int(time.mktime(parsed)) ! except ValueError, e: ! try: ! # maybe it was just a date... try that before dying ! parsed = time.strptime(timestamp,"%Y%m%dZ") ! rv = int(time.mktime(parsed)) ! except ValueError, e: ! raise e ! if( time.localtime()[8] == 1 ): ! # make sure strptime was parsed according to the current localtime ! rv -= 60*60 ! return str(rv) ! ! def unixToICALDate( secs ): ! """ ! Format a unix timestamp (from the z) as an ICAL date-only DT field ! Assumes that times coming from the Z are in the local timezone. ! """ ! return time.strftime("%Y%m%d",time.localtime(int(secs))) ! ! ! def getDay( secs ): ! """Return the day of the week in ics form""" ! return DAYS[int(time.strftime("%w",time.localtime(int(secs))))] ! ! def addDuration( start, duration ): ! """ ! add a duration to a start time... return the number of seconds ! """ ! # XXX TODO: make this robust... right now it only handles a few values we're certain ! # to encounter ! timeVal = 0 ! pattern = None ! if( -1 != duration.find("PT") ): ! # we're dealing with a period of time, not days ! timeVal = 1 ! pattern = re.compile("PT(\d+)(\S)") ! else: ! pattern = re.compile("P(\d+)(\S)") ! matcher = pattern.match(duration) ! interval = int(matcher.group(1)) ! units = matcher.group(2) ! if( units == "D" ): ! # 60*60*24 seconds in a day... no leap seconds are used :-) ! return str( int(start) + (interval*24*60*60) ) ! if( units == "M" ): ! # I haven't seen months, but I'm not sure we wont and wan't an exception if we do. ! if( timeVal == 0 ): ! raise DatebookError("Durations of Months dont work right now.") ! # 60 seconds in a minute ! return str( int(start) + (interval*60)) ! if( units == "H" ): ! # 60*60 seconds in an hour ! return str( int(start) + (interval*60*60)) ! raise DatebookError("Duration was not parsed properly. Could not calculate end time.") ! ! def xmlFromICAL( entry, rid, zaurus ): ! """Return a zaurus-style XML entry from a representation of an icalendar entry""" ! uid = entry.getField("UID") ! startdt = entry.getField("DTSTART") ! # IllegalArgumentException ! if( not(uid) ): ! raise DatebookError("Cannot generate XML for an entry that does not contain a UID") ! if( not(startdt) ): ! raise DatebookError("Cannot generate XML for an entry that does not contain a start date/time") ! xmlEntry = "<event" ! summary = entry.getField("SUMMARY") ! if( summary ): ! xmlEntry += " description=\"" + summary + "\"" ! location = entry.getField("LOCATION") ! if( location ): ! xmlEntry += " location=\"" + location + "\"" ! # first try the zaurus category, then try to map the iCal category, then use the default ! # this doesn't look elegant, but it's because I don't know of any c-style assignment shortcut ! # and I wish to avoid multiple costly getField calls ! zcat = entry.getField("X-ZAURUS-CATEGORY") ! icalendar = None ! catField = None ! if( zcat ): ! catField = " categories=\"" + str(zaurus.categories[zcat]) + "\"" ! else: ! # XXX: TODO: make this field configurable ! icalendar = entry.getField("X-ICAL-CALENDAR") ! if( icalendar ): ! catField = " categories=\"" + str(zaurus.categories[zaurus.categoryMap[icalendar]]) + "\"" ! if( catField ): ! xmlEntry += catField ! else: ! if( zaurus.categories[zaurus.defaultCategory] != None ): ! xmlEntry += " categories=\"" + str(zaurus.categories[zaurus.defaultCategory]) + "\"" ! else: ! xmlEntry += " categories=\"\"" ! ! xmlEntry += " uid=\""+str(uid)+"\"" ! xmlEntry += " rid=\""+str(rid)+"\"" ! rinfo = entry.getField("X-ZAURUS-RINFO") ! if( rinfo ): ! xmlEntry += " rinfo=\"" + str( rinfo ) + "\"" ! else: ! # this field is very mysterious... I've seen values 0 - 3 with no apparent rhyme ! # or reason. grepping through QTopia sources is not informative. 1 seems like a safe ! # value for now. ! xmlEntry += " rinfo=\"1\"" ! duration = entry.getField("DURATION") ! if( duration == "P1D" ): ! # all day event ! xmlEntry += " type=\"AllDay\"" ! # XXX Alarm support goes here ! # XXX recurrence support goes here ! # XXX Find a better way to handle timezones-- currently assume all times are localtime ! startdt = icalToUnixTime(startdt) ! xmlEntry += " start=\"" + startdt + "\"" ! enddt = entry.getField("DTEND") ! if( not(enddt) ): ! # if there was no end time, parse the duration ! if( not(duration) ): ! raise DatebookError("An ical entry must have either an end time or a duration") ! enddt = addDuration( startdt, duration ) ! else: ! enddt = icalToUnixTime(enddt) ! xmlEntry += " end=\"" + enddt + "\"" ! xmlEntry += " />\n" ! return xmlEntry + def zToICALFreq( entry ): + """ + Build an icalendar repeat rule from zaurus frequencies + """ + if( not(entry.has_key('rtype')) or (entry['rtype'] == "NoRepeat") ): + return None + rrule = None + if( entry['rtype'] == YEARLY ): + # the zaurus only supports yearly events like + # "Every January 3rd", not "The first Monday of January" + rrule = "FREQ=" + vevent.YEARLY + if( entry['rhasenddate'] == "1" ): + rrule += ";UNTIL=" + unixToICALTime( entry['enddt'] ) + rrule += ";INTERVAL=" + entry['rfreq'] + # get the month and kill any leading 0 + rrule += ";BYMONTH=" + str(int(time.strftime("%m",time.localtime(int(entry['start']))))) + return rrule + if( entry['rtype'] == MONTHLYDAY ): + # one quirk of the z is that it will indeed schedule stuff on the 5th X of a month... + # other apps might not like that and should filter accordingly + rrule = "FREQ=" + vevent.MONTHLY + if( entry['rhasenddate'] == "1" ): + rrule += ";UNTIL=" + unixToICALTime( entry['enddt'] ) + rrule += ";INTERVAL=" + entry['rfreq'] + rrule += ";BYDAY=" + entry['rposition'] + getDay(entry['start']) + return rrule + if( entry['rtype'] == MONTHLYDATE ): + rrule = "FREQ=" + vevent.MONTHLY + if( entry['rhasenddate'] == "1" ): + rrule += ";UNTIL=" + unixToICALTime( entry['enddt'] ) + rrule += ";INTERVAL=" + entry['rfreq'] + # get the day of the month and kill the leading 0 + rrule += ";BYMONTHDAY=" + str(int(time.strftime("%d",time.localtime(int(entry['start']))))) + if( entry['rtype'] == WEEKLY ): + rrule = "FREQ=" + vevent.WEEKLY + if( entry['rhasenddate'] == "1" ): + rrule += ";UNTIL=" + unixToICALTime( entry['enddt'] ) + rrule += ";INTERVAL=" + entry['rfreq'] + rrule += ";BYDAY=" + entry['rposition'] + getDay(entry['start']) + if( entry['rtype'] == DAILY ): + rrule = "FREQ=" + vevent.DAILY + if( entry['rhasenddate'] == "1" ): + rrule += ";UNTIL=" + unixToICALTime( entry['enddt'] ) + rrule += ";INTERVAL=" + entry['rfreq'] + return rrule + # don't write a repeat rule if we didn't recognize the repeat type + return rrule + |
From: <gb...@us...> - 2003-05-05 06:38:26
|
Update of /cvsroot/zxsync/zXSync/plugins/zaurus/util In directory sc8-pr-cvs1:/tmp/cvs-serv27985 Added Files: zaurusutils.py Log Message: some generally useful functions for the z --- NEW FILE: zaurusutils.py --- #!/usr/bin/env python # # Utility functions that are useful across the different Z apps # # Copyright (C) 2003 Geoff Beier <ge...@mo...> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: zaurusutils.py,v 1.1 2003/05/05 06:38:23 gbeier Exp $ import ftplib,tempfile import string,re # TODO: Move these strings elsewhere categoriesLoc = "Settings" categoriesFile = "Categories.xml" class ZaurusUtilError(Exception): """A dummy exception to make it easier to trap and handle errors from this module""" pass def zaurusEscape( text ): """Escapes the text for zaurus-style XML""" ### XXX:Not implemented yet return text def zaurusUnescape( text ): """ Unescapes the supplied text from the Zaurus Assumes that it is properly escaped in the first place """ # XXX:Not implemented yet return text def getCategories(zaurus): """ Read the category list from the Z and return a dictionary. This list will be so small, categories will simply be double-mapped, e.g. categories['foo'] = -12345 categories['-12345'] = foo """ # pull the XML file defining categories for all apps that use them on the Z ftpconn = ftplib.FTP() try: ftpconn.connect( zaurus.ip_address, zaurus.ftp_port ) ftpconn.login( zaurus.user, zaurus.password ) except Exception, e: raise ZaurusUtilError( "getCategories(): error connecting to Zaurus: " + str(e) ) try: tempfilename = tempfile.mktemp() file = open( tempfilename, "wb" ) except Exception, e: ftpconn.quit() raise ZaurusUtilError( "getCategories(): error creating temporary file " + tempfilename + ": " + str(e) ) try: ftpconn.retrbinary( "RETR " + zaurus.homedir + "/" + categoriesLoc + "/" + categoriesFile, file.write ) except Exception, e: ftpconn.quit() raise ZaurusUtilError( "getCategories(): error saving categories to temporary file: " + str(e) ) file.close() try: ftpconn.quit() except: ftpconn.close() try: file = open( tempfilename, "r" ) except Exception, e: raise ZaurusUtilError( "readDatebook(): error opening saved datebook: " + str(e) ) categoriesXML = file.read() file.close() categoryEntries = xml2dictlist(categoriesXML,"Category"); categories = {} for catDict in categoryEntries: categories[catDict['id']] = catDict['name'] categories[catDict['name']] = catDict['id'] # give the dictionary an identity entry categories[None] = None return categories def xml2dictlist( xml, entityName ): """ A utility function to convert a bunch of XML to a list of dictionaries based on entityName. Most of the angle-bracket nastiness for reading from the Z is confined here. So starting with the XML file: <Categories> <Category id="1" name="Business" /> <Category id="2" name="Personal" /> </Categories> xml2dictlist("Category") will return: [{'id':'1','name':'Business'},{'id':'2','name':'Personal'}] but xml2dictlist("Entry") would return an empty list. The Z uses XML files like this in many places. """ dictList = [] entries = [] entrylines = string.split(xml,"<"+entityName) # get a list of strings of the type key1="value1" key2="value2" key3="value3" # with the whitespace trimmed # A single space is tacked onto the end to enable us to use split rather than # a costlier regex below for line in entrylines: end = string.rfind(line,"/>") if( end > -1 ): entries.append(string.strip(line[0:end]) + " ") # parse the entry into a dictionary and add it to the list for entry in entries: items = string.split(entry, "\" ") entryDict = {} for pair in items: # the last one will be blank... ignore it if(pair): key,value = string.split(pair,"=\"") entryDict[key] = zaurusUnescape(value) dictList.append(entryDict) return dictList |