~ubuntu-branches/ubuntu/raring/hplip/raring-proposed

« back to all changes in this revision

Viewing changes to .pc/simple-scan-as-default.dpatch/base/utils.py

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-05-26 11:20:39 UTC
  • mfrom: (1.5.6) (31.1.3 precise)
  • Revision ID: package-import@ubuntu.com-20120526112039-bevxczegxnbyr5m7
Tags: 3.12.4-1
* New upstream release
* Switch to source/format 3.0 (quilt) - drop dpatch
* Refreshed debian/patches
* dh_autoreconf debian/autogen.sh & set local-options single-debian-patch
* Update to debian/compat -> 9
* Fix "hardened build flags" patch from Moritz - thanks (Closes: #667828)
* Fix "duplex descriptor uninitialized" patch from Matej (Closes: #583273)
* Fix "please migrate to kde-runtime" patch from Pino (Closes: #666544)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
# (c) Copyright 2001-2009 Hewlett-Packard Development Company, L.P.
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation; either version 2 of the License, or
 
8
# (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
18
#
 
19
# Author: Don Welch, Naga Samrat Chowdary Narla, Goutam Kodu, Amarnath Chitumalla
 
20
#
 
21
# Thanks to Henrique M. Holschuh <hmh@debian.org> for various security patches
 
22
#
 
23
 
 
24
from __future__ import generators
 
25
 
 
26
# Std Lib
 
27
import sys
 
28
import os
 
29
from subprocess import Popen, PIPE
 
30
import grp
 
31
import fnmatch
 
32
import tempfile
 
33
import socket
 
34
import struct
 
35
import select
 
36
import time
 
37
import fcntl
 
38
import errno
 
39
import stat
 
40
import string
 
41
import commands # TODO: Replace with subprocess (commands is deprecated in Python 3.0)
 
42
import cStringIO
 
43
import re
 
44
import xml.parsers.expat as expat
 
45
import getpass
 
46
import locale
 
47
import htmlentitydefs
 
48
import urllib
 
49
 
 
50
try:
 
51
    import platform
 
52
    platform_avail = True
 
53
except ImportError:
 
54
    platform_avail = False
 
55
 
 
56
# Local
 
57
from g import *
 
58
from codes import *
 
59
import pexpect
 
60
 
 
61
BIG_ENDIAN = 0
 
62
LITTLE_ENDIAN = 1
 
63
 
 
64
def addgroup():
 
65
    lis = []
 
66
    try:
 
67
        fp=open('/etc/cups/cupsd.conf')
 
68
    except IOError:
 
69
        try:
 
70
            if "root" != grp.getgrgid(os.stat('/etc/cups/cupsd.conf').st_gid).gr_name:
 
71
                return [grp.getgrgid(os.stat('/etc/cups/cupsd.conf').st_gid).gr_name]
 
72
        except OSError:
 
73
            return lis
 
74
 
 
75
    try:
 
76
        lis = ((re.findall('SystemGroup [\w* ]*',fp.read()))[0].replace('SystemGroup ','')).split(' ')
 
77
    except IndexError:
 
78
        return lis
 
79
 
 
80
    if 'root' in lis:
 
81
        lis.remove('root')
 
82
    fp.close()
 
83
    return lis
 
84
 
 
85
def list_to_string(lis):
 
86
    if len(lis) == 0:
 
87
        return ""
 
88
    if len(lis) == 1:
 
89
        return str("\""+lis[0]+"\"")
 
90
    if len(lis) >= 1:
 
91
        return "\""+"\", \"".join(lis)+"\" and \""+str(lis.pop())+"\""
 
92
        
 
93
def lock(f):
 
94
    log.debug("Locking: %s" % f.name)
 
95
    try:
 
96
        fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
 
97
        return True
 
98
    except (IOError, OSError):
 
99
        log.debug("Failed to unlock %s." % f.name)
 
100
        return False
 
101
 
 
102
 
 
103
def unlock(f):
 
104
    if f is not None:
 
105
        log.debug("Unlocking: %s" % f.name)
 
106
        try:
 
107
            fcntl.flock(f.fileno(), fcntl.LOCK_UN)
 
108
            os.remove(f.name)
 
109
        except (IOError, OSError):
 
110
            pass
 
111
 
 
112
 
 
113
def lock_app(application, suppress_error=False):
 
114
    dir = prop.user_dir
 
115
    if os.geteuid() == 0:
 
116
        dir = '/var'
 
117
 
 
118
    elif not os.path.exists(dir):
 
119
        os.makedirs(dir)
 
120
 
 
121
    lock_file = os.path.join(dir, '.'.join([application, 'lock']))
 
122
    try:
 
123
        lock_file_f = open(lock_file, "w")
 
124
    except IOError:
 
125
        if not suppress_error:
 
126
            log.error("Unable to open %s lock file." % lock_file)
 
127
        return False, None
 
128
 
 
129
    #log.debug("Locking file: %s" % lock_file)
 
130
 
 
131
    if not lock(lock_file_f):
 
132
        if not suppress_error:
 
133
            log.error("Unable to lock %s. Is %s already running?" % (lock_file, application))
 
134
        return False, None
 
135
 
 
136
    return True, lock_file_f
 
137
 
 
138
 
 
139
#xml_basename_pat = re.compile(r"""HPLIP-(\d*)_(\d*)_(\d*).xml""", re.IGNORECASE)
 
140
 
 
141
 
 
142
def Translator(frm='', to='', delete='', keep=None):
 
143
    allchars = string.maketrans('','')
 
144
 
 
145
    if len(to) == 1:
 
146
        to = to * len(frm)
 
147
    trans = string.maketrans(frm, to)
 
148
 
 
149
    if keep is not None:
 
150
        delete = allchars.translate(allchars, keep.translate(allchars, delete))
 
151
 
 
152
    def callable(s):
 
153
        return s.translate(trans, delete)
 
154
 
 
155
    return callable
 
156
 
 
157
 
 
158
def to_bool_str(s, default='0'):
 
159
    """ Convert an arbitrary 0/1/T/F/Y/N string to a normalized string 0/1."""
 
160
    if isinstance(s, str) and s:
 
161
        if s[0].lower() in ['1', 't', 'y']:
 
162
            return u'1'
 
163
        elif s[0].lower() in ['0', 'f', 'n']:
 
164
            return u'0'
 
165
 
 
166
    return default
 
167
 
 
168
def to_bool(s, default=False):
 
169
    """ Convert an arbitrary 0/1/T/F/Y/N string to a boolean True/False value."""
 
170
    if isinstance(s, str) and s:
 
171
        if s[0].lower() in ['1', 't', 'y']:
 
172
            return True
 
173
        elif s[0].lower() in ['0', 'f', 'n']:
 
174
            return False
 
175
    elif isinstance(s, bool):
 
176
        return s
 
177
 
 
178
    return default
 
179
 
 
180
 
 
181
def walkFiles(root, recurse=True, abs_paths=False, return_folders=False, pattern='*', path=None):
 
182
    if path is None:
 
183
        path = root
 
184
 
 
185
    try:
 
186
        names = os.listdir(root)
 
187
    except os.error:
 
188
        raise StopIteration
 
189
 
 
190
    pattern = pattern or '*'
 
191
    pat_list = pattern.split(';')
 
192
 
 
193
    for name in names:
 
194
        fullname = os.path.normpath(os.path.join(root, name))
 
195
 
 
196
        for pat in pat_list:
 
197
            if fnmatch.fnmatch(name, pat):
 
198
                if return_folders or not os.path.isdir(fullname):
 
199
                    if abs_paths:
 
200
                        yield fullname
 
201
                    else:
 
202
                        try:
 
203
                            yield os.path.basename(fullname)
 
204
                        except ValueError:
 
205
                            yield fullname
 
206
 
 
207
        #if os.path.islink(fullname):
 
208
        #    fullname = os.path.realpath(os.readlink(fullname))
 
209
 
 
210
        if recurse and os.path.isdir(fullname): # or os.path.islink(fullname):
 
211
            for f in walkFiles(fullname, recurse, abs_paths, return_folders, pattern, path):
 
212
                yield f
 
213
 
 
214
 
 
215
def is_path_writable(path):
 
216
    if os.path.exists(path):
 
217
        s = os.stat(path)
 
218
        mode = s[stat.ST_MODE] & 0777
 
219
 
 
220
        if mode & 02:
 
221
            return True
 
222
        elif s[stat.ST_GID] == os.getgid() and mode & 020:
 
223
            return True
 
224
        elif s[stat.ST_UID] == os.getuid() and mode & 0200:
 
225
            return True
 
226
 
 
227
    return False
 
228
 
 
229
 
 
230
# Provides the TextFormatter class for formatting text into columns.
 
231
# Original Author: Hamish B Lawson, 1999
 
232
# Modified by: Don Welch, 2003
 
233
class TextFormatter:
 
234
 
 
235
    LEFT  = 0
 
236
    CENTER = 1
 
237
    RIGHT  = 2
 
238
 
 
239
    def __init__(self, colspeclist):
 
240
        self.columns = []
 
241
        for colspec in colspeclist:
 
242
            self.columns.append(Column(**colspec))
 
243
 
 
244
    def compose(self, textlist, add_newline=False):
 
245
        numlines = 0
 
246
        textlist = list(textlist)
 
247
        if len(textlist) != len(self.columns):
 
248
            log.error("Formatter: Number of text items does not match columns")
 
249
            return
 
250
        for text, column in map(None, textlist, self.columns):
 
251
            column.wrap(text)
 
252
            numlines = max(numlines, len(column.lines))
 
253
        complines = [''] * numlines
 
254
        for ln in range(numlines):
 
255
            for column in self.columns:
 
256
                complines[ln] = complines[ln] + column.getline(ln)
 
257
        if add_newline:
 
258
            return '\n'.join(complines) + '\n'
 
259
        else:
 
260
            return '\n'.join(complines)
 
261
 
 
262
class Column:
 
263
 
 
264
    def __init__(self, width=78, alignment=TextFormatter.LEFT, margin=0):
 
265
        self.width = width
 
266
        self.alignment = alignment
 
267
        self.margin = margin
 
268
        self.lines = []
 
269
 
 
270
    def align(self, line):
 
271
        if self.alignment == TextFormatter.CENTER:
 
272
            return line.center(self.width)
 
273
        elif self.alignment == TextFormatter.RIGHT:
 
274
            return line.rjust(self.width)
 
275
        else:
 
276
            return line.ljust(self.width)
 
277
 
 
278
    def wrap(self, text):
 
279
        self.lines = []
 
280
        words = []
 
281
        for word in text.split():
 
282
            if word <= self.width:
 
283
                words.append(word)
 
284
            else:
 
285
                for i in range(0, len(word), self.width):
 
286
                    words.append(word[i:i+self.width])
 
287
        if not len(words): return
 
288
        current = words.pop(0)
 
289
        for word in words:
 
290
            increment = 1 + len(word)
 
291
            if len(current) + increment > self.width:
 
292
                self.lines.append(self.align(current))
 
293
                current = word
 
294
            else:
 
295
                current = current + ' ' + word
 
296
        self.lines.append(self.align(current))
 
297
 
 
298
    def getline(self, index):
 
299
        if index < len(self.lines):
 
300
            return ' '*self.margin + self.lines[index]
 
301
        else:
 
302
            return ' ' * (self.margin + self.width)
 
303
 
 
304
 
 
305
 
 
306
class Stack:
 
307
    def __init__(self):
 
308
        self.stack = []
 
309
 
 
310
    def pop(self):
 
311
        return self.stack.pop()
 
312
 
 
313
    def push(self, value):
 
314
        self.stack.append(value)
 
315
 
 
316
    def as_list(self):
 
317
        return self.stack
 
318
 
 
319
    def clear(self):
 
320
        self.stack = []
 
321
 
 
322
    def __len__(self):
 
323
        return len(self.stack)
 
324
 
 
325
 
 
326
 
 
327
class Queue(Stack):
 
328
    def __init__(self):
 
329
        Stack.__init__(self)
 
330
 
 
331
    def get(self):
 
332
        return self.stack.pop(0)
 
333
 
 
334
    def put(self, value):
 
335
        Stack.push(self, value)
 
336
 
 
337
 
 
338
 
 
339
# RingBuffer class
 
340
# Source: Python Cookbook 1st Ed., sec. 5.18, pg. 201
 
341
# Credit: Sebastien Keim
 
342
# License: Modified BSD
 
343
class RingBuffer:
 
344
    def __init__(self, size_max=50):
 
345
        self.max = size_max
 
346
        self.data = []
 
347
 
 
348
    def append(self,x):
 
349
        """append an element at the end of the buffer"""
 
350
        self.data.append(x)
 
351
 
 
352
        if len(self.data) == self.max:
 
353
            self.cur = 0
 
354
            self.__class__ = RingBufferFull
 
355
 
 
356
    def replace(self, x):
 
357
        """replace the last element instead off appending"""
 
358
        self.data[-1] = x
 
359
 
 
360
    def get(self):
 
361
        """ return a list of elements from the oldest to the newest"""
 
362
        return self.data
 
363
 
 
364
 
 
365
class RingBufferFull:
 
366
    def __init__(self, n):
 
367
        #raise "you should use RingBuffer"
 
368
        pass
 
369
 
 
370
    def append(self, x):
 
371
        self.data[self.cur] = x
 
372
        self.cur = (self.cur+1) % self.max
 
373
 
 
374
    def replace(self, x):
 
375
        # back up 1 position to previous location
 
376
        self.cur = (self.cur-1) % self.max
 
377
        self.data[self.cur] = x
 
378
        # setup for next item
 
379
        self.cur = (self.cur+1) % self.max
 
380
 
 
381
    def get(self):
 
382
        return self.data[self.cur:] + self.data[:self.cur]
 
383
 
 
384
 
 
385
 
 
386
def sort_dict_by_value(d):
 
387
    """ Returns the keys of dictionary d sorted by their values """
 
388
    items=d.items()
 
389
    backitems=[[v[1],v[0]] for v in items]
 
390
    backitems.sort()
 
391
    return [backitems[i][1] for i in range(0, len(backitems))]
 
392
 
 
393
 
 
394
def commafy(val):
 
395
    return unicode(locale.format("%d", val, grouping=True))
 
396
 
 
397
 
 
398
def format_bytes(s, show_bytes=False):
 
399
    if s < 1024:
 
400
        return ''.join([commafy(s), ' B'])
 
401
    elif 1024 < s < 1048576:
 
402
        if show_bytes:
 
403
            return ''.join([unicode(round(s/1024.0, 1)) , u' KB (',  commafy(s), ')'])
 
404
        else:
 
405
            return ''.join([unicode(round(s/1024.0, 1)) , u' KB'])
 
406
    elif 1048576 < s < 1073741824:
 
407
        if show_bytes:
 
408
            return ''.join([unicode(round(s/1048576.0, 1)), u' MB (',  commafy(s), ')'])
 
409
        else:
 
410
            return ''.join([unicode(round(s/1048576.0, 1)), u' MB'])
 
411
    else:
 
412
        if show_bytes:
 
413
            return ''.join([unicode(round(s/1073741824.0, 1)), u' GB (',  commafy(s), ')'])
 
414
        else:
 
415
            return ''.join([unicode(round(s/1073741824.0, 1)), u' GB'])
 
416
 
 
417
 
 
418
 
 
419
try:
 
420
    make_temp_file = tempfile.mkstemp # 2.3+
 
421
except AttributeError:
 
422
    def make_temp_file(suffix='', prefix='', dir='', text=False): # pre-2.3
 
423
        path = tempfile.mktemp(suffix)
 
424
        fd = os.open(path, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
 
425
        return ( os.fdopen( fd, 'w+b' ), path )
 
426
 
 
427
 
 
428
 
 
429
def which(command, return_full_path=False):
 
430
    path = os.getenv('PATH').split(':')
 
431
 
 
432
    # Add these paths for Fedora
 
433
    path.append('/sbin')
 
434
    path.append('/usr/sbin')
 
435
    path.append('/usr/local/sbin')
 
436
 
 
437
    found_path = ''
 
438
    for p in path:
 
439
        try:
 
440
            files = os.listdir(p)
 
441
        except OSError:
 
442
            continue
 
443
        else:
 
444
            if command in files:
 
445
                found_path = p
 
446
                break
 
447
 
 
448
    if return_full_path:
 
449
        if found_path:
 
450
            return os.path.join(found_path, command)
 
451
        else:
 
452
            return ''
 
453
    else:
 
454
        return found_path
 
455
 
 
456
 
 
457
class UserSettings(object): # Note: Deprecated after 2.8.8 in Qt4 (see ui4/ui_utils.py)
 
458
    def __init__(self):
 
459
        self.load()
 
460
 
 
461
    def loadDefaults(self):
 
462
        # Print
 
463
        self.cmd_print = ''
 
464
        path = which('hp-print')
 
465
 
 
466
        if len(path) > 0:
 
467
            self.cmd_print = 'hp-print -p%PRINTER%'
 
468
        else:
 
469
            path = which('kprinter')
 
470
            if len(path) > 0:
 
471
                self.cmd_print = 'kprinter -P%PRINTER% --system cups'
 
472
            else:
 
473
                path = which('gtklp')
 
474
                if len(path) > 0:
 
475
                    self.cmd_print = 'gtklp -P%PRINTER%'
 
476
                else:
 
477
                    path = which('xpp')
 
478
                    if len(path) > 0:
 
479
                        self.cmd_print = 'xpp -P%PRINTER%'
 
480
 
 
481
        # Scan
 
482
        self.cmd_scan = ''
 
483
        path = which('xsane')
 
484
 
 
485
        if len(path) > 0:
 
486
            self.cmd_scan = 'xsane -V %SANE_URI%'
 
487
        else:
 
488
            path = which('kooka')
 
489
            if len(path) > 0:
 
490
                self.cmd_scan = 'kooka'
 
491
            else:
 
492
                path = which('xscanimage')
 
493
                if len(path) > 0:
 
494
                    self.cmd_scan = 'xscanimage'
 
495
 
 
496
        # Photo Card
 
497
        path = which('hp-unload')
 
498
 
 
499
        if len(path):
 
500
            self.cmd_pcard = 'hp-unload -d %DEVICE_URI%'
 
501
        else:
 
502
            self.cmd_pcard = 'python %HOME%/unload.py -d %DEVICE_URI%'
 
503
 
 
504
        # Copy
 
505
        path = which('hp-makecopies')
 
506
 
 
507
        if len(path):
 
508
            self.cmd_copy = 'hp-makecopies -d %DEVICE_URI%'
 
509
        else:
 
510
            self.cmd_copy = 'python %HOME%/makecopies.py -d %DEVICE_URI%'
 
511
 
 
512
        # Fax
 
513
        path = which('hp-sendfax')
 
514
 
 
515
        if len(path):
 
516
            self.cmd_fax = 'hp-sendfax -d %FAX_URI%'
 
517
        else:
 
518
            self.cmd_fax = 'python %HOME%/sendfax.py -d %FAX_URI%'
 
519
 
 
520
        # Fax Address Book
 
521
        path = which('hp-fab')
 
522
 
 
523
        if len(path):
 
524
            self.cmd_fab = 'hp-fab'
 
525
        else:
 
526
            self.cmd_fab = 'python %HOME%/fab.py'
 
527
 
 
528
    def load(self):
 
529
        self.loadDefaults()
 
530
        log.debug("Loading user settings...")
 
531
        self.auto_refresh = to_bool(user_conf.get('refresh', 'enable', '0'))
 
532
 
 
533
        try:
 
534
            self.auto_refresh_rate = int(user_conf.get('refresh', 'rate', '30'))
 
535
        except ValueError:
 
536
            self.auto_refresh_rate = 30 # (secs)
 
537
 
 
538
        try:
 
539
            self.auto_refresh_type = int(user_conf.get('refresh', 'type', '0'))
 
540
        except ValueError:
 
541
            self.auto_refresh_type = 0 # refresh 1 (1=refresh all)
 
542
 
 
543
        self.cmd_print = user_conf.get('commands', 'prnt', self.cmd_print)
 
544
        self.cmd_scan = user_conf.get('commands', 'scan', self.cmd_scan)
 
545
        self.cmd_pcard = user_conf.get('commands', 'pcard', self.cmd_pcard)
 
546
        self.cmd_copy = user_conf.get('commands', 'cpy', self.cmd_copy)
 
547
        self.cmd_fax = user_conf.get('commands', 'fax', self.cmd_fax)
 
548
        self.cmd_fab = user_conf.get('commands', 'fab', self.cmd_fab)
 
549
 
 
550
        self.upgrade_notify= to_bool(user_conf.get('upgrade', 'notify_upgrade', '0'))
 
551
        self.upgrade_last_update_time = int(user_conf.get('upgrade','last_upgraded_time', '0'))
 
552
        self.upgrade_pending_update_time =int(user_conf.get('upgrade', 'pending_upgrade_time', '0'))
 
553
        self.latest_available_version=str(user_conf.get('upgrade', 'latest_available_version',''))
 
554
        self.debug()
 
555
 
 
556
    def debug(self):
 
557
        log.debug("Print command: %s" % self.cmd_print)
 
558
        log.debug("PCard command: %s" % self.cmd_pcard)
 
559
        log.debug("Fax command: %s" % self.cmd_fax)
 
560
        log.debug("FAB command: %s" % self.cmd_fab)
 
561
        log.debug("Copy command: %s " % self.cmd_copy)
 
562
        log.debug("Scan command: %s" % self.cmd_scan)
 
563
        log.debug("Auto refresh: %s" % self.auto_refresh)
 
564
        log.debug("Auto refresh rate: %s" % self.auto_refresh_rate)
 
565
        log.debug("Auto refresh type: %s" % self.auto_refresh_type)
 
566
        log.debug("Upgrade notification:%d"  %self.upgrade_notify)
 
567
        log.debug("Last Installed time:%d" %self.upgrade_last_update_time)
 
568
        log.debug("Next scheduled installation time:%d" % self.upgrade_pending_update_time)
 
569
 
 
570
 
 
571
    def save(self):
 
572
        log.debug("Saving user settings...")
 
573
        user_conf.set('commands', 'prnt', self.cmd_print)
 
574
        user_conf.set('commands', 'pcard', self.cmd_pcard)
 
575
        user_conf.set('commands', 'fax', self.cmd_fax)
 
576
        user_conf.set('commands', 'scan', self.cmd_scan)
 
577
        user_conf.set('commands', 'cpy', self.cmd_copy)
 
578
        user_conf.set('refresh', 'enable',self.auto_refresh)
 
579
        user_conf.set('refresh', 'rate', self.auto_refresh_rate)
 
580
        user_conf.set('refresh', 'type', self.auto_refresh_type)
 
581
        user_conf.set('upgrade', 'notify_upgrade', self.upgrade_notify)
 
582
        user_conf.set('upgrade','last_upgraded_time', self.upgrade_last_update_time)
 
583
        user_conf.set('upgrade', 'pending_upgrade_time', self.upgrade_pending_update_time)
 
584
        user_conf.set('upgrade', 'latest_available_version', self.latest_available_version)
 
585
 
 
586
        self.debug()
 
587
 
 
588
 
 
589
 
 
590
def no_qt_message_gtk():
 
591
    try:
 
592
        import gtk
 
593
        w = gtk.Window()
 
594
        dialog = gtk.MessageDialog(w, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
 
595
                                   gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
 
596
                                   "PyQt not installed. GUI not available. Please check that the PyQt package is installed. Exiting.")
 
597
        dialog.run()
 
598
        dialog.destroy()
 
599
 
 
600
    except ImportError:
 
601
        log.error("PyQt not installed. GUI not available. Please check that the PyQt package is installed. Exiting.")
 
602
 
 
603
 
 
604
def canEnterGUIMode(): # qt3
 
605
    if not prop.gui_build:
 
606
        log.warn("GUI mode disabled in build.")
 
607
        return False
 
608
 
 
609
    elif not os.getenv('DISPLAY'):
 
610
        log.warn("No display found.")
 
611
        return False
 
612
 
 
613
    elif not checkPyQtImport():
 
614
        log.warn("Qt/PyQt 3 initialization failed.")
 
615
        return False
 
616
 
 
617
    return True
 
618
 
 
619
 
 
620
def canEnterGUIMode4(): # qt4
 
621
    if not prop.gui_build:
 
622
        log.warn("GUI mode disabled in build.")
 
623
        return False
 
624
 
 
625
    elif not os.getenv('DISPLAY'):
 
626
        log.warn("No display found.")
 
627
        return False
 
628
 
 
629
    elif not checkPyQtImport4():
 
630
        log.warn("Qt/PyQt 4 initialization failed.")
 
631
        return False
 
632
 
 
633
    return True
 
634
 
 
635
 
 
636
def checkPyQtImport(): # qt3
 
637
    # PyQt
 
638
    try:
 
639
        import qt
 
640
    except ImportError:
 
641
        if os.getenv('DISPLAY') and os.getenv('STARTED_FROM_MENU'):
 
642
            no_qt_message_gtk()
 
643
 
 
644
        log.error("PyQt not installed. GUI not available. Exiting.")
 
645
        return False
 
646
 
 
647
    # check version of Qt
 
648
    qtMajor = int(qt.qVersion().split('.')[0])
 
649
 
 
650
    if qtMajor < MINIMUM_QT_MAJOR_VER:
 
651
 
 
652
        log.error("Incorrect version of Qt installed. Ver. 3.0.0 or greater required.")
 
653
        return False
 
654
 
 
655
    #check version of PyQt
 
656
    try:
 
657
        pyqtVersion = qt.PYQT_VERSION_STR
 
658
    except AttributeError:
 
659
        pyqtVersion = qt.PYQT_VERSION
 
660
 
 
661
    while pyqtVersion.count('.') < 2:
 
662
        pyqtVersion += '.0'
 
663
 
 
664
    (maj_ver, min_ver, pat_ver) = pyqtVersion.split('.')
 
665
 
 
666
    if pyqtVersion.find('snapshot') >= 0:
 
667
        log.warning("A non-stable snapshot version of PyQt is installed.")
 
668
    else:
 
669
        try:
 
670
            maj_ver = int(maj_ver)
 
671
            min_ver = int(min_ver)
 
672
            pat_ver = int(pat_ver)
 
673
        except ValueError:
 
674
            maj_ver, min_ver, pat_ver = 0, 0, 0
 
675
 
 
676
        if maj_ver < MINIMUM_PYQT_MAJOR_VER or \
 
677
            (maj_ver == MINIMUM_PYQT_MAJOR_VER and min_ver < MINIMUM_PYQT_MINOR_VER):
 
678
            log.error("This program may not function properly with the version of PyQt that is installed (%d.%d.%d)." % (maj_ver, min_ver, pat_ver))
 
679
            log.error("Incorrect version of pyQt installed. Ver. %d.%d or greater required." % (MINIMUM_PYQT_MAJOR_VER, MINIMUM_PYQT_MINOR_VER))
 
680
            log.error("This program will continue, but you may experience errors, crashes or other problems.")
 
681
            return True
 
682
 
 
683
    return True
 
684
 
 
685
 
 
686
def checkPyQtImport4():
 
687
    try:
 
688
        import PyQt4
 
689
    except ImportError:
 
690
        return False
 
691
    else:
 
692
        return True
 
693
 
 
694
 
 
695
try:
 
696
    from string import Template # will fail in Python <= 2.3
 
697
except ImportError:
 
698
    # Code from Python 2.4 string.py
 
699
    #import re as _re
 
700
 
 
701
    class _multimap:
 
702
        """Helper class for combining multiple mappings.
 
703
 
 
704
        Used by .{safe_,}substitute() to combine the mapping and keyword
 
705
        arguments.
 
706
        """
 
707
        def __init__(self, primary, secondary):
 
708
            self._primary = primary
 
709
            self._secondary = secondary
 
710
 
 
711
        def __getitem__(self, key):
 
712
            try:
 
713
                return self._primary[key]
 
714
            except KeyError:
 
715
                return self._secondary[key]
 
716
 
 
717
 
 
718
    class _TemplateMetaclass(type):
 
719
        pattern = r"""
 
720
        %(delim)s(?:
 
721
          (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
 
722
          (?P<named>%(id)s)      |   # delimiter and a Python identifier
 
723
          {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
 
724
          (?P<invalid>)              # Other ill-formed delimiter exprs
 
725
        )
 
726
        """
 
727
 
 
728
        def __init__(cls, name, bases, dct):
 
729
            super(_TemplateMetaclass, cls).__init__(name, bases, dct)
 
730
            if 'pattern' in dct:
 
731
                pattern = cls.pattern
 
732
            else:
 
733
                pattern = _TemplateMetaclass.pattern % {
 
734
                    'delim' : re.escape(cls.delimiter),
 
735
                    'id'    : cls.idpattern,
 
736
                    }
 
737
            cls.pattern = re.compile(pattern, re.IGNORECASE | re.VERBOSE)
 
738
 
 
739
 
 
740
    class Template:
 
741
        """A string class for supporting $-substitutions."""
 
742
        __metaclass__ = _TemplateMetaclass
 
743
 
 
744
        delimiter = '$'
 
745
        idpattern = r'[_a-z][_a-z0-9]*'
 
746
 
 
747
        def __init__(self, template):
 
748
            self.template = template
 
749
 
 
750
        # Search for $$, $identifier, ${identifier}, and any bare $'s
 
751
        def _invalid(self, mo):
 
752
            i = mo.start('invalid')
 
753
            lines = self.template[:i].splitlines(True)
 
754
            if not lines:
 
755
                colno = 1
 
756
                lineno = 1
 
757
            else:
 
758
                colno = i - len(''.join(lines[:-1]))
 
759
                lineno = len(lines)
 
760
            raise ValueError('Invalid placeholder in string: line %d, col %d' %
 
761
                             (lineno, colno))
 
762
 
 
763
        def substitute(self, *args, **kws):
 
764
            if len(args) > 1:
 
765
                raise TypeError('Too many positional arguments')
 
766
            if not args:
 
767
                mapping = kws
 
768
            elif kws:
 
769
                mapping = _multimap(kws, args[0])
 
770
            else:
 
771
                mapping = args[0]
 
772
            # Helper function for .sub()
 
773
            def convert(mo):
 
774
                # Check the most common path first.
 
775
                named = mo.group('named') or mo.group('braced')
 
776
                if named is not None:
 
777
                    val = mapping[named]
 
778
                    # We use this idiom instead of str() because the latter will
 
779
                    # fail if val is a Unicode containing non-ASCII characters.
 
780
                    return '%s' % val
 
781
                if mo.group('escaped') is not None:
 
782
                    return self.delimiter
 
783
                if mo.group('invalid') is not None:
 
784
                    self._invalid(mo)
 
785
                raise ValueError('Unrecognized named group in pattern',
 
786
                                 self.pattern)
 
787
            return self.pattern.sub(convert, self.template)
 
788
 
 
789
 
 
790
        def safe_substitute(self, *args, **kws):
 
791
            if len(args) > 1:
 
792
                raise TypeError('Too many positional arguments')
 
793
            if not args:
 
794
                mapping = kws
 
795
            elif kws:
 
796
                mapping = _multimap(kws, args[0])
 
797
            else:
 
798
                mapping = args[0]
 
799
            # Helper function for .sub()
 
800
            def convert(mo):
 
801
                named = mo.group('named')
 
802
                if named is not None:
 
803
                    try:
 
804
                        # We use this idiom instead of str() because the latter
 
805
                        # will fail if val is a Unicode containing non-ASCII
 
806
                        return '%s' % mapping[named]
 
807
                    except KeyError:
 
808
                        return self.delimiter + named
 
809
                braced = mo.group('braced')
 
810
                if braced is not None:
 
811
                    try:
 
812
                        return '%s' % mapping[braced]
 
813
                    except KeyError:
 
814
                        return self.delimiter + '{' + braced + '}'
 
815
                if mo.group('escaped') is not None:
 
816
                    return self.delimiter
 
817
                if mo.group('invalid') is not None:
 
818
                    return self.delimiter
 
819
                raise ValueError('Unrecognized named group in pattern',
 
820
                                 self.pattern)
 
821
            return self.pattern.sub(convert, self.template)
 
822
 
 
823
 
 
824
 
 
825
#cat = lambda _ : Template(_).substitute(sys._getframe(1).f_globals, **sys._getframe(1).f_locals)
 
826
 
 
827
def cat(s):
 
828
    globals = sys._getframe(1).f_globals.copy()
 
829
    if 'self' in globals:
 
830
        del globals['self']
 
831
 
 
832
    locals = sys._getframe(1).f_locals.copy()
 
833
    if 'self' in locals:
 
834
        del locals['self']
 
835
 
 
836
    return Template(s).substitute(sys._getframe(1).f_globals, **locals)
 
837
 
 
838
 
 
839
identity = string.maketrans('','')
 
840
unprintable = identity.translate(identity, string.printable)
 
841
 
 
842
 
 
843
def printable(s):
 
844
    return s.translate(identity, unprintable)
 
845
 
 
846
 
 
847
def any(S,f=lambda x:x):
 
848
    for x in S:
 
849
        if f(x): return True
 
850
    return False
 
851
 
 
852
 
 
853
def all(S,f=lambda x:x):
 
854
    for x in S:
 
855
        if not f(x): return False
 
856
    return True
 
857
 
 
858
 
 
859
BROWSERS = ['firefox', 'mozilla', 'konqueror', 'galeon', 'skipstone'] # in preferred order
 
860
BROWSER_OPTS = {'firefox': '-new-window', 'mozilla' : '', 'konqueror': '', 'galeon': '-w', 'skipstone': ''}
 
861
 
 
862
 
 
863
def find_browser():
 
864
    if platform_avail and platform.system() == 'Darwin':
 
865
        return "open"
 
866
    else:
 
867
        for b in BROWSERS:
 
868
            if which(b):
 
869
                return b
 
870
        else:
 
871
            return None
 
872
 
 
873
 
 
874
def openURL(url, use_browser_opts=True):
 
875
    if platform_avail and platform.system() == 'Darwin':
 
876
        cmd = 'open "%s"' % url
 
877
        log.debug(cmd)
 
878
        os.system(cmd)
 
879
    else:
 
880
        for b in BROWSERS:
 
881
            bb = which(b)
 
882
            if bb:
 
883
                bb = os.path.join(bb, b)
 
884
                if use_browser_opts:
 
885
                    cmd = """%s %s "%s" &""" % (bb, BROWSER_OPTS[b], url)
 
886
                else:
 
887
                    cmd = """%s "%s" &""" % (bb, url)
 
888
                log.debug(cmd)
 
889
                os.system(cmd)
 
890
                break
 
891
        else:
 
892
            log.warn("Unable to open URL: %s" % url)
 
893
 
 
894
 
 
895
def uniqueList(input):
 
896
    temp = []
 
897
    [temp.append(i) for i in input if not temp.count(i)]
 
898
    return temp
 
899
 
 
900
 
 
901
def list_move_up(l, m, cmp=None):
 
902
    if cmp is None:
 
903
        f = lambda x: l[x] == m
 
904
    else:
 
905
        f = lambda x: cmp(l[x], m)
 
906
 
 
907
    for i in range(1, len(l)):
 
908
        if f(i):
 
909
            l[i-1], l[i] = l[i], l[i-1]
 
910
 
 
911
 
 
912
def list_move_down(l, m, cmp=None):
 
913
    if cmp is None:
 
914
        f = lambda x: l[x] == m
 
915
    else:
 
916
        f = lambda x: cmp(l[x], m)
 
917
 
 
918
    for i in range(len(l)-2, -1, -1):
 
919
        if f(i):
 
920
            l[i], l[i+1] = l[i+1], l[i]
 
921
 
 
922
 
 
923
 
 
924
class XMLToDictParser:
 
925
    def __init__(self):
 
926
        self.stack = []
 
927
        self.data = {}
 
928
        self.last_start = ''
 
929
 
 
930
    def startElement(self, name, attrs):
 
931
        #print "START:", name, attrs
 
932
        self.stack.append(unicode(name).lower())
 
933
        self.last_start = unicode(name).lower()
 
934
 
 
935
        if len(attrs):
 
936
            for a in attrs:
 
937
                self.stack.append(unicode(a).lower())
 
938
                self.addData(attrs[a])
 
939
                self.stack.pop()
 
940
 
 
941
    def endElement(self, name):
 
942
        if name.lower() == self.last_start:
 
943
            self.addData('')
 
944
 
 
945
        #print "END:", name
 
946
        self.stack.pop()
 
947
 
 
948
    def charData(self, data):
 
949
        data = unicode(data).strip()
 
950
 
 
951
        if data and self.stack:
 
952
            self.addData(data)
 
953
 
 
954
    def addData(self, data):
 
955
        #print "DATA:", data
 
956
        self.last_start = ''
 
957
        try:
 
958
            data = int(data)
 
959
        except ValueError:
 
960
            data = unicode(data)
 
961
 
 
962
        stack_str = '-'.join(self.stack)
 
963
        stack_str_0 = '-'.join([stack_str, '0'])
 
964
 
 
965
        try:
 
966
            self.data[stack_str]
 
967
        except KeyError:
 
968
            try:
 
969
                self.data[stack_str_0]
 
970
            except KeyError:
 
971
                self.data[stack_str] = data
 
972
            else:
 
973
                j = 2
 
974
                while True:
 
975
                    try:
 
976
                        self.data['-'.join([stack_str, unicode(j)])]
 
977
                    except KeyError:
 
978
                        self.data['-'.join([stack_str, unicode(j)])] = data
 
979
                        break
 
980
                    j += 1
 
981
 
 
982
        else:
 
983
            self.data[stack_str_0] = self.data[stack_str]
 
984
            self.data['-'.join([stack_str, '1'])] = data
 
985
            del self.data[stack_str]
 
986
 
 
987
 
 
988
    def parseXML(self, text):
 
989
        parser = expat.ParserCreate()
 
990
        parser.StartElementHandler = self.startElement
 
991
        parser.EndElementHandler = self.endElement
 
992
        parser.CharacterDataHandler = self.charData
 
993
        parser.Parse(text.encode('utf-8'), True)
 
994
        return self.data
 
995
 
 
996
 
 
997
def dquote(s):
 
998
    return ''.join(['"', s, '"'])
 
999
 
 
1000
 
 
1001
# Python 2.2.x compatibility functions (strip() family with char argument added in Python 2.2.3)
 
1002
if sys.hexversion < 0x020203f0:
 
1003
    def xlstrip(s, chars=' '):
 
1004
        i = 0
 
1005
        for c, i in zip(s, range(len(s))):
 
1006
            if c not in chars:
 
1007
                break
 
1008
 
 
1009
        return s[i:]
 
1010
 
 
1011
    def xrstrip(s, chars=' '):
 
1012
        return xreverse(xlstrip(xreverse(s), chars))
 
1013
 
 
1014
    def xreverse(s):
 
1015
        l = list(s)
 
1016
        l.reverse()
 
1017
        return ''.join(l)
 
1018
 
 
1019
    def xstrip(s, chars=' '):
 
1020
        return xreverse(xlstrip(xreverse(xlstrip(s, chars)), chars))
 
1021
 
 
1022
else:
 
1023
    xlstrip = string.lstrip
 
1024
    xrstrip = string.rstrip
 
1025
    xstrip = string.strip
 
1026
 
 
1027
 
 
1028
def getBitness():
 
1029
    if platform_avail:
 
1030
        return int(platform.architecture()[0][:-3])
 
1031
    else:
 
1032
        return struct.calcsize("P") << 3
 
1033
 
 
1034
 
 
1035
def getProcessor():
 
1036
    if platform_avail:
 
1037
        return platform.machine().replace(' ', '_').lower() # i386, i686, power_macintosh, etc.
 
1038
    else:
 
1039
        return "i686" # TODO: Need a fix here
 
1040
 
 
1041
 
 
1042
def getEndian():
 
1043
    if sys.byteorder == 'big':
 
1044
        return BIG_ENDIAN
 
1045
    else:
 
1046
        return LITTLE_ENDIAN
 
1047
 
 
1048
 
 
1049
def get_password():
 
1050
    return getpass.getpass("Enter password: ")
 
1051
 
 
1052
def get_password_ui(pswd_msg=''):
 
1053
    fp = open("/etc/hp/hplip.conf", "r")
 
1054
    qt = "qt3"
 
1055
    for line in fp:
 
1056
        if string.find(line, "qt4") is not -1 and string.find(line, "yes") is not -1:
 
1057
            qt = "qt4"
 
1058
    fp.close()
 
1059
    if qt is "qt4":
 
1060
        from ui4.setupdialog import showPasswordUI
 
1061
        if pswd_msg == '':
 
1062
            username, password = showPasswordUI("Your HP Device requires to install HP proprietary plugin\nPlease enter root/superuser password to continue", "root", False)
 
1063
        else:
 
1064
            username, password = showPasswordUI(pswd_msg, "root", False)
 
1065
    if qt is "qt3":
 
1066
        from ui.setupform import showPasswordUI
 
1067
        if pswd_msg == '':
 
1068
            username, password = showPasswordUI("Your HP Device requires to install HP proprietary plugin\nPlease enter root/superuser password to continue", "root", False)
 
1069
        else:
 
1070
            username, password = showPasswordUI(pswd_msg, "root", False)
 
1071
    return  password
 
1072
 
 
1073
def run(cmd, log_output=True, password_func=get_password, timeout=1, spinner=True, pswd_msg=''):
 
1074
    output = cStringIO.StringIO()
 
1075
 
 
1076
    try:
 
1077
        child = pexpect.spawn(cmd, timeout=timeout)
 
1078
    except pexpect.ExceptionPexpect:
 
1079
        return -1, ''
 
1080
 
 
1081
    try:
 
1082
        while True:
 
1083
            if spinner:
 
1084
                update_spinner()
 
1085
 
 
1086
            i = child.expect(["[pP]assword:", pexpect.EOF, pexpect.TIMEOUT])
 
1087
 
 
1088
            if child.before:
 
1089
                output.write(child.before)
 
1090
                if log_output:
 
1091
                    log.debug(child.before)
 
1092
 
 
1093
            if i == 0: # Password:
 
1094
                if password_func is not None:
 
1095
                    if password_func == "get_password_ui":
 
1096
                        child.sendline(get_password_ui(pswd_msg))
 
1097
                    else:
 
1098
                        child.sendline(password_func())
 
1099
                else:
 
1100
                    child.sendline(get_password())
 
1101
                
 
1102
 
 
1103
            elif i == 1: # EOF
 
1104
                break
 
1105
 
 
1106
            elif i == 2: # TIMEOUT
 
1107
                continue
 
1108
 
 
1109
 
 
1110
    except Exception, e:
 
1111
        log.error("Exception: %s" % e)
 
1112
    if spinner:
 
1113
        cleanup_spinner()
 
1114
    child.close()
 
1115
 
 
1116
    return child.exitstatus, output.getvalue()
 
1117
 
 
1118
 
 
1119
def expand_range(ns): # ns -> string repr. of numeric range, e.g. "1-4, 7, 9-12"
 
1120
    """Credit: Jean Brouwers, comp.lang.python 16-7-2004
 
1121
       Convert a string representation of a set of ranges into a
 
1122
       list of ints, e.g.
 
1123
       u"1-4, 7, 9-12" --> [1,2,3,4,7,9,10,11,12]
 
1124
    """
 
1125
    fs = []
 
1126
    for n in ns.split(u','):
 
1127
        n = n.strip()
 
1128
        r = n.split('-')
 
1129
        if len(r) == 2:  # expand name with range
 
1130
            h = r[0].rstrip(u'0123456789')  # header
 
1131
            r[0] = r[0][len(h):]
 
1132
             # range can't be empty
 
1133
            if not (r[0] and r[1]):
 
1134
                raise ValueError, 'empty range: ' + n
 
1135
             # handle leading zeros
 
1136
            if r[0] == u'0' or r[0][0] != u'0':
 
1137
                h += '%d'
 
1138
            else:
 
1139
                w = [len(i) for i in r]
 
1140
                if w[1] > w[0]:
 
1141
                   raise ValueError, 'wide range: ' + n
 
1142
                h += u'%%0%dd' % max(w)
 
1143
             # check range
 
1144
            r = [int(i, 10) for i in r]
 
1145
            if r[0] > r[1]:
 
1146
               raise ValueError, 'bad range: ' + n
 
1147
            for i in range(r[0], r[1]+1):
 
1148
                fs.append(h % i)
 
1149
        else:  # simple name
 
1150
            fs.append(n)
 
1151
 
 
1152
     # remove duplicates
 
1153
    fs = dict([(n, i) for i, n in enumerate(fs)]).keys()
 
1154
     # convert to ints and sort
 
1155
    fs = [int(x) for x in fs if x]
 
1156
    fs.sort()
 
1157
 
 
1158
    return fs
 
1159
 
 
1160
 
 
1161
def collapse_range(x): # x --> sorted list of ints
 
1162
    """ Convert a list of integers into a string
 
1163
        range representation:
 
1164
        [1,2,3,4,7,9,10,11,12] --> u"1-4,7,9-12"
 
1165
    """
 
1166
    if not x:
 
1167
        return ''
 
1168
 
 
1169
    s, c, r = [str(x[0])], x[0], False
 
1170
 
 
1171
    for i in x[1:]:
 
1172
        if i == (c+1):
 
1173
            r = True
 
1174
        else:
 
1175
            if r:
 
1176
                s.append(u'-%s,%s' % (c,i))
 
1177
                r = False
 
1178
            else:
 
1179
                s.append(u',%s' % i)
 
1180
 
 
1181
        c = i
 
1182
 
 
1183
    if r:
 
1184
        s.append(u'-%s' % i)
 
1185
 
 
1186
    return ''.join(s)
 
1187
 
 
1188
 
 
1189
def createSequencedFilename(basename, ext, dir=None, digits=3):
 
1190
    if dir is None:
 
1191
        dir = os.getcwd()
 
1192
 
 
1193
    m = 0
 
1194
    for f in walkFiles(dir, recurse=False, abs_paths=False, return_folders=False, pattern='*', path=None):
 
1195
        r, e = os.path.splitext(f)
 
1196
 
 
1197
        if r.startswith(basename) and ext == e:
 
1198
            try:
 
1199
                i = int(r[len(basename):])
 
1200
            except ValueError:
 
1201
                continue
 
1202
            else:
 
1203
                m = max(m, i)
 
1204
 
 
1205
    return os.path.join(dir, "%s%0*d%s" % (basename, digits, m+1, ext))
 
1206
 
 
1207
 
 
1208
def validate_language(lang, default='en_US'):
 
1209
    if lang is None:
 
1210
        loc, encoder = locale.getdefaultlocale()
 
1211
    else:
 
1212
        lang = lang.lower().strip()
 
1213
        for loc, ll in supported_locales.items():
 
1214
            if lang in ll:
 
1215
                break
 
1216
        else:
 
1217
            loc = 'en_US'
 
1218
            log.warn("Unknown lang/locale. Using default of %s." % loc)
 
1219
 
 
1220
    return loc
 
1221
 
 
1222
 
 
1223
def gen_random_uuid():
 
1224
    try:
 
1225
        import uuid # requires Python 2.5+
 
1226
        return str(uuid.uuid4())
 
1227
 
 
1228
    except ImportError:
 
1229
        uuidgen = which("uuidgen")
 
1230
        if uuidgen:
 
1231
            uuidgen = os.path.join(uuidgen, "uuidgen")
 
1232
            return commands.getoutput(uuidgen) # TODO: Replace with subprocess (commands is deprecated in Python 3.0)
 
1233
        else:
 
1234
            return ''
 
1235
 
 
1236
 
 
1237
class RestTableFormatter(object):
 
1238
    def __init__(self, header=None):
 
1239
        self.header = header # tuple of strings
 
1240
        self.rows = [] # list of tuples
 
1241
 
 
1242
    def add(self, row_data): # tuple of strings
 
1243
        self.rows.append(row_data)
 
1244
 
 
1245
    def output(self, w):
 
1246
        if self.rows:
 
1247
            num_cols = len(self.rows[0])
 
1248
            for r in self.rows:
 
1249
                if len(r) != num_cols:
 
1250
                    log.error("Invalid number of items in row: %s" % r)
 
1251
                    return
 
1252
 
 
1253
            if len(self.header) != num_cols:
 
1254
                log.error("Invalid number of items in header.")
 
1255
 
 
1256
            col_widths = []
 
1257
            for x, c in enumerate(self.header):
 
1258
                max_width = len(c)
 
1259
                for r in self.rows:
 
1260
                    max_width = max(max_width, len(r[x]))
 
1261
 
 
1262
                col_widths.append(max_width+2)
 
1263
 
 
1264
            x = '+'
 
1265
            for c in col_widths:
 
1266
                x = ''.join([x, '-' * (c+2), '+'])
 
1267
 
 
1268
            x = ''.join([x, '\n'])
 
1269
            w.write(x)
 
1270
 
 
1271
            # header
 
1272
            if self.header:
 
1273
                x = '|'
 
1274
                for i, c in enumerate(col_widths):
 
1275
                    x = ''.join([x, ' ', self.header[i], ' ' * (c+1-len(self.header[i])), '|'])
 
1276
 
 
1277
                x = ''.join([x, '\n'])
 
1278
                w.write(x)
 
1279
 
 
1280
                x = '+'
 
1281
                for c in col_widths:
 
1282
                    x = ''.join([x, '=' * (c+2), '+'])
 
1283
 
 
1284
                x = ''.join([x, '\n'])
 
1285
                w.write(x)
 
1286
 
 
1287
            # data rows
 
1288
            for j, r in enumerate(self.rows):
 
1289
                x = '|'
 
1290
                for i, c in enumerate(col_widths):
 
1291
                    x = ''.join([x, ' ', self.rows[j][i], ' ' * (c+1-len(self.rows[j][i])), '|'])
 
1292
 
 
1293
                x = ''.join([x, '\n'])
 
1294
                w.write(x)
 
1295
 
 
1296
                x = '+'
 
1297
                for c in col_widths:
 
1298
                    x = ''.join([x, '-' * (c+2), '+'])
 
1299
 
 
1300
                x = ''.join([x, '\n'])
 
1301
                w.write(x)
 
1302
 
 
1303
        else:
 
1304
            log.error("No data rows")
 
1305
 
 
1306
 
 
1307
def mixin(cls):
 
1308
    import inspect
 
1309
 
 
1310
    locals = inspect.stack()[1][0].f_locals
 
1311
    if "__module__" not in locals:
 
1312
        raise TypeError("Must call mixin() from within class def.")
 
1313
 
 
1314
    dict = cls.__dict__.copy()
 
1315
    dict.pop("__doc__", None)
 
1316
    dict.pop("__module__", None)
 
1317
 
 
1318
    locals.update(dict)
 
1319
 
 
1320
 
 
1321
 
 
1322
# TODO: Move usage stuff to to base/module/Module class
 
1323
 
 
1324
 
 
1325
 # ------------------------- Usage Help
 
1326
USAGE_OPTIONS = ("[OPTIONS]", "", "heading", False)
 
1327
USAGE_LOGGING1 = ("Set the logging level:", "-l<level> or --logging=<level>", 'option', False)
 
1328
USAGE_LOGGING2 = ("", "<level>: none, info\*, error, warn, debug (\*default)", "option", False)
 
1329
USAGE_LOGGING3 = ("Run in debug mode:", "-g (same as option: -ldebug)", "option", False)
 
1330
USAGE_LOGGING_PLAIN = ("Output plain text only:", "-t", "option", False)
 
1331
USAGE_ARGS = ("[PRINTER|DEVICE-URI]", "", "heading", False)
 
1332
USAGE_ARGS2 = ("[PRINTER]", "", "heading", False)
 
1333
USAGE_DEVICE = ("To specify a device-URI:", "-d<device-uri> or --device=<device-uri>", "option", False)
 
1334
USAGE_PRINTER = ("To specify a CUPS printer:", "-p<printer> or --printer=<printer>", "option", False)
 
1335
USAGE_BUS1 = ("Bus to probe (if device not specified):", "-b<bus> or --bus=<bus>", "option", False)
 
1336
USAGE_BUS2 = ("", "<bus>: cups\*, usb\*, net, bt, fw, par\* (\*defaults) (Note: bt and fw not supported in this release.)", 'option', False)
 
1337
USAGE_HELP = ("This help information:", "-h or --help", "option", True)
 
1338
USAGE_SPACE = ("", "", "space", False)
 
1339
USAGE_EXAMPLES = ("Examples:", "", "heading", False)
 
1340
USAGE_NOTES = ("Notes:", "", "heading", False)
 
1341
USAGE_STD_NOTES1 = ("If device or printer is not specified, the local device bus is probed and the program enters interactive mode.", "", "note", False)
 
1342
USAGE_STD_NOTES2 = ("If -p\* is specified, the default CUPS printer will be used.", "", "note", False)
 
1343
USAGE_SEEALSO = ("See Also:", "", "heading", False)
 
1344
USAGE_LANGUAGE = ("Set the language:", "-q <lang> or --lang=<lang>. Use -q? or --lang=? to see a list of available language codes.", "option", False)
 
1345
USAGE_LANGUAGE2 = ("Set the language:", "--lang=<lang>. Use --lang=? to see a list of available language codes.", "option", False)
 
1346
USAGE_MODE = ("[MODE]", "", "header", False)
 
1347
USAGE_NON_INTERACTIVE_MODE = ("Run in non-interactive mode:", "-n or --non-interactive", "option", False)
 
1348
USAGE_GUI_MODE = ("Run in graphical UI mode:", "-u or --gui (Default)", "option", False)
 
1349
USAGE_INTERACTIVE_MODE = ("Run in interactive mode:", "-i or --interactive", "option", False)
 
1350
 
 
1351
if sys_conf.get('configure', 'ui-toolkit', 'qt3') == 'qt3':
 
1352
    USAGE_USE_QT3 = ("Use Qt3:",  "--qt3 (Default)",  "option",  False)
 
1353
    USAGE_USE_QT4 = ("Use Qt4:",  "--qt4",  "option",  False)
 
1354
else:
 
1355
    USAGE_USE_QT3 = ("Use Qt3:",  "--qt3",  "option",  False)
 
1356
    USAGE_USE_QT4 = ("Use Qt4:",  "--qt4 (Default)",  "option",  False)
 
1357
 
 
1358
 
 
1359
 
 
1360
 
 
1361
def ttysize(): # TODO: Move to base/tui
 
1362
    ln1 = commands.getoutput('stty -a').splitlines()[0]
 
1363
    vals = {'rows':None, 'columns':None}
 
1364
    for ph in ln1.split(';'):
 
1365
        x = ph.split()
 
1366
        if len(x) == 2:
 
1367
            vals[x[0]] = x[1]
 
1368
            vals[x[1]] = x[0]
 
1369
    try:
 
1370
        rows, cols = int(vals['rows']), int(vals['columns'])
 
1371
    except TypeError:
 
1372
        rows, cols = 25, 80
 
1373
 
 
1374
    return rows, cols
 
1375
 
 
1376
 
 
1377
def usage_formatter(override=0): # TODO: Move to base/module/Module class
 
1378
    rows, cols = ttysize()
 
1379
 
 
1380
    if override:
 
1381
        col1 = override
 
1382
        col2 = cols - col1 - 8
 
1383
    else:
 
1384
        col1 = int(cols / 3) - 8
 
1385
        col2 = cols - col1 - 8
 
1386
 
 
1387
    return TextFormatter(({'width': col1, 'margin' : 2},
 
1388
                            {'width': col2, 'margin' : 2},))
 
1389
 
 
1390
 
 
1391
def format_text(text_list, typ='text', title='', crumb='', version=''): # TODO: Move to base/module/Module class
 
1392
    """
 
1393
    Format usage text in multiple formats:
 
1394
        text: for --help in the console
 
1395
        rest: for conversion with rst2web for the website
 
1396
        man: for manpages
 
1397
    """
 
1398
    if typ == 'text':
 
1399
        formatter = usage_formatter()
 
1400
 
 
1401
        for line in text_list:
 
1402
            text1, text2, format, trailing_space = line
 
1403
 
 
1404
            # remove any reST/man escapes
 
1405
            text1 = text1.replace("\\", "")
 
1406
            text2 = text2.replace("\\", "")
 
1407
 
 
1408
            if format == 'summary':
 
1409
                log.info(log.bold(text1))
 
1410
                log.info("")
 
1411
 
 
1412
            elif format in ('para', 'name', 'seealso'):
 
1413
                log.info(text1)
 
1414
 
 
1415
                if trailing_space:
 
1416
                    log.info("")
 
1417
 
 
1418
            elif format in ('heading', 'header'):
 
1419
                log.info(log.bold(text1))
 
1420
 
 
1421
            elif format in ('option', 'example'):
 
1422
                log.info(formatter.compose((text1, text2), trailing_space))
 
1423
 
 
1424
            elif format == 'note':
 
1425
                if text1.startswith(' '):
 
1426
                    log.info('\t' + text1.lstrip())
 
1427
                else:
 
1428
                    log.info(text1)
 
1429
 
 
1430
            elif format == 'space':
 
1431
                log.info("")
 
1432
 
 
1433
        log.info("")
 
1434
 
 
1435
 
 
1436
    elif typ == 'rest':
 
1437
        opt_colwidth1, opt_colwidth2 = 0, 0
 
1438
        exmpl_colwidth1, exmpl_colwidth2 = 0, 0
 
1439
        note_colwidth1, note_colwidth2 = 0, 0
 
1440
 
 
1441
        for line in text_list:
 
1442
            text1, text2, format, trailing_space = line
 
1443
 
 
1444
            if format  == 'option':
 
1445
                opt_colwidth1 = max(len(text1), opt_colwidth1)
 
1446
                opt_colwidth2 = max(len(text2), opt_colwidth2)
 
1447
 
 
1448
            elif format == 'example':
 
1449
                exmpl_colwidth1 = max(len(text1), exmpl_colwidth1)
 
1450
                exmpl_colwidth2 = max(len(text2), exmpl_colwidth2)
 
1451
 
 
1452
            elif format == 'note':
 
1453
                note_colwidth1 = max(len(text1), note_colwidth1)
 
1454
                note_colwidth2 = max(len(text2), note_colwidth2)
 
1455
 
 
1456
        opt_colwidth1 += 4
 
1457
        opt_colwidth2 += 4
 
1458
        exmpl_colwidth1 += 4
 
1459
        exmpl_colwidth2 += 4
 
1460
        note_colwidth1 += 4
 
1461
        note_colwidth2 += 4
 
1462
        opt_tablewidth = opt_colwidth1 + opt_colwidth2
 
1463
        exmpl_tablewidth = exmpl_colwidth1 + exmpl_colwidth2
 
1464
        note_tablewidth = note_colwidth1 + note_colwidth2
 
1465
 
 
1466
        # write the rst2web header
 
1467
        log.info("""restindex
 
1468
page-title: %s
 
1469
crumb: %s
 
1470
format: rest
 
1471
file-extension: html
 
1472
encoding: utf8
 
1473
/restindex\n""" % (title, crumb))
 
1474
 
 
1475
        t = "%s: %s (ver. %s)" % (crumb, title, version)
 
1476
        log.info(t)
 
1477
        log.info("="*len(t))
 
1478
        log.info("")
 
1479
 
 
1480
        links = []
 
1481
        needs_header = False
 
1482
        for line in text_list:
 
1483
            text1, text2, format, trailing_space = line
 
1484
 
 
1485
            if format == 'seealso':
 
1486
                links.append(text1)
 
1487
                text1 = "`%s`_" % text1
 
1488
 
 
1489
            len1, len2 = len(text1), len(text2)
 
1490
 
 
1491
            if format == 'summary':
 
1492
                log.info(''.join(["**", text1, "**"]))
 
1493
                log.info("")
 
1494
 
 
1495
            elif format in ('para', 'name'):
 
1496
                log.info("")
 
1497
                log.info(text1)
 
1498
                log.info("")
 
1499
 
 
1500
            elif format in ('heading', 'header'):
 
1501
 
 
1502
                log.info("")
 
1503
                log.info("**" + text1 + "**")
 
1504
                log.info("")
 
1505
                needs_header = True
 
1506
 
 
1507
            elif format == 'option':
 
1508
                if needs_header:
 
1509
                    log.info(".. class:: borderless")
 
1510
                    log.info("")
 
1511
                    log.info(''.join(["+", "-"*opt_colwidth1, "+", "-"*opt_colwidth2, "+"]))
 
1512
                    needs_header = False
 
1513
 
 
1514
                if text1 and '`_' not in text1:
 
1515
                    log.info(''.join(["| *", text1, '*', " "*(opt_colwidth1-len1-3), "|", text2, " "*(opt_colwidth2-len2), "|"]))
 
1516
                elif text1:
 
1517
                    log.info(''.join(["|", text1, " "*(opt_colwidth1-len1), "|", text2, " "*(opt_colwidth2-len2), "|"]))
 
1518
                else:
 
1519
                    log.info(''.join(["|", " "*(opt_colwidth1), "|", text2, " "*(opt_colwidth2-len2), "|"]))
 
1520
 
 
1521
                log.info(''.join(["+", "-"*opt_colwidth1, "+", "-"*opt_colwidth2, "+"]))
 
1522
 
 
1523
            elif format == 'example':
 
1524
                if needs_header:
 
1525
                    log.info(".. class:: borderless")
 
1526
                    log.info("")
 
1527
                    log.info(''.join(["+", "-"*exmpl_colwidth1, "+", "-"*exmpl_colwidth2, "+"]))
 
1528
                    needs_header = False
 
1529
 
 
1530
                if text1 and '`_' not in text1:
 
1531
                    log.info(''.join(["| *", text1, '*', " "*(exmpl_colwidth1-len1-3), "|", text2, " "*(exmpl_colwidth2-len2), "|"]))
 
1532
                elif text1:
 
1533
                    log.info(''.join(["|", text1, " "*(exmpl_colwidth1-len1), "|", text2, " "*(exmpl_colwidth2-len2), "|"]))
 
1534
                else:
 
1535
                    log.info(''.join(["|", " "*(exmpl_colwidth1), "|", text2, " "*(exmpl_colwidth2-len2), "|"]))
 
1536
 
 
1537
                log.info(''.join(["+", "-"*exmpl_colwidth1, "+", "-"*exmpl_colwidth2, "+"]))
 
1538
 
 
1539
            elif format == 'seealso':
 
1540
                if text1 and '`_' not in text1:
 
1541
                    log.info(text1)
 
1542
 
 
1543
 
 
1544
            elif format == 'note':
 
1545
                if needs_header:
 
1546
                    log.info(".. class:: borderless")
 
1547
                    log.info("")
 
1548
                    log.info(''.join(["+", "-"*note_colwidth1, "+", "-"*note_colwidth2, "+"]))
 
1549
                    needs_header = False
 
1550
 
 
1551
                if text1.startswith(' '):
 
1552
                    log.info(''.join(["|", " "*(note_tablewidth+1), "|"]))
 
1553
 
 
1554
                log.info(''.join(["|", text1, " "*(note_tablewidth-len1+1), "|"]))
 
1555
                log.info(''.join(["+", "-"*note_colwidth1, "+", "-"*note_colwidth2, "+"]))
 
1556
 
 
1557
            elif format == 'space':
 
1558
                log.info("")
 
1559
 
 
1560
        for l in links:
 
1561
            log.info("\n.. _`%s`: %s.html\n" % (l, l.replace('hp-', '')))
 
1562
 
 
1563
        log.info("")
 
1564
 
 
1565
    elif typ == 'man':
 
1566
        log.info('.TH "%s" 1 "%s" Linux "User Manuals"' % (crumb, version))
 
1567
        log.info(".SH NAME\n%s \- %s" % (crumb, title))
 
1568
 
 
1569
        for line in text_list:
 
1570
            text1, text2, format, trailing_space = line
 
1571
 
 
1572
            text1 = text1.replace("\\*", "*")
 
1573
            text2 = text2.replace("\\*", "*")
 
1574
 
 
1575
            len1, len2 = len(text1), len(text2)
 
1576
 
 
1577
            if format == 'summary':
 
1578
                log.info(".SH SYNOPSIS")
 
1579
                log.info(".B %s" % text1.replace('Usage:', ''))
 
1580
 
 
1581
            elif format == 'name':
 
1582
                log.info(".SH DESCRIPTION\n%s" % text1)
 
1583
 
 
1584
            elif format in ('option', 'example', 'note'):
 
1585
                if text1:
 
1586
                    log.info('.IP "%s"\n%s' % (text1, text2))
 
1587
                else:
 
1588
                    log.info(text2)
 
1589
 
 
1590
            elif format in ('header', 'heading'):
 
1591
                log.info(".SH %s" % text1.upper().replace(':', '').replace('[', '').replace(']', ''))
 
1592
 
 
1593
            elif format in ('seealso, para'):
 
1594
                log.info(text1)
 
1595
 
 
1596
        log.info(".SH AUTHOR")
 
1597
        log.info("HPLIP (Hewlett-Packard Linux Imaging and Printing) is an")
 
1598
        log.info("HP developed solution for printing, scanning, and faxing with")
 
1599
        log.info("HP inkjet and laser based printers in Linux.")
 
1600
 
 
1601
        log.info(".SH REPORTING BUGS")
 
1602
        log.info("The HPLIP Launchpad.net site")
 
1603
        log.info(".B https://launchpad.net/hplip")
 
1604
        log.info("is available to get help, report")
 
1605
        log.info("bugs, make suggestions, discuss the HPLIP project or otherwise")
 
1606
        log.info("contact the HPLIP Team.")
 
1607
 
 
1608
        log.info(".SH COPYRIGHT")
 
1609
        log.info("Copyright (c) 2001-14 Hewlett-Packard Development Company, L.P.")
 
1610
        log.info(".LP")
 
1611
        log.info("This software comes with ABSOLUTELY NO WARRANTY.")
 
1612
        log.info("This is free software, and you are welcome to distribute it")
 
1613
        log.info("under certain conditions. See COPYING file for more details.")
 
1614
 
 
1615
        log.info("")
 
1616
 
 
1617
 
 
1618
def log_title(program_name, version, show_ver=True): # TODO: Move to base/module/Module class
 
1619
    log.info("")
 
1620
 
 
1621
    if show_ver:
 
1622
        log.info(log.bold("HP Linux Imaging and Printing System (ver. %s)" % prop.version))
 
1623
    else:
 
1624
        log.info(log.bold("HP Linux Imaging and Printing System"))
 
1625
 
 
1626
    log.info(log.bold("%s ver. %s" % (program_name, version)))
 
1627
    log.info("")
 
1628
    log.info("Copyright (c) 2001-14 Hewlett-Packard Development Company, LP")
 
1629
    log.info("This software comes with ABSOLUTELY NO WARRANTY.")
 
1630
    log.info("This is free software, and you are welcome to distribute it")
 
1631
    log.info("under certain conditions. See COPYING file for more details.")
 
1632
    log.info("")
 
1633
 
 
1634
 
 
1635
def ireplace(old, search, replace):
 
1636
    regex = '(?i)' + re.escape(search)
 
1637
    return re.sub(regex, replace, old)
 
1638
 
 
1639
 
 
1640
def su_sudo():
 
1641
    su_sudo_str = None
 
1642
 
 
1643
    if which('kdesu'):
 
1644
        su_sudo_str = 'kdesu -- %s'
 
1645
 
 
1646
    elif utils.which('/usr/lib/kde4/libexec/kdesu'):
 
1647
        su_sudo_str = '/usr/lib/kde4/libexec/kdesu -- %s'
 
1648
 
 
1649
    elif utils.which('kdesudo'):
 
1650
        su_sudo_str = 'kdesudo -- %s'
 
1651
 
 
1652
    elif which('gnomesu'):
 
1653
        su_sudo_str = 'gnomesu -c "%s"'
 
1654
 
 
1655
    elif which('gksu'):
 
1656
        su_sudo_str = 'gksu "%s"'
 
1657
    
 
1658
    elif which('su'):
 
1659
        su_sudo_str = 'su'
 
1660
 
 
1661
    return su_sudo_str
 
1662
 
 
1663
# This function returns the distro name and distro version. 
 
1664
#This is provided to check on Fedora 14 in pkit.py file for Plugin-installation. 
 
1665
#is_su variable is used to provide a check on Fedora 8 
 
1666
def os_release():
 
1667
    os_name = None;
 
1668
    os_version = None;
 
1669
    is_su = None;
 
1670
    if which('lsb_release'):
 
1671
       name = os.popen('lsb_release -i | cut -f 2')
 
1672
       os_name = name.read().strip()
 
1673
       name.close()
 
1674
       version = os.popen('lsb_release -r | cut -f 2')
 
1675
       os_version=version.read().strip()
 
1676
       version.close()
 
1677
       is_su = True
 
1678
    else:
 
1679
       name = os.popen('cat /etc/issue | cut -c 1-6 | head -n 1')
 
1680
       os_name = name.read().strip()
 
1681
       name.close()
 
1682
       version1=os.popen('cat /etc/issue | cut -c 16 | head -n 1')
 
1683
       version2=version1.read().strip()
 
1684
       version1.close()
 
1685
       if (version2 == '1'):
 
1686
           version=os.popen('cat /etc/issue | cut -c 16-17 | head -n 1')
 
1687
           is_su = True
 
1688
       else: 
 
1689
           version=os.popen('cat /etc/issue | cut -c 16 | head -n 1')
 
1690
           is_su = False
 
1691
       os_version=version.read().strip()
 
1692
       version.close()
 
1693
 
 
1694
    return os_name,os_version,is_su 
 
1695
    
 
1696
 
 
1697
#
 
1698
# Removes HTML or XML character references and entities from a text string.
 
1699
#
 
1700
 
 
1701
def unescape(text):
 
1702
    def fixup(m):
 
1703
        text = m.group(0)
 
1704
        if text[:2] == "&#":
 
1705
            # character reference
 
1706
            try:
 
1707
                if text[:3] == "&#x":
 
1708
                    #return unichr(int(text[3:-1], 16))
 
1709
                    return chr(int(text[3:-1], 16))
 
1710
                else:
 
1711
                    #return unichr(int(text[2:-1]))
 
1712
                    return chr(int(text[2:-1]))
 
1713
            except ValueError:
 
1714
                pass
 
1715
        else:
 
1716
            # named entity
 
1717
            try:
 
1718
                #text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
 
1719
                text = chr(htmlentitydefs.name2codepoint[text[1:-1]])
 
1720
            except KeyError:
 
1721
                pass
 
1722
        return text # leave as is
 
1723
    return re.sub("&#?\w+;", fixup, text)
 
1724
 
 
1725
 
 
1726
# Adds HTML or XML character references and entities from a text string
 
1727
 
 
1728
def escape(s):
 
1729
    if not isinstance(s, unicode):
 
1730
        s = unicode(s) # hmmm...
 
1731
 
 
1732
    s = s.replace(u"&", u"&amp;")
 
1733
 
 
1734
    for c in htmlentitydefs.codepoint2name:
 
1735
        if c != 0x26: # exclude &
 
1736
            s = s.replace(unichr(c), u"&%s;" % htmlentitydefs.codepoint2name[c])
 
1737
 
 
1738
    for c in range(0x20) + range(0x7f, 0xa0):
 
1739
        s = s.replace(unichr(c), u"&#%d;" % c)
 
1740
 
 
1741
    return s
 
1742
 
 
1743
# checks if given process is running.
 
1744
#return value:
 
1745
#    True or False
 
1746
#    None - if process is not running
 
1747
#    grep output - if process is running
 
1748
 
 
1749
def Is_Process_Running(process_name):
 
1750
    try:
 
1751
        p1 = Popen(["ps", "aux"], stdout=PIPE)
 
1752
        p2 = Popen(["grep", process_name], stdin=p1.stdout, stdout=PIPE)
 
1753
        p3 = Popen(["grep", "-v", "grep"], stdin=p2.stdout, stdout=PIPE)
 
1754
        output = p3.communicate()[0]
 
1755
        log.debug("Is_Process_Running outpu = %s " %output)
 
1756
 
 
1757
        if process_name in output:
 
1758
            return True, output
 
1759
        else:
 
1760
            return False, None
 
1761
 
 
1762
    except Exception, e:
 
1763
        log.error("Execution failed: process Name[%s]" %process_name)
 
1764
        print >>sys.stderr, "Execution failed:", e
 
1765
        return False, None
 
1766
 
 
1767
#return tye: strings
 
1768
#Return values.
 
1769
#   None --> on error.
 
1770
#  "terminal name"-->success
 
1771
def get_terminal():
 
1772
    terminal_list=['gnome-terminal', 'konsole','x-terminal-emulator', 'xterm', 'gtkterm']
 
1773
    cnt = 0
 
1774
    terminal_cmd = None
 
1775
    while cnt < len(terminal_list):
 
1776
        if which(terminal_list[cnt]):
 
1777
            terminal_cmd = terminal_list[cnt]+" -e "
 
1778
            log.debug("Available Terminal = %s " %terminal_cmd)
 
1779
            break
 
1780
            
 
1781
    return terminal_cmd
 
1782
 
 
1783
#Return Type: bool
 
1784
# Return values:
 
1785
#      True --> if it is older version
 
1786
#      False  --> if it is same or later version.
 
1787
 
 
1788
def Is_HPLIP_older_version(installed_version, available_version):
 
1789
    
 
1790
    if available_version == "" or available_version == None or installed_version == "" or installed_version == None:
 
1791
        log.debug("available_version is ''")
 
1792
        return False
 
1793
 
 
1794
    installed_array=installed_version.split('.')
 
1795
    available_array=available_version.split('.')
 
1796
 
 
1797
    log.debug("HPLIP Installed_version=%s  Available_version=%s"%(installed_version,available_version))
 
1798
    cnt = 0
 
1799
    Is_older = False
 
1800
    while cnt <len(installed_array) and cnt <len(available_array):
 
1801
        if(int(installed_array[cnt]) < int(available_array[cnt])):
 
1802
            Is_older = True
 
1803
            break
 
1804
        elif(int(installed_array[cnt]) > int(available_array[cnt])):
 
1805
            log.debug("Already new verison is installed")
 
1806
            return False
 
1807
        cnt += 1
 
1808
 
 
1809
    # To check internal version is installed.
 
1810
    if Is_older is False and len(installed_array) >len(available_array):
 
1811
        Is_older = True
 
1812
 
 
1813
    return Is_older
 
1814
 
 
1815
 
 
1816
def downLoad_status(count, blockSize, totalSize):
 
1817
    percent = int(count*blockSize*100/totalSize)
 
1818
    if count != 0:
 
1819
        sys.stdout.write("\b\b\b")
 
1820
    sys.stdout.write("%s" %(log.color("%2d%%"%percent, 'bold')))
 
1821
    sys.stdout.flush()
 
1822
 
 
1823
 
 
1824
def download_from_network(weburl, outputFile = None, useURLLIB=False):
 
1825
    result =False
 
1826
 
 
1827
    if weburl is "" or weburl is None:
 
1828
        log.error("URL is empty")
 
1829
        return result, ""
 
1830
 
 
1831
    if outputFile is None:
 
1832
        fp, outputFile = make_temp_file()
 
1833
 
 
1834
    try:
 
1835
        if useURLLIB is False:
 
1836
            wget = which("wget")
 
1837
            if wget:
 
1838
                wget = os.path.join(wget, "wget")
 
1839
                status, output = run("%s --cache=off --timeout=60 --output-document=%s %s" %(wget, outputFile, weburl))
 
1840
                if status:
 
1841
                    log.error("Failed to connect to HPLIP site. Error code = %d" %status)
 
1842
                    return False, ""
 
1843
            else:
 
1844
                useURLLIB = True
 
1845
 
 
1846
        if useURLLIB:
 
1847
            sys.stdout.write("Download in progress...")
 
1848
            urllib.urlretrieve(weburl, outputFile, downLoad_status)
 
1849
 
 
1850
    except IOError, e:
 
1851
        log.error("I/O Error: %s" % e.strerror)
 
1852
        return False, ""
 
1853
 
 
1854
    if not os.path.exists(outputFile):
 
1855
        log.error("Failed to get hplip version/ %s file not found."%hplip_version_file)
 
1856
        return False, ""
 
1857
 
 
1858
    return True, outputFile
 
1859
 
 
1860
 
 
1861
 
 
1862
 
 
1863
    
 
1864
class Sync_Lock:
 
1865
    def __init__(self, filename):
 
1866
        self.Lock_filename = filename
 
1867
        self.handler = open(self.Lock_filename, 'w')
 
1868
 
 
1869
# Wait for another process to release resource and acquires the resource.
 
1870
    def acquire(self):
 
1871
        fcntl.flock(self.handler, fcntl.LOCK_EX)
 
1872
 
 
1873
    def release(self):
 
1874
        fcntl.flock(self.handler, fcntl.LOCK_UN)
 
1875
 
 
1876
    def __del__(self):
 
1877
        self.handler.close()