00001
00002
00003
00004
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
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
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
00245 attrname = string.split(attr[1:-2], ":", maxsplit=1)[1]
00246
00247 self.attrnames[nextline[2:-1]] = attrname
00248 nextline = self.fp.readline()
00249
00250 while nextline and nextline[0] == "!":
00251
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
00273
00274 line = self.fp.readline()[:-1]
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
00286 obj.name = self._readstr()
00287 obj.attrs["NAME"] = obj.name
00288
00289 obj.location = self._readint()
00290
00291
00292 obj.zone = self._readint()
00293
00294 obj.contents = self._readint()
00295 obj.exits = self._readint()
00296
00297
00298 obj.link = self._readint()
00299
00300 obj.next = self._readint()
00301
00302
00303
00304 obj.lock = self._readstr()
00305 obj.attrs["LOCK"] = obj.lock
00306
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
00314 obj.parent = self._readint()
00315
00316 obj.money = self._readint()
00317
00318 obj.flags = self._readint()
00319
00320
00321 obj.flags2 = self._readint()
00322
00323
00324 obj.flags3 = self._readint()
00325
00326
00327 obj.powers = self._readint()
00328 obj.powers2 = self._readint()
00329
00330
00331
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