#!/usr/bin/env python # docucolor.cgi -- CGI script to interpret Xerox DocuColor forensic dot pattern # Copyright (C) 2005 Electronic Frontier Foundation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # # # Xerox Corporation has no connection with this program and does not # warrant its correctness. # # This program is the result of research by Robert Lee, Seth Schoen, Patrick # Murphy, Joel Alwen, and Andrew "bunnie" Huang. For more information, see # http://www.eff.org/Privacy/printers import cgi, os, sys import cgitb; cgitb.enable() print "Content-type: text/html" print form = cgi.FieldStorage() print """
"
print " 111111"
print " 123456789012345"
for y in range(7, -1, -1):
line = ""
for x in range(1, 16):
if dots[(x,y)]: line = line + "o"
else: line = line + " "
print y, line
print ""
def column_value(col):
# Extract and decode the value of the indicated column.
total = 0
for y in range(6, -1, -1):
total = total + dots[(col, y)] * 2**y
return total
def footer():
if os.environ.has_key("HTTP_REFERER"):
r = os.environ["HTTP_REFERER"]
if r:
print '' % r
print ""
sys.exit(0)
dots = {}
for x in range(1, 16):
for y in range(0,8):
dots[(x,y)] = form.has_key("%i,%i" % (x,y))
# Step 1: display disclaimer and output
print "This is an interpretation of the following dot pattern:
" print_matrix() print """This interpretation is based on reverse engineering, and may not be complete or current for every DocuColor model version. Xerox Corporation has no connection with this program, and does not warrant its correctness.
This pattern is empty and cannot be interpreted.
" footer() # Step 2: verify row parity bad_rows = [] # don't check row 7 because it is expected to have even parity for row in range(6, -1, -1): p = 0 for col in range(1, 16): p = (p + dots[(col, row)]) % 2 if p == 0: print "Parity mismatch for row %i.There are numerous errors here; you probably" print "did not enter a genuine DocuColor matrix, or used a" print "matrix we don't know how to decode. The content of" print "this interpretation is unlikely to be" print "meaningful.
" print "Making correction and processing corrected matrix:
" print_matrix() print "Printer serial number: %02i%02i%02i [or %02i%02i%02i%02i]
" % (tuple(map(column_value, (13, 12, 11))) + tuple(map(column_value, (14, 13, 12, 11)))) # Step 6: decode date and time # Year: guessing about Y2K, for lack of any relevant evidence year = column_value(8) if year < 70 or year > 99: year = year + 2000 else: year = year + 1900 # Month month_names = ["(no month specified)", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] try: month = month_names[column_value(7)] except IndexError: month = "(invalid month %i)" % column_value(8) # Day day = column_value(6) if day == 0: day = "(no day specified)" elif day > 31: day = "(invalid day %i)" % day print "Date: %s %s, %s
" % (str(month), str(day), str(year)) hour = column_value(5) minute = column_value(2) print "Time: %02i:%02i
" % (hour, minute) # Step 7: decode unknown column 15 print "" print "Column 15 value: %i" % column_value(15) footer()