|
1 #! /usr/bin/env python |
|
2 # Viewer for archives packaged by archive.py |
|
3 # Copyright (C) 2005, Giovanni Bajo |
|
4 # Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc. |
|
5 # |
|
6 # This program is free software; you can redistribute it and/or |
|
7 # modify it under the terms of the GNU General Public License |
|
8 # as published by the Free Software Foundation; either version 2 |
|
9 # of the License, or (at your option) any later version. |
|
10 # |
|
11 # This program is distributed in the hope that it will be useful, |
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 # GNU General Public License for more details. |
|
15 # |
|
16 # You should have received a copy of the GNU General Public License |
|
17 # along with this program; if not, write to the Free Software |
|
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|
19 import archive |
|
20 import carchive |
|
21 import sys, string, tempfile, os |
|
22 try: |
|
23 import zlib |
|
24 except ImportError: |
|
25 zlib = archive.DummyZlib() |
|
26 import pprint |
|
27 |
|
28 stack = [] |
|
29 cleanup = [] |
|
30 |
|
31 def main(): |
|
32 global stack |
|
33 name = sys.argv[1] |
|
34 arch = getArchive(name) |
|
35 stack.append((name, arch)) |
|
36 show(name, arch) |
|
37 |
|
38 while 1: |
|
39 toks = string.split(raw_input('? '), ' ', 1) |
|
40 if not toks: |
|
41 usage() |
|
42 continue |
|
43 if len(toks) == 1: |
|
44 cmd = toks[0] |
|
45 arg = '' |
|
46 else: |
|
47 cmd, arg = toks |
|
48 cmd = string.upper(cmd) |
|
49 if cmd == 'U': |
|
50 if len(stack) > 1: |
|
51 arch = stack[-1][1] |
|
52 arch.lib.close() |
|
53 del stack[-1] |
|
54 nm, arch = stack[-1] |
|
55 show(nm, arch) |
|
56 elif cmd == 'O': |
|
57 if not arg: |
|
58 arg = raw_input('open name? ') |
|
59 arg = string.strip(arg) |
|
60 arch = getArchive(arg) |
|
61 if arch is None: |
|
62 print arg, "not found" |
|
63 continue |
|
64 stack.append((arg, arch)) |
|
65 show(arg, arch) |
|
66 elif cmd == 'X': |
|
67 if not arg: |
|
68 arg = raw_input('extract name? ') |
|
69 arg = string.strip(arg) |
|
70 data = getData(arg, arch) |
|
71 if data is None: |
|
72 print "Not found" |
|
73 continue |
|
74 fnm = raw_input('to filename? ') |
|
75 if not fnm: |
|
76 print `data` |
|
77 else: |
|
78 open(fnm, 'wb').write(data) |
|
79 elif cmd == 'Q': |
|
80 break |
|
81 else: |
|
82 usage() |
|
83 for (nm, arch) in stack: |
|
84 arch.lib.close() |
|
85 stack = [] |
|
86 for fnm in cleanup: |
|
87 try: |
|
88 os.remove(fnm) |
|
89 except Exception, e: |
|
90 print "couldn't delete", fnm, e.args |
|
91 def usage(): |
|
92 print "U: go Up one level" |
|
93 print "O <nm>: open embedded archive nm" |
|
94 print "X <nm>: extract nm" |
|
95 print "Q: quit" |
|
96 def getArchive(nm): |
|
97 if not stack: |
|
98 if string.lower(nm[-4:]) == '.pyz': |
|
99 return ZlibArchive(nm) |
|
100 return carchive.CArchive(nm) |
|
101 parent = stack[-1][1] |
|
102 try: |
|
103 return parent.openEmbedded(nm) |
|
104 except KeyError, e: |
|
105 return None |
|
106 except (ValueError, RuntimeError): |
|
107 ndx = parent.toc.find(nm) |
|
108 dpos, dlen, ulen, flag, typcd, nm = parent.toc[ndx] |
|
109 x, data = parent.extract(ndx) |
|
110 tfnm = tempfile.mktemp() |
|
111 cleanup.append(tfnm) |
|
112 open(tfnm, 'wb').write(data) |
|
113 if typcd == 'z': |
|
114 return ZlibArchive(tfnm) |
|
115 else: |
|
116 return carchive.CArchive(tfnm) |
|
117 |
|
118 def getData(nm, arch): |
|
119 if type(arch.toc) is type({}): |
|
120 (ispkg, pos, lngth) = arch.toc.get(nm, (0, None, 0)) |
|
121 if pos is None: |
|
122 return None |
|
123 arch.lib.seek(arch.start + pos) |
|
124 return zlib.decompress(arch.lib.read(lngth)) |
|
125 ndx = arch.toc.find(nm) |
|
126 dpos, dlen, ulen, flag, typcd, nm = arch.toc[ndx] |
|
127 x, data = arch.extract(ndx) |
|
128 return data |
|
129 |
|
130 def show(nm, arch): |
|
131 if type(arch.toc) == type({}): |
|
132 print " Name: (ispkg, pos, len)" |
|
133 toc = arch.toc |
|
134 else: |
|
135 print " pos, length, uncompressed, iscompressed, type, name" |
|
136 toc = arch.toc.data |
|
137 pprint.pprint(toc) |
|
138 |
|
139 class ZlibArchive(archive.ZlibArchive): |
|
140 def checkmagic(self): |
|
141 """ Overridable. |
|
142 Check to see if the file object self.lib actually has a file |
|
143 we understand. |
|
144 """ |
|
145 self.lib.seek(self.start) #default - magic is at start of file |
|
146 if self.lib.read(len(self.MAGIC)) != self.MAGIC: |
|
147 raise RuntimeError, "%s is not a valid %s archive file" \ |
|
148 % (self.path, self.__class__.__name__) |
|
149 if self.lib.read(len(self.pymagic)) != self.pymagic: |
|
150 print "Warning: pyz is from a different Python version" |
|
151 self.lib.read(4) |
|
152 |
|
153 if __name__ == '__main__': |
|
154 main() |
|
155 |