1# A script for analyzing the output of NPSPY and merging data about streams.
2
3import sys
4
5
6def ReadFile(filename, flags='rb'):
7  """Returns the contents of a file."""
8  file = open(filename, flags)
9  result = file.read()
10  file.close()
11  return result
12
13
14def WriteFile(filename, contents):
15  """Overwrites the file with the given contents."""
16  file = open(filename, 'w')
17  file.write(contents)
18  file.close()
19
20
21# sample line: 'NPP_NewStream(0x645c898, 0x56ba900("application/x-shockwave-flash"), 0x64bb3b0 (http://weeklyad.target.com/target/flash/target/target.swf?ver=090326), TRUE, NP_NORMAL)'
22class Stream:
23  def __init__(self, line):
24    split = line.split(', ')
25
26    self.mime_type = split[1].split('"')[1]
27    self.url = split[2].split(' ')[1].strip('()')
28    self.seekable = split[3]
29    self.type = split[4].strip(')')
30    self.size = 0
31    self.status = ''
32    try:
33      self.address = split[2].split(' ')[0]
34    except:
35      print 'parsing error on ' + line
36      self.address = ''
37
38    if self.type != 'NP_NORMAL':
39      print 'line got unexpected type: ' + line
40
41
42def main(argv=None):
43  if argv is None:
44    argv = sys.argv
45
46  streams = []
47
48  if len(argv) != 2:
49    print 'need filename'
50    return
51  file = ReadFile(argv[1])
52  for line in file.splitlines():
53    if line.startswith('NPP_NewStream('):
54      if line.count('(') < 3:
55        print 'unknown format for line: ' + line
56        continue
57
58      s = Stream(line)
59      streams.append(s)
60    elif line.startswith('NPP_Write('):
61      # sample: NPP_Write(0x645c898, 0x64bb3b0, 0, 16384, 0x56c1000("CW")))
62      split = line.split(', ')
63      address = split[1]
64      start = int(split[2])
65      size = int(split[3])
66      found = False
67      for stream in streams:
68        if stream.address == address:
69          if stream.size != start:
70            print 'error: starting at wrong place for write ' + stream.url + ' ' + str(stream.size) + ' ' + str(start)
71          stream.size += size
72          found = True
73          break
74
75      if not found:
76        print "couldn't find stream to match NPP_Write " + line
77    elif line.startswith('NPP_DestroyStream('):
78      # sample: NPP_DestroyStream(0x645c898, 0x64bb3b0, NPRES_DONE)
79      split = line.split(', ')
80      address = split[1]
81      status = split[2].strip(')')
82      found = False
83      for stream in streams:
84        if stream.address == address:
85          stream.status = status
86          stream.address = ''  # address can be reused
87          found = True
88          break
89
90      if not found:
91        print "couldn't find stream to match NPP_DestroyStream " + line
92
93
94  output = []
95  for stream in streams:
96    if stream.status != 'NPRES_DONE':
97      print 'error: no NPP_DestroyStream with success for ' + stream.url + ' ' + stream.status + '.'
98    output.append(', '.join([stream.url, stream.mime_type, str(stream.size), stream.seekable]))
99  output_file = argv[1].replace('.', '_analyzed.')
100
101  WriteFile(output_file, '\n'.join(output))
102
103
104if __name__ == "__main__":
105  sys.exit(main())
106