python/flatfiledb.py

Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 # Copyright (c) 1999-2002 Thomas Wouters
00004 #   All rights reserved
00005 
00006 import sys, string
00007 
00008 builtin_attrnames = {
00009     "1": "OSUCC",
00010     "2": "OFAIL",
00011     "3": "FAIL",
00012     "4": "SUCC",
00013     "5": "PASS",
00014     "6": "DESC",
00015     "7": "SEX",
00016     "8": "ODROP",
00017     "9": "DROP",
00018     "10": "OKILL",
00019     "11": "KILL",
00020     "12": "ASUCC",
00021     "13": "AFAIL",
00022     "14": "ADROP",
00023     "15": "AKILL",
00024     "16": "AUSE",
00025     "17": "CHARGES",
00026     "18": "RUNOUT",
00027     "19": "STARTUP",
00028     "20": "ACLONE",
00029     "21": "APAY",
00030     "22": "OPAY",
00031     "23": "PAY",
00032     "24": "COST",
00033     "25": "MONEY",
00034     "26": "LISTEN",
00035     "27": "AAHEAR",
00036     "28": "AMHEAR",
00037     "29": "AHEAR",
00038     "30": "LAST",
00039     "31": "QUEUEMAX",
00040     "32": "IDESC",
00041     "33": "ENTER",
00042     "34": "OXENTER",
00043     "35": "AENTER",
00044     "36": "ADESC",
00045     "37": "ODESC",
00046     "38": "RQUOTA",
00047     "39": "ACONNECT",
00048     "40": "ADISCONNECT",
00049     "41": "ALLOWANCE",
00050     "42": "LOCK",
00051     "43": "NAME",
00052     "44": "COMMENT",
00053     "45": "USE",
00054     "46": "OUSE",
00055     "47": "SEMAPHORE",
00056     "48": "TIMEOUT",
00057     "49": "QUOTA",
00058     "50": "LEAVE",
00059     "51": "OLEAVE",
00060     "52": "ALEAVE",
00061     "53": "OENTER",
00062     "54": "OXLEAVE",
00063     "55": "MOVE",
00064     "56": "OMOVE",
00065     "57": "AMOVE",
00066     "58": "ALIAS",
00067     "59": "LENTER",
00068     "60": "LLEAVE",
00069     "61": "LPAGE",
00070     "62": "LUSE",
00071     "63": "LGIVE",
00072     "64": "EALIAS",
00073     "65": "LALIAS",
00074     "66": "EFAIL",
00075     "67": "OEFAIL",
00076     "68": "AEFAIL",
00077     "69": "LFAIL",
00078     "70": "OLFAIL",
00079     "71": "ALFAIL",
00080     "72": "REJECT",
00081     "73": "AWAY",
00082     "74": "IDLE",
00083     "75": "UFAIL",
00084     "76": "OUFAIL",
00085     "77": "AUFAIL",
00086     "78": "PFAIL",
00087     "79": "TPORT",
00088     "80": "OTPORT",
00089     "81": "OXTPORT",
00090     "82": "ATPORT",
00091     "83": "PRIVS",
00092     "84": "LOGINDATA",
00093     "85": "LTPORT",
00094     "86": "LDROP",
00095     "87": "LRECEIVE",
00096     "88": "LASTSITE",
00097     "89": "INPREFIX",
00098     "90": "PREFIX",
00099     "91": "INFILTER",
00100     "92": "FILTER",
00101     "93": "LLINK",
00102     "94": "LTELOUT",
00103     "95": "FORWARDLIST",
00104     "96": "MAILFOLDERS",
00105     "97": "LUSER",
00106     "98": "LPARENT",
00107     "100": "VA",
00108     "101": "VB",
00109     "102": "VC",
00110     "103": "VD",
00111     "104": "VE",
00112     "105": "VF",
00113     "106": "VG",
00114     "107": "VH",
00115     "108": "VI",
00116     "109": "VJ",
00117     "110": "VK",
00118     "111": "VL",
00119     "112": "VM",
00120     "113": "VN",
00121     "114": "VO",
00122     "115": "VP",
00123     "116": "VQ",
00124     "117": "VR",
00125     "118": "VS",
00126     "119": "VT",
00127     "120": "VU",
00128     "121": "VV",
00129     "122": "VW",
00130     "123": "VX",
00131     "124": "VY",
00132     "125": "VZ",
00133 
00134     "129": "GFAIL",
00135     "130": "OGFAIL",
00136     "131": "AGFAIL",
00137     "132": "RFAIL",
00138     "133": "ORFAIL",
00139     "134": "ARFAIL",
00140     "135": "DFAIL",
00141     "136": "ODFAIL",
00142     "137": "ADFAIL",
00143     "138": "TFAIL",
00144     "139": "OTFAIL",
00145     "140": "ATFAIL",
00146     "141": "TOFAIL",
00147     "142": "OTOFAIL",
00148     "143": "ATOFAIL",
00149     "144": "LASTNAME",
00150     "145": "HEATCHARS",
00151     "146": "MECHPREFID",
00152     "200": "LASTPAGE",
00153     "201": "MAIL",
00154     "202": "AMAIL",
00155     "203": "SIGNATURE",
00156     "204": "DAILY",
00157     "205": "MAILTO",
00158     "206": "MAILMSG",
00159     "207": "MAILSUB",
00160     "208": "MAILCURF",
00161     "209": "LSPEECH",
00162     "210": "PROGCMD",
00163     "211": "MAILFLAGS",
00164     "212": "DESTROYER",
00165     "213": "LUCK",
00166     "214": "MECHSKILLS",
00167     "215": "XTYPE",
00168     "216": "TACHEIGHT",
00169     "217": "LRSHEIGHT",
00170     "218": "CONTACTOPT",
00171     "219": "MECHNAME",
00172     "220": "MECHTYPE",
00173     "221": "MECHDESC",
00174     "222": "MECHSTATUS",
00175     "229": "MWTEMPLATE",
00176     "230": "FACTION",
00177     "231": "JOB",
00178     "232": "RANKNUM",
00179     "233": "HEALTH",
00180     "234": "ATTRS",
00181     "235": "BUILDLINKS",
00182     "236": "BUILDENTRANCE",
00183     "237": "BUILDCOORD",
00184     "238": "ADVS",
00185     "239": "PILOTNUM",
00186     "240": "MAPVIS",
00187     "241": "TZ",
00188     "242": "TECHTIME",
00189     "243": "ECONPARTS",
00190     "244": "SKILLS",
00191     "245": "PCEQUIP",
00192     "246": "HOURLY",
00193     "247": "HISTORY",
00194     "250": "VRML_URL",
00195     "251": "HTDESC"
00196 }
00197 
00198 class MUXDBLoadError(Exception):
00199     "Something went wrong with loading the DB"
00200     pass
00201 
00202 class MUXFlatfileDB:
00203     def __init__(self, fp=None):
00204         self.db = {}
00205         self.dbtop = 0
00206         self.player_record = 0
00207         self.version = 0
00208         self.attrnames = builtin_attrnames.copy()
00209         if fp:
00210             self.readdb(fp)
00211 
00212     def readdb(self, fp):
00213         self.fp = fp
00214         version = self.fp.readline()
00215         if not version or version[:2] <> "+X":
00216             # Version starts with +X
00217             raise MUXDBLoadError, \
00218                   "Not a valid DB file (no first line or it doesn't start with '+X')"
00219         if version[2:-1] <> "992001":
00220             sys.stderr.write("flatfiledb: Warning: possibly wrong flatfile version"
00221                              "(%d insteas of %s)\n"%( version[2:-1], "992001"))
00222         self.version = int(version[2:-1])
00223         nextline = self.fp.readline()
00224 
00225         if nextline and nextline[:2] == "+S":
00226             self.dbtop = int(nextline[2:-1])
00227             nextline = self.fp.readline()
00228 
00229         if nextline and nextline[:2] == "+N":
00230             self.nextattr = int(nextline[2:-1])
00231             nextline = self.fp.readline()
00232 
00233         if nextline and nextline[:2] == "-R":
00234             self.player_record = int(nextline[2:-1])
00235             nextline = self.fp.readline()
00236 
00237         while nextline and nextline[:2] == "+A":
00238             # Attribute defn, next line is the attribute name
00239             attr = self.fp.readline()
00240             if attr[0] <> '"' or attr[-2] <> '"':
00241                 sys.stderr.write("Warning: broken +A lines:\n%s%s"%(nextline, attr))
00242                 nextline = self.fp.readline()
00243                 continue
00244             # The attribute name is really "flags:name", but we don't care about flags yet
00245             attrname = string.split(attr[1:-2], ":", maxsplit=1)[1]
00246 #            sys.stderr.write("debug: adding attr num %s (%s)\n"%(nextline[2:-1], nextline))
00247             self.attrnames[nextline[2:-1]] = attrname
00248             nextline = self.fp.readline()
00249 
00250         while nextline and nextline[0] == "!":
00251             # Next object.
00252             nextline = self.readobject(int(nextline[1:-1]))
00253 
00254         if not nextline or nextline <> "***END OF DUMP***\n":
00255             sys.stderr.write("Didn't find ***END OF DUMP***\n")
00256             if nextline:
00257                 sys.stderr.write("The line read was: %s"%nextline)
00258         return
00259 
00260     def _readint(self):
00261         line = self.fp.readline()[:-1]
00262         try:
00263             return int(line)
00264         except:
00265             sys.stderr.write("warning: something went wrong with reading int: %s\n"%line)
00266             return -1
00267 
00268     def _readstr(self):
00269         return self.fp.readline()[1:-2]
00270 
00271     def _readattr(self):
00272         # If the line doesn't start with '"', it's broken
00273         # If the line doesn't *end* with '"', it's continued on the next line
00274         line = self.fp.readline()[:-1] # Strip the newline
00275         if line[0] <> '"':
00276             sys.stderr.write("flatfiledb: Warning: not a valid attr line: %s\n"%line)
00277         while line[-1] <> '"':
00278             line = line + self.fp.readline()[:-1]
00279         return line[1:-1]
00280 
00281     def readobject(self, objnum):
00282         obj = MUXDBObject(objnum)
00283         self.db[objnum] = obj
00284 
00285         # if not vlags & V_ATRNAME
00286         obj.name = self._readstr()
00287         obj.attrs["NAME"] = obj.name
00288 
00289         obj.location = self._readint()
00290 
00291         # if flags & V_ZONE)
00292         obj.zone = self._readint()
00293         
00294         obj.contents = self._readint()
00295         obj.exits = self._readint()
00296 
00297         # if flags & V_LINK)
00298         obj.link = self._readint()
00299 
00300         obj.next = self._readint()
00301 
00302         # if not flags & V_ATRKEY
00303         # Lock attribute... treat as string, even though it should be specially handled
00304         obj.lock = self._readstr()
00305         obj.attrs["LOCK"] = obj.lock
00306         # Ugly hack to work around silly db restriction
00307         nextline = self.fp.readline()
00308         if string.strip(nextline):
00309             obj.owner = int(nextline[:-1])
00310         else:
00311             obj.owner = self._readint()
00312 
00313         # if flags & V_PARENT
00314         obj.parent = self._readint()
00315         # if not flags & V_ATRMONEY
00316         obj.money = self._readint()
00317 
00318         obj.flags = self._readint()
00319 
00320         # if flags & V_XFLAGS
00321         obj.flags2 = self._readint()
00322 
00323         # if flags & V_3FLAGS
00324         obj.flags3 = self._readint()
00325 
00326         # if flags & V_POWERS
00327         obj.powers = self._readint()
00328         obj.powers2 = self._readint()
00329 
00330         # Read the attributes
00331         # This is really 'if not flags & V_GDBM' but we don't do GDBM db's (yet?)
00332 
00333         nextline = self.fp.readline()
00334         while nextline and nextline[0] == ">":
00335             attrnum = nextline[1:-1]
00336             obj.attrs[self.attrnames[attrnum]] = self._readattr()
00337             nextline = self.fp.readline()
00338 
00339         if nextline <> "<\n":
00340             sys.stderr.write("flatfiledb: Warning: attrlist ended with: %s"%nextline)
00341 
00342         return self.fp.readline()
00343 
00344     def attr_search(self, str):
00345         res = []
00346         for obj in self.db.values():
00347             res.extend(obj.attr_search(str))
00348         return res
00349 
00350 class MUXDBObject:
00351     def __init__(self, objnum):
00352         self.objnum = objnum
00353         self.attrs = {}
00354 
00355     def attr_search(self, str):
00356         res = []
00357         for attr in self.attrs.keys():
00358             if string.find(self.attrs[attr], str) <> -1:
00359                 res.append((self.objnum, attr, self.attrs[attr]))
00360         return res
00361 
00362 
00363 if __name__ == "__main__":
00364     import sys
00365     if len(sys.argv) <> 2:
00366         print "Usage: python -i flatfiledb.py <flatfile>"
00367         sys.exit()
00368     db = MUXFlatfileDB(open(sys.argv[1]))
00369         

Generated on Mon May 28 04:25:18 2007 for BattletechMUX by  doxygen 1.4.7