Initial import of Bongo source code.
This commit is contained in:
@@ -0,0 +1,831 @@
|
||||
import logging
|
||||
from CommandStream import *
|
||||
from StoreConnection import StoreConnection
|
||||
from cStringIO import StringIO
|
||||
import bongo
|
||||
import re
|
||||
import time
|
||||
import random
|
||||
import md5
|
||||
import socket
|
||||
|
||||
class DocTypes:
|
||||
Unknown = 0x0001
|
||||
Mail = 0x0002
|
||||
Event = 0x0003
|
||||
Addressbook = 0x0004
|
||||
Conversation = 0x0005
|
||||
Calendar = 0x0006
|
||||
|
||||
Folder = 0x1000
|
||||
Shared = 0x2000
|
||||
SharedFolder = Folder | Shared
|
||||
Purged = 0x4000
|
||||
|
||||
class DocFlags:
|
||||
Purged = (1 << 0)
|
||||
Seen = (1 << 1)
|
||||
Answered = (1 << 2)
|
||||
Flagged = (1 << 3)
|
||||
Deleted = (1 << 4)
|
||||
Draft = (1 << 5)
|
||||
Recent = (1 << 6)
|
||||
Junk = (1 << 7)
|
||||
Sent = (1 << 8)
|
||||
|
||||
Starred = (3 << 16)
|
||||
|
||||
names = {
|
||||
Purged : "purged",
|
||||
Seen : "read",
|
||||
Answered : "answered",
|
||||
Flagged : "flagged",
|
||||
Deleted : "deleted",
|
||||
Draft : "draft",
|
||||
Recent : "recent",
|
||||
Junk : "junk",
|
||||
Sent : "sent",
|
||||
Starred : "starred"
|
||||
}
|
||||
|
||||
# reverse the names hash so we can look up flags by name
|
||||
revNames = {}
|
||||
for name, flag in names.items():
|
||||
revNames[flag] = name
|
||||
|
||||
# some helpful functions
|
||||
def GetName(flag):
|
||||
return DocFlags.names[flag]
|
||||
GetName = staticmethod(GetName)
|
||||
|
||||
def ByName(name):
|
||||
return DocFlags.revNames[name]
|
||||
ByName = staticmethod(ByName)
|
||||
|
||||
def AllFlags():
|
||||
return DocFlags.names.keys()
|
||||
AllFlags = staticmethod(AllFlags)
|
||||
|
||||
def GetMask(hash):
|
||||
flags = mask = 0
|
||||
|
||||
for flag, status in hash.items():
|
||||
if status:
|
||||
flags = flags | flag
|
||||
mask = mask | flag
|
||||
|
||||
return flags, mask
|
||||
GetMask = staticmethod(GetMask)
|
||||
|
||||
class FlagMode:
|
||||
Show = 0
|
||||
Add = 1
|
||||
Remove = 2
|
||||
Replace = 3
|
||||
|
||||
class ACL :
|
||||
def __init__(self, acl = None) :
|
||||
self.entries = []
|
||||
|
||||
if acl :
|
||||
split = acl.split(';')
|
||||
for entry in split :
|
||||
if entry == '' :
|
||||
continue
|
||||
|
||||
tmp = re.split('\s+', entry)
|
||||
self.entries.append((tmp[0], tmp[1], tmp[2]))
|
||||
self.changed = False
|
||||
|
||||
def __str__(self) :
|
||||
acl = ''
|
||||
for entry in self.entries :
|
||||
acl = acl + "%s %s %s;" % entry
|
||||
return acl
|
||||
|
||||
def Clear(self) :
|
||||
if (self.entries != []) :
|
||||
self.entries = []
|
||||
self.changed = True
|
||||
|
||||
def Grant(self, principal, priv) :
|
||||
newEntry = ("grant", principal, priv)
|
||||
for entry in self.entries :
|
||||
if entry == newEntry :
|
||||
return
|
||||
|
||||
self.changed = True
|
||||
self.entries.append(newEntry)
|
||||
|
||||
def AddEntries(self, entries) :
|
||||
self.changed = True
|
||||
self.entries.extend(entries)
|
||||
|
||||
def Revoke(self, principal, priv) :
|
||||
self.RevokeEntry(("grant", principal, priv))
|
||||
|
||||
def RevokeEntry(self, revokeEntry) :
|
||||
newEntries = []
|
||||
for entry in self.entries :
|
||||
if entry != revokeEntry :
|
||||
newEntries.append(entry)
|
||||
else :
|
||||
self.changed = True
|
||||
|
||||
self.entries = newEntries
|
||||
|
||||
def RevokeEntries(self, entries) :
|
||||
for entry in entries :
|
||||
self.RevokeEntry(entry)
|
||||
|
||||
class CalendarACL :
|
||||
class Rights :
|
||||
Read = (1 << 0)
|
||||
Write = (1 << 1)
|
||||
ReadProps = (1 << 2)
|
||||
|
||||
def __init__(self, acl) :
|
||||
self.acl = acl
|
||||
self.summary = None
|
||||
|
||||
def __str__(self) :
|
||||
return str(self.acl)
|
||||
|
||||
def GetACL(self) :
|
||||
return self.acl
|
||||
|
||||
def _GetUid (self, *args):
|
||||
t = long(time.time() * 1000)
|
||||
r = long(random.random() * 100000000000000000L)
|
||||
try:
|
||||
a = socket.gethostbyname(socket.gethostname())
|
||||
except:
|
||||
# if we can't get a network address, just imagine one
|
||||
a = random.random() * 100000000000000000L
|
||||
data = str(t) + ' ' + str (r) + ' ' + str(a) + ' ' + str(args)
|
||||
data = md5.md5(data).hexdigest()
|
||||
return data
|
||||
|
||||
|
||||
def _GetRights(self, name) :
|
||||
rights = 0
|
||||
if name == "read" :
|
||||
rights = rights | CalendarACL.Rights.Read
|
||||
elif name == "write" :
|
||||
rights = rights | CalendarACL.Rights.Write
|
||||
elif name == "read-props" :
|
||||
rights = rights | CalendarACL.Rights.ReadProps
|
||||
return rights
|
||||
|
||||
def RightsToString(self, rights) :
|
||||
names = []
|
||||
if rights == 0 :
|
||||
return "none"
|
||||
if rights & CalendarACL.Rights.Read :
|
||||
names.append("read")
|
||||
if rights & CalendarACL.Rights.Write :
|
||||
names.append("write")
|
||||
if rights & CalendarACL.Rights.ReadProps :
|
||||
names.append("read-props")
|
||||
return ", ".join(names)
|
||||
|
||||
|
||||
def SetPublic(self, rights) :
|
||||
self.summary = None
|
||||
entries = self._Find("all")
|
||||
if (entries) :
|
||||
self.acl.RevokeEntries(entries)
|
||||
if (rights & CalendarACL.Rights.Read) :
|
||||
self.acl.Grant("all", "read")
|
||||
if (rights & CalendarACL.Rights.Write) :
|
||||
self.acl.Grant("all", "write")
|
||||
if (rights & CalendarACL.Rights.ReadProps) :
|
||||
self.acl.Grant("all", "read-props")
|
||||
|
||||
def GetPublic(self) :
|
||||
entries = self._Find("all")
|
||||
rights = 0
|
||||
for entry in entries :
|
||||
rights = rights | self._GetRights(entry[2])
|
||||
return rights
|
||||
|
||||
def AddPassword(self, user, password, rights) :
|
||||
self.summary = None
|
||||
if (rights & CalendarACL.Rights.Read) :
|
||||
self.acl.Grant("token:pw:" + user + ":" + password, "read")
|
||||
if (rights & CalendarACL.Rights.Write) :
|
||||
self.acl.Grant("token:pw:" + user + ":" + password, "write")
|
||||
|
||||
def CheckPassword(self, user, password) :
|
||||
entries = self._Find("token:pw:" + user + ":" + password)
|
||||
if entries :
|
||||
return True
|
||||
else :
|
||||
return False
|
||||
|
||||
def HasPassword(self, user = None) :
|
||||
entries = self._FindPasswords()
|
||||
if entries :
|
||||
return True
|
||||
else :
|
||||
return False
|
||||
|
||||
def RemovePassword(self, user, password) :
|
||||
self.summary = None
|
||||
self.acl.RemoveEntries(self._Find("token:pw:" + user + ":" + password))
|
||||
|
||||
def RemovePasswords(self) :
|
||||
self.summary = None
|
||||
self.acl.RemoveEntries(self._FindPasswords())
|
||||
|
||||
def GetPasswords(self) :
|
||||
entries = self._FindPasswords()
|
||||
ret = {}
|
||||
for entry in entries :
|
||||
split = entry[1].split(":")
|
||||
ret[split[2]] = split[3]
|
||||
|
||||
return ret
|
||||
|
||||
def Share(self, address, rights, password = None) :
|
||||
self.summary = None
|
||||
entries = self._FindAddress(address)
|
||||
|
||||
if (entries) :
|
||||
if not password :
|
||||
token = entries[0][1]
|
||||
else :
|
||||
token = "token:email:%s:%s" % (address, password)
|
||||
|
||||
self.acl.RevokeEntries(entries)
|
||||
else :
|
||||
if not password :
|
||||
password = self._GetUid()
|
||||
token = "token:email:%s:%s" % (address, password)
|
||||
|
||||
if (rights & CalendarACL.Rights.Read) :
|
||||
self.acl.Grant(token, "read")
|
||||
if (rights & CalendarACL.Rights.Write) :
|
||||
self.acl.Grant(token, "write")
|
||||
if (rights & CalendarACL.Rights.ReadProps) :
|
||||
self.acl.Grant(token, "read-props")
|
||||
|
||||
return token[len("token:"):]
|
||||
|
||||
def Unshare(self, address) :
|
||||
entries = self._FindAddress(address)
|
||||
if (entries) :
|
||||
self.acl.RevokeEntries(entries)
|
||||
|
||||
def GetAddressToken(self, address) :
|
||||
entries = self._FindAddress(address)
|
||||
token = entries[0][1]
|
||||
return token[len("token:"):]
|
||||
|
||||
def UnshareAll(self) :
|
||||
rights = self.GetPublic()
|
||||
self.acl.Clear()
|
||||
self.SetPublic(rights)
|
||||
|
||||
def Clear(self) :
|
||||
self.acl.Clear()
|
||||
|
||||
def Summarize(self) :
|
||||
if self.summary :
|
||||
return self.summary
|
||||
|
||||
public = 0
|
||||
addresses = {}
|
||||
passwords = {}
|
||||
|
||||
for entry in self.acl.entries :
|
||||
principal = entry[1]
|
||||
rights = self._GetRights(entry[2])
|
||||
|
||||
if principal == "all" :
|
||||
public = public | rights
|
||||
elif principal.startswith("token:email:") :
|
||||
remaining = principal[len("token:email:"):]
|
||||
split = remaining.split(':', 2)
|
||||
address = split[0]
|
||||
password = split[1]
|
||||
|
||||
if addresses.has_key(address) :
|
||||
entry = addresses[address]
|
||||
else :
|
||||
entry = { "password": password, "rights": 0 }
|
||||
addresses[address] = entry
|
||||
entry["token"] = principal[len("token:"):]
|
||||
entry["rights"] = entry["rights"] | rights
|
||||
elif principal.startswith("token:") :
|
||||
password = principal[len("token:"):]
|
||||
if (passwords.has_key(password)) :
|
||||
passwords[password] = passwords[password] | rights
|
||||
else :
|
||||
passwords[password] = rights
|
||||
|
||||
ret = {}
|
||||
ret["passwords"] = passwords
|
||||
ret["addresses"] = addresses
|
||||
ret["public"] = public
|
||||
self.summary = ret
|
||||
return ret
|
||||
|
||||
def _FindAddress(self, address) :
|
||||
"""Find acls with a given email token prefix"""
|
||||
ret = []
|
||||
for entry in self.acl.entries :
|
||||
if entry[1].startswith ("token:email:" + address + ":") :
|
||||
ret.append(entry)
|
||||
return ret
|
||||
|
||||
def _Find(self, principal) :
|
||||
"""Find acls with a given principal"""
|
||||
ret = []
|
||||
for entry in self.acl.entries :
|
||||
if entry[1] == principal :
|
||||
ret.append(entry)
|
||||
return ret
|
||||
|
||||
def _FindPasswords(self) :
|
||||
"""Find all password acls"""
|
||||
ret = []
|
||||
for entry in self.acl.entries :
|
||||
if entry[1].startswith("token:pw:") :
|
||||
ret.append(entry)
|
||||
return ret
|
||||
|
||||
class StoreClient:
|
||||
def __init__(self, user, owner, authToken=None, authCookie=None,
|
||||
authPassword=None):
|
||||
from bongo.libs import msgapi
|
||||
self.owner = self.user = None
|
||||
|
||||
addr = msgapi.FindUserNmap(owner)
|
||||
if addr is None:
|
||||
raise bongo.BongoError ("Could not look up nmap host for user %s" % owner)
|
||||
(host, port) = addr
|
||||
|
||||
if authCookie:
|
||||
self.connection = StoreConnection(host, port, systemAuth=False)
|
||||
if not self.connection.CookieAuth(user, authCookie):
|
||||
raise bongo.BongoError("Failed cookie authentication with store")
|
||||
elif authPassword:
|
||||
self.connection = StoreConnection(host, port, systemAuth=False)
|
||||
if not self.connection.UserAuth(user, authPassword):
|
||||
raise bongo.BongoError("Failed user authentication with store")
|
||||
else:
|
||||
self.connection = StoreConnection(host, port)
|
||||
|
||||
self.stream = self.connection.stream
|
||||
|
||||
# if we authed with a cookie or password, we don't need to USER
|
||||
if not authCookie and not authPassword and user is not None:
|
||||
self.User(user)
|
||||
self.Store(owner)
|
||||
|
||||
if authToken is not None:
|
||||
self.Token(authToken)
|
||||
|
||||
def _escape_arg(self, arg):
|
||||
return "\"" + self._escape_quotes(arg) + "\""
|
||||
|
||||
def _escape_quotes(self, s):
|
||||
return s.replace('"', '\\"')
|
||||
|
||||
def _escape_query(self, s):
|
||||
return self._escape_quotes(s)
|
||||
|
||||
def CookieDelete(self, token):
|
||||
command = "COOKIE DELETE %s" % token
|
||||
|
||||
stream.log.debug("SEND: COOKIE DELETE ****************")
|
||||
self.stream.Write(command, nolog=1)
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
def CookieNew(self, timeout):
|
||||
command = "COOKIE NEW %d" % (time.time() + timeout)
|
||||
self.stream.Write(command)
|
||||
|
||||
r = self.stream.GetResponse(nolog=True)
|
||||
|
||||
if r.code != 1000:
|
||||
self.stream.log.debug("READ: %s %s", r.code, r.message)
|
||||
raise CommandError(r)
|
||||
|
||||
self.stream.log.debug("READ: 1000 ****************")
|
||||
return r.message
|
||||
|
||||
def Create(self, path, existingOk=False):
|
||||
command = "CREATE %s" % path
|
||||
self.stream.Write(command)
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
|
||||
if r.code != 1000:
|
||||
if r.code != 4226 or not existingOk:
|
||||
raise CommandError(r)
|
||||
|
||||
return r
|
||||
|
||||
def Conversation(self, uid, props=[]):
|
||||
command = "CONVERSATION %s" % uid
|
||||
|
||||
if len(props) > 0:
|
||||
command = command + " P" + ",".join(props)
|
||||
|
||||
self.stream.Write(command)
|
||||
return ItemIterator(self.stream, len(props))
|
||||
|
||||
def Conversations(self, source=None, props=[], query=None, start=-1, end=-1,
|
||||
center=None, showTotal=False, flags=None, mask=None):
|
||||
command = "CONVERSATIONS"
|
||||
|
||||
if source is not None:
|
||||
command = command + " S" + source
|
||||
|
||||
if start == -1 and end == -1:
|
||||
command = command + " Rall"
|
||||
else:
|
||||
command = command + " R%d-%d" % (start, end)
|
||||
|
||||
if len(props) > 0:
|
||||
command = command + " P" + ",".join(props)
|
||||
|
||||
if query is not None:
|
||||
command = command + " \"Q" + self._escape_query(query) + "\""
|
||||
|
||||
if center is not None:
|
||||
command = command + " C" + center
|
||||
|
||||
if flags is not None:
|
||||
command = command + " F" + str(flags)
|
||||
|
||||
if mask is not None:
|
||||
command = command + " M" + str(mask)
|
||||
|
||||
if showTotal:
|
||||
command = command + " T"
|
||||
|
||||
self.stream.Write(command)
|
||||
return ItemIterator(self.stream, len(props))
|
||||
|
||||
def Delete(self, doc):
|
||||
self.stream.Write("DELETE %s" % (doc))
|
||||
r = self.stream.GetResponse()
|
||||
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
def Events(self, calendar=None, props=[], query=None, start=None, end=None):
|
||||
command = "EVENTS"
|
||||
|
||||
if calendar is not None:
|
||||
command = command + " C" + calendar
|
||||
|
||||
if len(props) > 0:
|
||||
command = command + " P" + ",".join(props)
|
||||
|
||||
if query is not None:
|
||||
command = command + " \"Q" + self._escape_query(query) + "\""
|
||||
|
||||
if start != None and end != None:
|
||||
command = command + " \"D%s-%s\"" % (start.strftime('%Y%m%dT%H%M%S'), end.strftime('%Y%m%dT%H%M%S'))
|
||||
|
||||
self.stream.Write(command)
|
||||
return ItemIterator(self.stream, len(props))
|
||||
|
||||
def Flag(self, guid, flags=None, mode=None):
|
||||
command = "FLAG %s" % guid
|
||||
|
||||
if flags is None:
|
||||
mode = FlagMode.Show
|
||||
elif mode is None:
|
||||
mode = FlagMode.Replace
|
||||
command = "%s %d" % (command, flags)
|
||||
elif mode == FlagMode.Add:
|
||||
command = "%s +%d" % (command, flags)
|
||||
elif mode == FlagMode.Remove:
|
||||
command = "%s -%d" % (command, flags)
|
||||
|
||||
self.stream.Write(command)
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
(old, new) = r.message.split(" ", 1)
|
||||
return (old, new)
|
||||
|
||||
def GetACL(self, doc) :
|
||||
command = "PROPGET \"%s\" nmap.access-control" % doc
|
||||
self.stream.Write(command)
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2001 and r.code != 3245:
|
||||
raise CommandError(r)
|
||||
|
||||
acl = ""
|
||||
if r.code == 2001 :
|
||||
(key, length) = r.message.split(" ", 2)
|
||||
acl = self.stream.Read(int(length))
|
||||
# eat the \r\n afterward
|
||||
self.stream.Read(2)
|
||||
|
||||
return ACL(acl)
|
||||
|
||||
def Info(self, path, props=[]):
|
||||
command = "INFO %s" % self._escape_arg(path)
|
||||
|
||||
if len(props) > 0:
|
||||
command = command + " P" + ",".join(props)
|
||||
|
||||
self.stream.Write(command)
|
||||
r = self.stream.GetResponse()
|
||||
|
||||
if r.code == 2001:
|
||||
item = Item(r)
|
||||
|
||||
for i in range(len(props)):
|
||||
r = self.stream.GetResponse()
|
||||
if r.code == 2001:
|
||||
(key, length) = r.message.split(" ", 2)
|
||||
item.props[key] = self.stream.Read(int(length))
|
||||
# eat the \r\n afterward
|
||||
self.stream.Read(2)
|
||||
|
||||
# eat the response line
|
||||
self.stream.GetResponse()
|
||||
return item
|
||||
elif r.code == 1000:
|
||||
return None
|
||||
|
||||
raise CommandError(r)
|
||||
|
||||
def ISearch(self, query, props = [], start=-1, end=-1):
|
||||
command = "ISEARCH "
|
||||
|
||||
if start == -1 and end == -1:
|
||||
command = command + " Rall"
|
||||
else:
|
||||
command = command + " R%d-%d" % (start, end)
|
||||
|
||||
command = "%s \"%s\"" % (command, self._escape_query(query))
|
||||
|
||||
if len(props) > 0:
|
||||
command = command + " P" + ",".join(props)
|
||||
|
||||
self.stream.Write(command)
|
||||
return ItemIterator(self.stream, len(props))
|
||||
|
||||
def Link(self, calendar, doc) :
|
||||
self.stream.Write("LINK \"%s\" %s" % (calendar, doc))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000 :
|
||||
raise CommandError(r)
|
||||
|
||||
def List(self, path, props=[], start=-1, end=-1, flags=None, mask=None):
|
||||
command = "LIST %s" % path
|
||||
|
||||
if start == -1 and end == -1:
|
||||
command = command + " Rall"
|
||||
else:
|
||||
command = command + " R%d-%d" % (start, end)
|
||||
|
||||
if len(props) > 0:
|
||||
command = command + " P" + ",".join(props)
|
||||
|
||||
if flags is not None:
|
||||
command = command + " F" + str(flags)
|
||||
|
||||
if mask is not None:
|
||||
command = command + " M" + str(mask)
|
||||
|
||||
self.stream.Write(command)
|
||||
return ItemIterator(self.stream, len(props))
|
||||
|
||||
def MailingLists(self, source):
|
||||
command = "MAILINGLISTS %s" % source
|
||||
self.stream.Write(command)
|
||||
return ResponseIterator(self.stream)
|
||||
|
||||
def Mime(self, uid):
|
||||
command = "MIME %s" % uid
|
||||
|
||||
self.stream.Write(command)
|
||||
|
||||
parts = []
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
while r.code in (2002, 2003, 2004):
|
||||
parts.append(MimeItem(r))
|
||||
r = self.stream.GetResponse()
|
||||
|
||||
if len(parts) == 0:
|
||||
return None
|
||||
|
||||
topPart = parts[0]
|
||||
|
||||
if topPart.multipart:
|
||||
parent = topPart
|
||||
|
||||
for child in parts[1:]:
|
||||
child.parent = parent
|
||||
|
||||
if child.end:
|
||||
parent = parent.parent
|
||||
if parent is None:
|
||||
break
|
||||
else:
|
||||
parent.children.append(child)
|
||||
if child.multipart:
|
||||
parent = child
|
||||
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
return topPart
|
||||
|
||||
def Move(self, uid, path, filename=None):
|
||||
command = "MOVE %s \"%s\"" % (uid, path)
|
||||
|
||||
if filename is not None:
|
||||
command = "%s \"%s\"" % (command, filename)
|
||||
self.stream.Write(command)
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
def PropGet(self, doc, name=None):
|
||||
command = "PROPGET %s" % doc
|
||||
|
||||
if name is not None:
|
||||
self.stream.Write("%s %s" % (command, name))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2001:
|
||||
raise CommandError(r)
|
||||
(key, length) = r.message.split(" ", 2)
|
||||
data = unicode(self.stream.Read(int(length)), "utf-8")
|
||||
# eat the \r\n afterward
|
||||
self.stream.Read(2)
|
||||
return data
|
||||
|
||||
self.stream.Write(command)
|
||||
props = {}
|
||||
r = self.stream.GetResponse()
|
||||
while r.code == 2001 or r.code == 3245:
|
||||
if r.code == 3245:
|
||||
# set empty properties to None
|
||||
props[key] = None
|
||||
r = self.stream.GetResponse()
|
||||
continue
|
||||
|
||||
(key, length) = r.message.split(" ", 2)
|
||||
props[key] = unicode(self.stream.Read(int(length)), "utf-8")
|
||||
# eat the \r\n afterward
|
||||
self.stream.Read(2)
|
||||
r = self.stream.GetResponse()
|
||||
|
||||
return props
|
||||
|
||||
def PropSet(self, doc, name, value=None):
|
||||
if value is None:
|
||||
value = ""
|
||||
|
||||
self.stream.Write("PROPSET %s %s %d" % (doc, name, len(value)))
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2002:
|
||||
raise CommandError(r)
|
||||
|
||||
self.stream.WriteRaw(value)
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
def Quit(self):
|
||||
self.stream.Write("QUIT")
|
||||
self.connection.Close()
|
||||
|
||||
def Read(self, doc):
|
||||
self.stream.Write("READ %s" % (doc))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2001:
|
||||
raise CommandError(r)
|
||||
length = r.message.split(" ")[-1]
|
||||
s = self.stream.Read(int(length))
|
||||
# eat the \r\n afterward
|
||||
self.stream.Read(2)
|
||||
return s
|
||||
|
||||
def ReadMimePart(self, doc, part):
|
||||
self.stream.Write("READ %s %d %d" % (doc, part.start, part.length))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2001:
|
||||
raise CommandError(r)
|
||||
length = r.message.split(" ")[-1]
|
||||
s = self.stream.Read(int(length))
|
||||
# eat the \r\n afterward
|
||||
self.stream.Read(2)
|
||||
return StringIO(s)
|
||||
|
||||
def Replace(self, doc, data):
|
||||
self.stream.Write("REPLACE %s %d" % (doc, len(data)))
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2002:
|
||||
raise CommandError(r)
|
||||
|
||||
self.stream.WriteRaw(data)
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
(guid, junk) = r.message.split(" ", 1)
|
||||
return guid
|
||||
|
||||
def Reset(self):
|
||||
self.stream.Write("RESET")
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
def SetACL(self, doc, acl, force=False) :
|
||||
if force or acl.changed :
|
||||
self.PropSet(doc, "nmap.access-control", str(acl))
|
||||
|
||||
def Store(self, name):
|
||||
self.stream.Write("STORE %s" % (name))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
self.owner = name
|
||||
return r
|
||||
|
||||
def Token(self, token):
|
||||
self.stream.Write("TOKEN %s" % (token))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
return r
|
||||
|
||||
def Unlink(self, calendar, event):
|
||||
self.stream.Write("UNLINK %s %s" % (calendar, event))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
return r
|
||||
|
||||
def User(self, name):
|
||||
self.stream.Write("USER %s" % (name))
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
self.user = name
|
||||
return r
|
||||
|
||||
def Write(self, collection, type, data, filename=None, index=None, guid=None, timeCreated=None, flags=None, link=None):
|
||||
if data is None:
|
||||
data = ""
|
||||
|
||||
command = "WRITE \"%s\" %d %d" % (collection, type, len(data))
|
||||
|
||||
if index is not None:
|
||||
command = command + " I%s" % index
|
||||
|
||||
if filename is not None:
|
||||
command = command + " \"F%s\"" % filename
|
||||
|
||||
if guid is not None:
|
||||
command = command + " G%s" % guid
|
||||
|
||||
if timeCreated is not None:
|
||||
command += " T" + timeCreated
|
||||
|
||||
if flags is not None:
|
||||
command = command + " Z%d" % flags
|
||||
|
||||
if link is not None:
|
||||
command = command + " \"L%s\"" % link
|
||||
|
||||
self.stream.Write(command)
|
||||
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 2002:
|
||||
raise CommandError(r)
|
||||
|
||||
self.stream.WriteRaw(data)
|
||||
|
||||
r = self.stream.GetResponse()
|
||||
if r.code != 1000:
|
||||
raise CommandError(r)
|
||||
|
||||
(guid, junk) = r.message.split(" ", 1)
|
||||
return guid
|
||||
|
||||
def Reset(self) :
|
||||
self.stream.Write("RESET\r\n")
|
||||
self.stream.GetResponse()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user