home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / hplip / setup < prev    next >
Encoding:
Text File  |  2007-04-04  |  33.5 KB  |  955 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19. #
  20. # Author: Don Welch
  21. #
  22.  
  23.  
  24. __version__ = '4.5'
  25. __title__ = 'Printer/Fax Setup Utility'
  26. __doc__ = "Installs HPLIP printers and faxes in the CUPS spooler. Tries to automatically determine the correct PPD file to use. Allows the printing of a testpage. Performs basic fax parameter setup."
  27.  
  28. # Std Lib
  29. import sys, getopt, time
  30. import socket, os.path, re
  31. import readline, gzip
  32.  
  33. # Local
  34. from base.g import *
  35. from base import device, utils, msg, service
  36. from prnt import cups
  37.  
  38. #number_pat = re.compile(r""".*?(\d+)""", re.IGNORECASE)
  39. nickname_pat = re.compile(r'''\*NickName:\s*\"(.*)"''', re.MULTILINE)
  40.  
  41. USAGE = [ (__doc__, "", "name", True),
  42.           ("Usage: hp-setup [MODE] [OPTIONS] [SERIAL NO.|USB bus:device|IP|DEVNODE]", "", "summary", True),
  43.           ("[MODE]", "", "header", False),
  44.           ("Enter graphical UI mode:", "-u or --gui (Default)", "option", False),
  45.           ("Run in interactive mode:", "-i or --interactive", "option", False),
  46.           utils.USAGE_SPACE,
  47.           utils.USAGE_OPTIONS,
  48.           ("Automatic mode:", "-a or --auto (-i mode only)", "option", False),
  49.           ("To specify the port on a multi-port JetDirect:", "-p<port> or --port=<port> (Valid values are 1\*, 2, and 3. \*default)", "option", False),
  50.           ("No testpage in automatic mode:", "-x (-i mode only)", "option", False),
  51.           ("To specify a CUPS printer queue name:", "-n<printer> or --printer=<printer> (-i mode only)", "option", False),
  52.           ("To specify a CUPS fax queue name:", "-f<fax> or --fax=<fax> (-i mode only)", "option", False),
  53.           ("Type of queue(s) to install:", "-t<typelist> or --type=<typelist>. <typelist>: print*, fax\* (\*default) (-i mode only)", "option", False),
  54.           ("Bus to probe (if device not specified):", "-b<bus> or --bus=<bus>", "option", False),
  55.           utils.USAGE_BUS2,
  56.           utils.USAGE_LOGGING1, utils.USAGE_LOGGING2, utils.USAGE_LOGGING3,
  57.           utils.USAGE_HELP,
  58.           ("[SERIAL NO.|USB ID|IP|DEVNODE]", "", "heading", False),
  59.           ("USB bus:device (usb only):", """"xxx:yyy" where 'xxx' is the USB bus and 'yyy' is the USB device. (Note: The ':' and all leading zeros must be present.)""", 'option', False),
  60.           ("", "Use the 'lsusb' command to obtain this information.", "option", False),
  61.           ("IPs (network only):", 'IPv4 address "a.b.c.d" or "hostname"', "option", False),
  62.           ("DEVNODE (parallel only):", '"/dev/parportX", X=0,1,2,...', "option", False),
  63.           ("SERIAL NO. (usb and parallel only):", '"serial no."', "option", True),
  64.           utils.USAGE_EXAMPLES,
  65.           ("Setup using GUI mode:", "$ hp-setup", "example", False),
  66.           ("Setup using GUI mode, specifying usb:", "$ hp-setup -b usb", "example", False),
  67.           ("Setup using GUI mode, specifying an IP:", "$ hp-setup 192.168.0.101", "example", False),          
  68.           ("One USB printer attached, automatic:", "$ hp-setup -i -a", "example", False),
  69.           ("USB, IDs specified:", "$ hp-setup -i 001:002", "example", False),
  70.           ("Network:", "$ hp-setup -i 66.35.250.209", "example", False),
  71.           ("Network, Jetdirect port 2:", "$ hp-setup -i --port=2 66.35.250.209", "example", False),
  72.           ("Parallel:", "$ hp-setup -i /dev/parport0", "example", False),
  73.           ("USB or parallel, using serial number:", "$ hp-setup -i US12345678A", "example", False),
  74.           ("USB, automatic:", "$ hp-setup -i --auto 001:002", "example", False),
  75.           ("Parallel, automatic, no testpage:", "$ hp-setup -i -a -x /dev/parport0", "example", False),
  76.           ("Parallel, choose device:", "$ hp-setup -i -b par", "example", False),
  77.           utils.USAGE_SPACE,
  78.           utils.USAGE_NOTES,
  79.           ("1. If no serial number, USB ID, IP, or device node is specified, the USB and parallel busses will be probed for devices.", "", 'note', False),
  80.           ("2. Using 'lsusb' to obtain USB IDs: (example)", "", 'note', False),
  81.           ("   $ lsusb", "", 'note', False),
  82.           ("         Bus 003 Device 011: ID 03f0:c202 Hewlett-Packard", "", 'note', False),
  83.           ("   $ hp-setup --auto 003:011", "", 'note', False),
  84.           ("   (Note: You may have to run 'lsusb' from /sbin or another location. Use '$ locate lsusb' to determine this.)", "", 'note', True),
  85.           ("3. Parameters -a, -n, -f, or -t are not valid in GUI (-u) mode.", "", 'note', True),
  86.           utils.USAGE_SPACE,
  87.           utils.USAGE_SEEALSO,
  88.           ("hp-makeuri", "", "seealso", False),
  89.           ("hp-probe", "", "seealso", False),
  90.         ]
  91.  
  92. def usage(typ='text'):
  93.     if typ == 'text':
  94.         utils.log_title(__title__, __version__)
  95.  
  96.     utils.format_text(USAGE, typ, __title__, 'hp-setup', __version__)
  97.     sys.exit(0)
  98.  
  99.  
  100. def restart_cups():
  101.     if os.path.exists('/etc/init.d/cups'):
  102.         return '/etc/init.d/cups restart'
  103.  
  104.     elif os.path.exists('/etc/init.d/cupsys'):
  105.         return '/etc/init.d/cupsys restart'
  106.  
  107.     else:
  108.         return 'killall -HUP cupsd'
  109.  
  110.  
  111. log.set_module('hp-setup')
  112.  
  113. try:
  114.     opts, args = getopt.getopt(sys.argv[1:], 'p:n:d:hl:b:t:f:axgui',
  115.         ['printer=', 'fax=', 'device=', 'help', 'help-rest', 'help-man',
  116.          'logging=', 'bus=', 'type=', 'auto', 'port=', 'gui', 'interactive',
  117.          'help-desc', 'username='])
  118. except getopt.GetoptError:
  119.     usage()
  120.  
  121. printer_name = None
  122. fax_name = None
  123. device_uri = None
  124. log_level = logger.DEFAULT_LOG_LEVEL
  125. bus = 'usb' #device.DEFAULT_PROBE_BUS
  126. setup_print = True
  127. setup_fax = True
  128. makeuri = None
  129. bus = None
  130. auto = False
  131. testpage_in_auto_mode = True
  132. jd_port = 1
  133. mode = GUI_MODE
  134. mode_specified = False
  135. username = ''
  136.  
  137. if os.getenv("HPLIP_DEBUG"):
  138.     log.set_level('debug')
  139.  
  140. for o, a in opts:
  141.     if o in ('-h', '--help'):
  142.         usage('text')
  143.  
  144.     elif o == '--help-rest':
  145.         usage('rest')
  146.  
  147.     elif o == '--help-man':
  148.         usage('man')
  149.  
  150.     elif o == '--help-desc':
  151.         print __doc__,
  152.         sys.exit(0)
  153.  
  154.     elif o == '-x':
  155.         testpage_in_auto_mode = False
  156.  
  157.     elif o in ('-n', '--printer'):
  158.         printer_name = a
  159.  
  160.     elif o in ('-f', '--fax'):
  161.         fax_name = a
  162.  
  163.     elif o in ('-d', '--device'):
  164.         device_uri = a
  165.  
  166.     elif o in ('-b', '--bus'):
  167.         bus = a.lower().strip()
  168.         if not device.validateBusList(bus, False):
  169.             usage()
  170.  
  171.     elif o in ('-l', '--logging'):
  172.         log_level = a.lower().strip()
  173.         if not log.set_level(log_level):
  174.             usage()
  175.  
  176.     elif o == '-g':
  177.         log.set_level('debug')
  178.  
  179.     elif o in ('-t', '--type'):
  180.         setup_fax, setup_print = False, False
  181.         a = a.strip().lower()
  182.         for aa in a.split(','):
  183.             if aa.strip() not in ('print', 'fax'):
  184.                 usage()
  185.             if aa.strip() == 'print':
  186.                 setup_print = True
  187.             elif aa.strip() == 'fax':
  188.                 setup_fax = True
  189.  
  190.     elif o in ('-p', '--port'):
  191.         try:
  192.             jd_port = int(a)
  193.         except ValueError:
  194.             log.error("Invalid port number. Must be between 1 and 3 inclusive.")
  195.             usage()
  196.  
  197.     elif o in ('-a', '--auto'):
  198.         auto = True
  199.  
  200.     elif o in ('-u', '--gui'):
  201.         if mode_specified:
  202.             log.error("You may only specify a single mode as a parameter (-i or -u).")
  203.             sys.exit(1)
  204.  
  205.         mode = GUI_MODE
  206.         mode_specified = True
  207.  
  208.     elif o in ('-i', '--interactive'):
  209.         if mode_specified:
  210.             log.error("You may only specify a single mode as a parameter (-i or -u).")
  211.             sys.exit(1)
  212.  
  213.         mode = INTERACTIVE_MODE
  214.         mode_specified = True
  215.  
  216.     elif o == '--username':
  217.         username = a
  218.  
  219. try:
  220.     param = args[0]
  221. except IndexError:
  222.     param = ''
  223.  
  224. utils.log_title(__title__, __version__)
  225.  
  226. if mode == GUI_MODE:
  227.     if not os.getenv('DISPLAY'):
  228.         log.error("No display found. Reverting to interactive mode.")
  229.         mode = INTERACTIVE_MODE
  230.  
  231.     elif not utils.checkPyQtImport():
  232.         log.error("PyQt init failed. Reverting to interactive mode.")
  233.         mode = INTERACTIVE_MODE
  234.  
  235.  
  236. if mode == GUI_MODE:
  237.     from qt import *
  238.     from ui import setupform
  239.  
  240.     a = QApplication(sys.argv)
  241.     QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
  242.  
  243.     if not os.geteuid() == 0:
  244.         log.error("You must be root to run this utility.")
  245.  
  246.         QMessageBox.critical(None, 
  247.                              "HP Device Manager - Printer Setup Wizard",
  248.                              "You must be root to run hp-setup.",
  249.                               QMessageBox.Ok,
  250.                               QMessageBox.NoButton,
  251.                               QMessageBox.NoButton)
  252.  
  253.         sys.exit(1)
  254.  
  255.     try:
  256.         w = setupform.SetupForm(bus, param, jd_port, username)
  257.     except Error:
  258.         log.error("Unable to connect to HPLIP I/O. Please (re)start HPLIP and try again.")
  259.         sys.exit(1)
  260.  
  261.     a.setMainWidget(w)
  262.     w.show()
  263.  
  264.     a.exec_loop()
  265.  
  266. else: # INTERACTIVE_MODE
  267.  
  268.     if not os.geteuid() == 0:
  269.         log.error("You must be root to run this utility.")
  270.         sys.exit(1)
  271.  
  272.     hpiod_sock = None
  273.     try:
  274.         hpiod_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  275.         hpiod_sock.connect((prop.hpiod_host, prop.hpiod_port))
  276.     except socket.error:
  277.         log.error("Unable to connect to hpiod.")
  278.         sys.exit(1)
  279.  
  280.  
  281.     hpssd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  282.     try:
  283.         hpssd_sock.connect((prop.hpssd_host, prop.hpssd_port))
  284.     except socket.error:
  285.         print "Unable to connect to HPLIP I/O (hpssd)."
  286.         sys.exit(1)
  287.  
  288.     # ******************************* MAKEURI
  289.  
  290.     if param:
  291.         device_uri, sane_uri, fax_uri = device.makeURI(hpiod_sock, param, jd_port)
  292.  
  293.     # ******************************* DEVICE CHOOSER
  294.     if bus is None:
  295.         bus = 'usb,par'
  296.  
  297.     if not device_uri: 
  298.         try:
  299.             device_uri = device.getInteractiveDeviceURI(bus)
  300.             if device_uri is None:
  301.                 sys.exit(1)
  302.  
  303.         except Error:
  304.             log.error("Error occured during interactive mode. Exiting.")
  305.             sys.exit(1)
  306.  
  307.     # ******************************* QUERY MODEL AND COLLECT PPDS
  308.  
  309.     log.info(utils.bold("\nSetting up device: %s\n" % device_uri))
  310.  
  311.     if not auto:
  312.         log.info("(Note: Defaults for each question are maked with a '*'. Press <enter> to accept the default.)")
  313.  
  314.     log.info("")
  315.  
  316.     print_uri = device_uri.replace("hpfax:", "hp:")
  317.     fax_uri = device_uri.replace("hp:", "hpfax:")
  318.  
  319.     back_end, is_hp, bus, model, \
  320.         serial, dev_file, host, port = \
  321.         device.parseDeviceURI(device_uri)
  322.  
  323.     log.debug("Model=%s" % model)
  324.     mq = device.queryModelByURI(device_uri)
  325.  
  326.     if not mq or mq.get('support-type', SUPPORT_TYPE_NONE) == SUPPORT_TYPE_NONE:
  327.         log.error("Unsupported printer model.")
  328.         sys.exit(1)
  329.  
  330.     if not mq.get('fax-type', 0) and setup_fax:
  331.         log.warning("Cannot setup fax - device does not have fax feature.")
  332.         setup_fax = False
  333.  
  334.     ppds = cups.getSystemPPDs()
  335.  
  336.     default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
  337.     stripped_model = default_model.lower().replace('hp-', '').replace('hp_', '')
  338.  
  339.     # ******************************* PRINT QUEUE SETUP
  340.  
  341.     if setup_print:
  342.         installed_print_devices = device.getSupportedCUPSDevices(['hp'])  
  343.         log.debug(installed_print_devices)
  344.  
  345.         if not auto and print_uri in installed_print_devices:
  346.             log.warning("One or more print queues already exist for this device: %s." % ', '.join(installed_print_devices[print_uri]))
  347.  
  348.             while True:
  349.                 user_input = raw_input(utils.bold("\nWould you like to install another print queue for this device? (y=yes, n=no*, q=quit) ?" ))
  350.                 user_input = user_input.lower().strip()
  351.  
  352.                 if not user_input:
  353.                     user_input = 'n'
  354.  
  355.                 setup_print = (user_input == 'y')
  356.  
  357.                 if user_input in ('q', 'y', 'n'):
  358.                     break
  359.  
  360.                 log.error("Please enter 'y', 'n' or 'q'")
  361.  
  362.             if user_input == 'q':
  363.                 log.info("OK, done.")
  364.                 sys.exit(0)
  365.  
  366.  
  367.  
  368.     if setup_print:
  369.         log.info(utils.bold("\nPRINT QUEUE SETUP"))
  370.  
  371.         if auto:
  372.             printer_name = default_model
  373.  
  374.         printer_default_model = default_model
  375.  
  376.         # Check for duplicate names
  377.         if device_uri in installed_print_devices and \
  378.             printer_default_model in installed_print_devices[device_uri]:
  379.                 i = 2
  380.                 while True:
  381.                     t = printer_default_model + "_%d" % i
  382.                     if t not in installed_print_devices[device_uri]:
  383.                         printer_default_model += "_%d" % i
  384.                         break
  385.                     i += 1
  386.  
  387.         if not auto:
  388.             if printer_name is None:
  389.                 while True:
  390.                     printer_name = raw_input(utils.bold("\nPlease enter a name for this print queue (m=use model name:'%s'*, q=quit) ?" % printer_default_model))
  391.  
  392.                     if printer_name.lower().strip() == 'q':
  393.                         log.info("OK, done.")
  394.                         sys.exit(0)
  395.  
  396.                     if not printer_name or printer_name.lower().strip() == 'm':
  397.                         printer_name = printer_default_model
  398.  
  399.                     name_ok = True
  400.  
  401.                     if print_uri in installed_print_devices:
  402.                         for d in installed_print_devices[print_uri]:
  403.                             if printer_name in d:
  404.                                 log.error("A print queue with that name already exists. Please enter a different name.")
  405.                                 name_ok = False
  406.                                 break
  407.  
  408.                     for c in printer_name:
  409.                         if c in (' ', '#', '/', '%'):
  410.                             log.error("Invalid character '%s' in printer name. Please enter a name that does not contain this character." % c)
  411.                             name_ok = False
  412.  
  413.                     if name_ok:
  414.                         break
  415.         else:
  416.             printer_name = printer_default_model
  417.  
  418.         log.info("Using queue name: %s" % printer_name)
  419.  
  420.         default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
  421.         stripped_model = default_model.lower().replace('hp-', '').replace('hp_', '')
  422.  
  423.         mins = cups.getPPDFile(stripped_model, ppds)
  424.         x = len(mins)
  425.  
  426.         enter_ppd = False
  427.  
  428.         if x == 0:
  429.             enter_ppd = True
  430.  
  431.         elif x == 1:
  432.             print_ppd = mins.keys()[0]
  433.             log.info("\nFound a possible PPD file: %s" % print_ppd)
  434.             log.info("Desc: %s" % mins[print_ppd])
  435.  
  436.             if not auto:
  437.                 while True:
  438.                     log.info("\nNote: The model number may vary slightly from the actual model number on the device.")
  439.                     user_input = raw_input(utils.bold("\nDoes this PPD file appear to be the correct one (y=yes*, n=no, q=quit) ?"))
  440.                     user_input = user_input.strip().lower()
  441.  
  442.                     if user_input == 'q':
  443.                         log.info("OK, done.")
  444.                         sys.exit(0)
  445.  
  446.                     if not user_input or user_input == 'y':
  447.                         break
  448.  
  449.                     if user_input == 'n':
  450.                         enter_ppd = True
  451.                         break
  452.  
  453.                     log.error("Please enter 'y' or 'n'")
  454.  
  455.         else:
  456.             log.info("")
  457.             log.warn("Found multiple possible PPD files")
  458.  
  459.             max_ppd_filename_size = 0
  460.             for p in mins:
  461.                 max_ppd_filename_size = max(len(p), max_ppd_filename_size)
  462.  
  463.             log.info(utils.bold("\nChoose a PPD file that most closely matches your device:"))
  464.             log.info("(Note: The model number may vary slightly from the actual model number on the device.)\n")
  465.  
  466.             formatter = utils.TextFormatter(
  467.                     (
  468.                         {'width': 4},
  469.                         {'width': max_ppd_filename_size, 'margin': 2},
  470.                         {'width': 40, 'margin': 2},
  471.                     )
  472.                 )
  473.  
  474.             log.info(formatter.compose(("Num.", "PPD Filename", "Description")))
  475.             log.info(formatter.compose(('-'*4, '-'*(max_ppd_filename_size), '-'*40 )))
  476.  
  477.             mins_list = mins.keys()
  478.  
  479.             for y in range(x):
  480.                 log.info(formatter.compose((str(y), mins_list[y], mins[mins_list[y]])))
  481.  
  482.             x += 1
  483.             none_of_the_above = y+1
  484.             log.info(formatter.compose((str(none_of_the_above), "(None of the above match)", '')))
  485.  
  486.             while 1:
  487.                 user_input = raw_input(utils.bold("\nEnter number 0...%d for PPD file (q=quit) ?" % (x-1)))
  488.                 user_input = user_input.strip().lower()
  489.  
  490.                 if user_input == '':
  491.                     log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  492.                     continue
  493.  
  494.                 if user_input == 'q':
  495.                     log.info("OK, done.")
  496.                     sys.exit(0)
  497.  
  498.                 try:
  499.                     i = int(user_input)
  500.                 except ValueError:
  501.                     log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  502.                     continue
  503.  
  504.                 if i == none_of_the_above:
  505.                     enter_ppd = True
  506.                     break
  507.  
  508.                 if i < 0 or i > (x-1):
  509.                     log.warn("Invalid input - enter a value between 0 and %d or 'q' to quit." % (x-1))
  510.                     continue
  511.  
  512.                 break
  513.  
  514.             if not enter_ppd:
  515.                 print_ppd = mins_list[i]
  516.  
  517.         if enter_ppd:
  518.             log.error("Unable to find an appropriate PPD file.")
  519.             enter_ppd = False
  520.  
  521.             while True:
  522.                 user_input = raw_input(utils.bold("\nWould you like to specify the path to the correct PPD file to use (y=yes, n=no*, q=quit) ?"))
  523.                 user_input = user_input.strip().lower()
  524.  
  525.                 if not user_input or user_input in ('q', 'n'):
  526.                     log.info("OK, done.")
  527.                     sys.exit(0)
  528.  
  529.                 if user_input == 'y':
  530.                     enter_ppd = True
  531.                     break
  532.  
  533.                 log.error("Please enter 'y' or 'n'")
  534.  
  535.             if enter_ppd:
  536.                 ok = False
  537.  
  538.                 while True:
  539.                     user_input = raw_input(utils.bold("\nPlease enter the full filesystem path to the PPD file to use (q=quit) :"))
  540.  
  541.                     if user_input.lower().strip() == 'q':
  542.                         log.info("OK, done.")
  543.                         sys.exit(0)
  544.  
  545.                     file_path = user_input
  546.  
  547.                     if os.path.exists(file_path) and os.path.isfile(file_path):
  548.  
  549.                         if file_path.endswith('.gz'):
  550.                             nickname = gzip.GzipFile(file_path, 'r').read(4096)
  551.                         else:
  552.                             nickname = file(file_path, 'r').read(4096)
  553.  
  554.                         try:
  555.                             desc = nickname_pat.search(nickname).group(1)
  556.                         except AttributeError:
  557.                             desc = ''
  558.  
  559.                         if desc:
  560.                             log.info("Description for the file: %s" % desc)
  561.                         else:
  562.                             log.error("No PPD 'NickName' found. This file may not be a valid PPD file.")
  563.  
  564.                         while True:
  565.                             user_input = raw_input(utils.bold("\nUse this file (y=yes*, n=no, q=quit) ?"))
  566.                             user_input = user_input.strip().lower()
  567.  
  568.                             if not user_input or user_input == 'y':
  569.                                 print_ppd = file_path
  570.                                 ok = True
  571.                                 break
  572.  
  573.                             elif user_input == 'q':
  574.                                 log.info("OK, done.")
  575.                                 sys.exit(0)
  576.  
  577.                             elif user_input == 'n':
  578.                                 break
  579.  
  580.                     else:
  581.                         log.error("File not found or not an appropriate (PPD) file.")
  582.  
  583.  
  584.                     if ok:
  585.                         break
  586.  
  587.         if auto:
  588.             location, info = '', 'Automatically setup by HPLIP'
  589.         else:
  590.             while True:
  591.                 location = raw_input(utils.bold("Enter a location description for this printer (q=quit) ?"))
  592.  
  593.                 if location.strip().lower() == 'q':
  594.                     log.info("OK, done.")
  595.                     sys.exit(0)
  596.  
  597.                 # TODO: Validate chars
  598.  
  599.                 break
  600.  
  601.             while True:
  602.                 info = raw_input(utils.bold("Enter additonal information or notes for this printer (q=quit) ?"))
  603.  
  604.                 if info.strip().lower() == 'q':
  605.                     log.info("OK, done.")
  606.                     sys.exit(0)
  607.  
  608.                 # TODO: Validate chars
  609.  
  610.                 break
  611.  
  612.         log.info(utils.bold("\nAdding print queue to CUPS:"))
  613.         log.info("Device URI: %s" % print_uri)
  614.         log.info("Queue name: %s" % printer_name)
  615.         log.info("PPD file: %s" % print_ppd)
  616.         log.info("Location: %s" % location)
  617.         log.info("Information: %s" % info)
  618.  
  619.         log.debug("Restarting CUPS...")
  620.         status, output = utils.run(restart_cups())
  621.         log.debug("Restart CUPS returned: exit=%d output=%s" % (status, output))
  622.  
  623.         if not os.path.exists(print_ppd): # assume foomatic: or some such
  624.             status, status_str = cups.addPrinter(printer_name, print_uri,
  625.                 location, '', print_ppd, info)
  626.         else:
  627.             status, status_str = cups.addPrinter(printer_name, print_uri,
  628.                 location, print_ppd, '', info)
  629.  
  630.         installed_print_devices = device.getSupportedCUPSDevices(['hp']) 
  631.  
  632.         log.debug(installed_print_devices)
  633.  
  634.         if print_uri not in installed_print_devices or \
  635.             printer_name not in installed_print_devices[print_uri]:
  636.  
  637.             log.error("Printer queue setup failed. Please restart CUPS and try again.")
  638.             sys.exit(1)
  639.         else:
  640.             service.sendEvent(hpssd_sock, EVENT_CUPS_QUEUES_CHANGED, device_uri=print_uri)
  641.  
  642.         if username:
  643.             import pwd
  644.             user_path = pwd.getpwnam(username)[5]
  645.             user_config_file = os.path.join(user_path, '.hplip.conf')
  646.  
  647.             if os.path.exists(user_config_file):
  648.                 cfg = Config(user_config_file)
  649.                 cfg.last_used.device_uri = print_uri
  650.  
  651.  
  652.     # ******************************* FAX QUEUE SETUP
  653.  
  654.     if setup_fax:
  655.         try:
  656.             from fax import fax
  657.         except ImportError:
  658.             # This can fail on Python < 2.3 due to the datetime module
  659.             setup_fax = False
  660.             log.warning("Fax setup disabled - Python 2.3+ required.")
  661.  
  662.     log.info("")
  663.  
  664.     if setup_fax:
  665.         log.info(utils.bold("\nFAX QUEUE SETUP"))
  666.         installed_fax_devices = device.getSupportedCUPSDevices(['hpfax'])    
  667.         log.debug(installed_fax_devices)
  668.  
  669.         if not auto and fax_uri in installed_fax_devices:
  670.             log.warning("One or more fax queues already exist for this device: %s." % ', '.join(installed_fax_devices[fax_uri]))
  671.             while True:
  672.                 user_input = raw_input(utils.bold("\nWould you like to install another fax queue for this device? (y=yes, n=no*, q=quit) ?"))
  673.                 user_input = user_input.lower().strip()
  674.  
  675.                 if not user_input:
  676.                     user_input = 'n'
  677.  
  678.                 setup_fax = (user_input == 'y')
  679.  
  680.                 if user_input in ('q', 'y', 'n'):
  681.                     break
  682.  
  683.                 log.error("Please enter 'y', 'n' or 'q'")
  684.  
  685.             if user_input == 'q':
  686.                 log.info("OK, done.")
  687.                 sys.exit(0)
  688.  
  689.  
  690.     if setup_fax:
  691.         #log.info(utils.bold("\nSetting up fax queue..."))
  692.  
  693.         if auto: # or fax_name is None:
  694.             fax_name = default_model + '_fax'
  695.  
  696.         fax_default_model = default_model + '_fax'
  697.  
  698.         # Check for duplicate names
  699.         if fax_uri in installed_fax_devices and \
  700.             fax_default_model in installed_fax_devices[fax_uri]:
  701.                 i = 2
  702.                 while True:
  703.                     t = fax_default_model + "_%d" % i
  704.                     if t not in installed_fax_devices[fax_uri]:
  705.                         fax_default_model += "_%d" % i
  706.                         break
  707.                     i += 1
  708.  
  709.         if not auto:
  710.             if fax_name is None:
  711.                 while True:
  712.                     fax_name = raw_input(utils.bold("\nPlease enter a name for this fax queue (m=use model name:'%s'*, q=quit) ?" % fax_default_model))
  713.  
  714.                     if fax_name.lower().strip() == 'q':
  715.                         log.info("OK, done.")
  716.                         sys.exit(0)
  717.  
  718.                     if not fax_name or fax_name.lower().strip() == 'm':
  719.                         fax_name = fax_default_model
  720.  
  721.                     name_ok = True
  722.  
  723.                     if fax_uri in installed_fax_devices:
  724.                         for d in installed_fax_devices[fax_uri]:
  725.                             if fax_name in d:
  726.                                 log.error("A fax queue with that name already exists. Please enter a different name.")
  727.                                 name_ok = False
  728.                                 break
  729.  
  730.                     for c in fax_name:
  731.                         if c in (' ', '#', '/', '%'):
  732.                             log.error("Invalid character '%s' in fax name. Please enter a name that does not contain this character." % c)
  733.                             name_ok = False
  734.  
  735.                     if name_ok:
  736.                         break
  737.  
  738.         else:
  739.             fax_name = fax_default_model
  740.  
  741.         log.info("Using queue name: %s" % fax_name)
  742.  
  743.         for f in ppds:
  744.             if f.find('HP-Fax') >= 0:
  745.                 fax_ppd = f
  746.                 log.debug("Found PDD file: %s" % fax_ppd)
  747.                 break
  748.         else:
  749.             log.error("Unable to find HP fax PPD file! Please check you HPLIP installation and try again.")
  750.             sys.exit(1)
  751.  
  752.  
  753.         if auto:
  754.             location, info = '', 'Automatically setup by HPLIP'
  755.         else:
  756.             while True:
  757.                 location = raw_input(utils.bold("Enter a location description for this printer (q=quit) ?"))
  758.  
  759.                 if location.strip().lower() == 'q':
  760.                     log.info("OK, done.")
  761.                     sys.exit(0)
  762.  
  763.                 # TODO: Validate chars
  764.  
  765.                 break
  766.  
  767.             while True:
  768.                 info = raw_input(utils.bold("Enter additonal information or notes for this printer (q=quit) ?"))
  769.  
  770.                 if info.strip().lower() == 'q':
  771.                     log.info("OK, done.")
  772.                     sys.exit(0)
  773.  
  774.                 # TODO: Validate chars
  775.  
  776.                 break
  777.  
  778.  
  779.         log.info(utils.bold("\nAdding fax queue to CUPS:"))
  780.         log.info("Device URI: %s" % fax_uri)
  781.         log.info("Queue name: %s" % fax_name)
  782.         log.info("PPD file: %s" % fax_ppd)
  783.         log.info("Location: %s" % location)
  784.         log.info("Information: %s" % info)
  785.  
  786.         cups.addPrinter(fax_name, fax_uri, location, fax_ppd, "", info)
  787.  
  788.         installed_fax_devices = device.getSupportedCUPSDevices(['hpfax']) 
  789.  
  790.         log.debug(installed_fax_devices) 
  791.  
  792.         if fax_uri not in installed_fax_devices or \
  793.             fax_name not in installed_fax_devices[fax_uri]:
  794.  
  795.             log.error("Fax queue setup failed. Please restart CUPS and try again.")
  796.             sys.exit(1)
  797.         else:
  798.             service.sendEvent(hpssd_sock, EVENT_CUPS_QUEUES_CHANGED, device_uri=fax_uri)
  799.  
  800.  
  801.     # ******************************* FAX HEADER SETUP
  802.  
  803.         if auto:
  804.             setup_fax = False
  805.         else:
  806.             while True:
  807.                 user_input = raw_input(utils.bold("\nWould you like to perform fax header setup (y=yes*, n=no, q=quit) ?"))
  808.                 user_input = user_input.strip().lower()
  809.  
  810.                 if user_input == 'q':
  811.                     log.info("OK, done.")
  812.                     sys.exit(0)
  813.  
  814.                 if not user_input:
  815.                     user_input = 'y'
  816.  
  817.                 setup_fax = (user_input == 'y')
  818.  
  819.                 if user_input in ('y', 'n', 'q'):
  820.                     break
  821.  
  822.                 log.error("Please enter 'y' or 'n'")
  823.  
  824.         if setup_fax:
  825.             d = fax.FaxDevice(fax_uri)
  826.  
  827.             try:
  828.                 d.open()
  829.             except Error:
  830.                 log.error("Unable to communicate with the device. Please check the device and try again.")
  831.             else:
  832.                 try:
  833.                     tries = 0
  834.                     ok = True
  835.  
  836.                     while True:
  837.                         tries += 1
  838.  
  839.                         try:
  840.                             current_phone_num = d.getPhoneNum()
  841.                             current_station_name = d.getStationName()
  842.                         except Error:
  843.                             log.error("Could not communicate with device. Device may be busy. Please wait for retry...")
  844.                             time.sleep(5)
  845.                             ok = False
  846.  
  847.                             if tries > 12:
  848.                                 break
  849.  
  850.                         else:
  851.                             ok = True
  852.                             break
  853.  
  854.                     if ok:
  855.                         while True:
  856.                             if current_phone_num:
  857.                                 phone_num = raw_input(utils.bold("\nEnter the fax phone number for this device (c=use current:'%s'*, q=quit) ?" % current_phone_num))
  858.                             else:
  859.                                 phone_num = raw_input(utils.bold("\nEnter the fax phone number for this device (q=quit) ?"))
  860.  
  861.                             if current_phone_num and (not phone_num or phone_num.strip().lower() == 'c'):
  862.                                 phone_num = current_phone_num
  863.  
  864.                             if phone_num.strip().lower() == 'q':
  865.                                 log.info("OK, done.")
  866.                                 sys.exit(0)
  867.  
  868.                             if len(phone_num) > 50:
  869.                                 log.error("Phone number length is too long (>50 characters). Please enter a shorter number.")
  870.                                 continue
  871.  
  872.                             ok = True
  873.                             for x in phone_num:
  874.                                 if x not in '0123456789-(+) ':
  875.                                     log.error("Invalid characters in phone number. Please only use 0-9, -, (, +, and )")
  876.                                     ok = False
  877.                                     break
  878.  
  879.                             if not ok:
  880.                                 continue
  881.  
  882.                             break
  883.  
  884.                         while True:
  885.                             if current_station_name:
  886.                                 station_name = raw_input(utils.bold("\nEnter the name and/or company for this device (c=use current:'%s'*, q=quit) ?" % current_station_name))
  887.                             else:
  888.                                 station_name = raw_input(utils.bold("\nEnter the name and/or company for this device (q=quit) ?"))
  889.  
  890.                             if current_station_name and (not station_name or station_name.strip().lower() == 'c'):
  891.                                 station_name = current_station_name
  892.  
  893.                             if station_name.strip().lower() == 'q':
  894.                                 log.info("OK, done.")
  895.                                 sys.exit(0)
  896.  
  897.                             if len(station_name) > 50:
  898.                                 log.error("Name/company length is too long (>50 characters). Please enter a shorter name/company.")
  899.                                 continue
  900.  
  901.                             break
  902.  
  903.  
  904.                         try:
  905.                             d.setStationName(station_name)
  906.                             d.setPhoneNum(phone_num)
  907.                         except Error:
  908.                             log.error("Could not communicate with device. Device may be busy.")
  909.                         else:
  910.                             log.info("\nParameters sent to device.")
  911.  
  912.                 finally:
  913.                     d.close()
  914.  
  915.  
  916.     # ******************************* TEST PAGE
  917.  
  918.     if setup_print:
  919.         print_test_page = False
  920.  
  921.         if auto:
  922.             if testpage_in_auto_mode:
  923.                 print_test_page = True
  924.         else:
  925.             while True:
  926.                 user_input = raw_input(utils.bold("\nWould you like to print a test page (y=yes*, n=no, q=quit) ?"))
  927.                 user_input = user_input.strip().lower()
  928.  
  929.                 if not user_input:
  930.                     user_input = 'y'
  931.  
  932.                 if user_input == 'q':
  933.                     log.info("OK, done.")
  934.                     sys.exit(0)
  935.  
  936.                 print_test_page = (user_input == 'y')
  937.  
  938.                 if user_input in ('y', 'n', 'q'):
  939.                     break
  940.  
  941.                 log.error("Please enter 'y' or 'n'")
  942.  
  943.         if print_test_page:
  944.             path = utils.which('hp-testpage')
  945.  
  946.             if len(path) > 0:
  947.                 cmd = 'hp-testpage -d%s' % print_uri
  948.             else:
  949.                 cmd = 'python ./testpage.py -d%s' % print_uri
  950.  
  951.             os.system(cmd)
  952.  
  953. log.info("Done.")
  954. sys.exit(0)
  955.