~mozillateam/thunderbird/thunderbird-beta.vivid

« back to all changes in this revision

Viewing changes to debian/apport/source_thunderbird.py.in

  • Committer: Chris Coulson
  • Date: 2012-07-13 21:55:50 UTC
  • Revision ID: chris.coulson@canonical.com-20120713215550-yiifogw5jq3q0cgi
* New upstream release from the beta channel (THUNDERBIRD_14_0b5_BUILD1)
* New upstream release from the beta channel (THUNDERBIRD_14_0b4_BUILD1)
* Update globalmenu-extension to 3.3 prerelease r388
  - Fix LP: #775305 - Use style to determine menuitem visibility
  - Fix LP: #1017247 - Manually register our UA stylesheet rather than
    relying on this happening via chrome registration, to work around a
    bug in various bootstrapped third party addons, which initialize and
    use the stylesheet service before extension chrome is registered for
    non-restartless addons such as ours
  - Fix a crash in uGlobalMenu::RecycleList::~RecycleList()
* Apport hook improvements:
  - Sort preferences alphabetically in the apport data
  - Treat preferences set in default addons as default prefs so that
    they don't show up in apport data, unless the preference files have
    been modified
  - Support random pref files dropped in to the Firefox install folder, and
    preferences from application bundles
  - Fix ordering issues when loading preferences
* Fix LP: #1013171 - Fully support Python 3 in the apport hook
  - update debian/apport/source_firefox.py.in
* Update the Apport blacklist file after dropping thunderbird-bin
  - update debian/apport/blacklist.in
* Update eds extension to 0.3.11 for YAEDSABI (yet another EDS ABI)
* Update eds dependencies for YAEDSABI
  - update debian/rules
* Add partial support for Python 3 in the apport hook (LP: #1013171)
  - update debian/apport/source_firefox.py.in
* Cherry pick patch from aurora to use YARR interpreter on ppc
  - update debian/patches/fix-build-failure-without-yarr-jit.patch
  - update debian/patches/series
* Fix ppc build due to new dtoa library
  - add debian/patches/fix-dtoa-build-on-ppc.patch
  - update debian/patches/series
* debian/apport/source_thunderbird.py.in:
  - Update apport hook for python3
* Add missing file
* New upstream release from the beta channel (THUNDERBIRD_14_0b3_BUILD1)
* Update globalmenu-extension to 3.3 prerelease r369
  - Fix LP: #1010580 - update the window event timestamp when handling
    menu events
  - Fix LP: #775080 - Thunderbird with Firetray/MinimizeToTray -
    Global menu disappears
  - Fix LP: #813775 - Hitting an assertion in dbusmenu
* Update eds extension to 0.3.10 for new evolution-data-server ABI
  (thanks to Tim Gardner)
* Update eds dependencies for quantal (LP: #1015723)
* New upstream release from the beta channel (THUNDERBIRD_14_0b2_BUILD1)
* Switch back to GCC4.7 now that LP: #1003733 is fixed
  - update debian/config/branch.mk
  - update debian/control{,.in}
* Don't set LD_LIBRARY_PATH in our shell wrapper, and install
  dependentlibs.list instead now
  - update debian/thunderbird.sh.in
  - update debian/thunderbird.install.in
* Drop StartupWMClass from the desktop file now that WM_CLASS is the same
  as the binary name (also fixes LP: #1012158)
  - update debian/thunderbird.desktop.in
  - update debian/rules
* New upstream release from the beta channel (THUNDERBIRD_14_0b1_BUILD2)
* Update globalmenu-extension to 3.2.4 prerelease r338
* Drop patches fixed upstream
  - remove debian/patches/revert-bmo621446-investigation.patch
  - update debian/patches/series
* Update desktop file translations
  - update debian/thunderbird.desktop.in
* Ensure that additional actions in the desktop file match the fd.o spec
  in precise
  - update debian/thunderbird.desktop.in
  - update debian/rules
* Add application/x-xpinstall to the MimeType field of the desktop file
  - update debian/thunderbird.desktop.in
* Drop almost all mimetypes from the desktop file. Thunderbird won't display
  any of them if you invoke it with files of these types. It will just 
  open a Compose window and add the file as an attachment
  - update debian/thunderbird.desktop.in
* Drop the ability to select between tree/system libraries using a single
  option in debian/rules. It adds additional complexity and was never used
  - update debian/config/mozconfig.in
  - update debian/control.in
  - update debian/thunderbird-dev.links.in
  - update debian/rules
* Add Catalan keywords
  - update debian/thunderbird.desktop.in

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import subprocess
20
20
import struct
21
21
from subprocess import Popen
22
 
from ConfigParser import ConfigParser
 
22
try:
 
23
    from configparser import ConfigParser
 
24
except ImportError:
 
25
    from ConfigParser import ConfigParser
23
26
import sqlite3
24
27
import tempfile
25
28
import re
28
31
from glob import glob
29
32
import zipfile
30
33
import stat
 
34
import functools
 
35
if sys.version_info[0] < 3:
 
36
    import codecs
 
37
 
 
38
DISTRO_ADDONS = [
 
39
    '@MOZ_APP_NAME@'
 
40
]
31
41
 
32
42
class PrefParseError(Exception):
33
43
    def __init__(self, msg, filename, linenum):
74
84
        return "Failed to compare versions A = %s, B = %s (%s)" % (self.a, self.b, str(self.e))
75
85
 
76
86
 
 
87
def _open(filename, mode):
 
88
    if sys.version_info[0] < 3:
 
89
        return codecs.open(filename, mode, 'utf-8')
 
90
    return open(filename, mode)
 
91
 
77
92
def mkstemp_copy(path):
78
93
    '''Make a copy of a file to a temporary file, and return the path'''
79
94
    (outfd, outpath) = tempfile.mkstemp()
80
 
    outfile = os.fdopen(outfd, 'w')
81
 
    infile = open(path, 'r')
 
95
    outfile = os.fdopen(outfd, 'wb')
 
96
    infile = open(path, 'rb')
82
97
 
83
98
    total = 0
84
99
    while True:
165
180
                self.parser = parser
166
181
                self.index = 0
167
182
 
168
 
            def next(self):
 
183
            def __next__(self):
169
184
                if self.index == len(self.parser):
170
185
                    raise StopIteration
171
186
                res = self.parser[self.index]
172
187
                self.index += 1
173
188
                return res
174
189
 
 
190
            def next(self):
 
191
                return self.__next__()
 
192
 
175
193
        return ExtensionINIParserIter(self)
176
194
 
177
195
    def __len__(self):
194
212
        spl = part.split('.')
195
213
 
196
214
        if part == '*' and len(part) == 1:
197
 
            res.numA = sys.maxint
 
215
            try:
 
216
                res.numA = sys.maxint
 
217
            except:
 
218
                res.numA = sys.maxsize # python3
 
219
            res.strB = ""
198
220
            res.strB = ""
199
221
        else:
200
222
            res.numA = int(re.sub(r'([0-9]*)(.*)', r'\1', spl[0]))
220
242
        return (re.sub(r'([^\.]*)\.*(.*)', r'\2', part), res)
221
243
 
222
244
    def strcmp(stra, strb):
223
 
        if stra == None and strb != None:
 
245
        if stra == None and strb == None:
 
246
            return 0
 
247
        elif stra == None and strb != None:
224
248
            return 1
225
249
        elif stra != None and strb == None:
226
250
            return -1
284
308
    @property
285
309
    def package(self):
286
310
        if self._checked_package == False:
287
 
            package = apport.packaging.get_file_package(self.path)
288
 
            if package != None:
289
 
                self._package = package.encode()
 
311
            self._package = apport.packaging.get_file_package(self.path)
290
312
            self._checked_package = True
291
313
        return self._package
292
314
 
308
330
 
309
331
        fd = None
310
332
        try:
311
 
            fd = open(os.path.join(path, 'pluginreg.dat'), 'r')
 
333
            fd = _open(os.path.join(path, 'pluginreg.dat'), 'r')
312
334
            try:
313
335
                skip = 0
314
336
                linenum = 1
379
401
                self.registry = registry
380
402
                self.index = 0
381
403
 
382
 
            def next(self):
 
404
            def __next__(self):
383
405
                if self.index == len(self.registry):
384
406
                    raise StopIteration
385
407
                ret = self.registry[self.index]
386
408
                self.index += 1
387
409
                return ret
388
410
 
 
411
            def next(self):
 
412
                return self.__next__()
 
413
 
389
414
        return PluginRegistryIter(self)
390
415
 
391
416
    def __len__(self):
466
491
 
467
492
        self._profile_path = profile_path
468
493
 
469
 
        # Report non-default preferences = ie, those from syspref.js, prefs.js,
470
 
        # user.js and extension prefs. The load order is important
 
494
        # Read all preferences. Note that we hide preferences that are considered
 
495
        # default (ie, all of those set by the Firefox package or bundled addons,
 
496
        # unless any of the pref files have been modified by the user).
 
497
        # The load order is *very important*
471
498
        if profile_path != None:
472
499
            locations = [
473
 
%%ifdef MOZ_NEW_SYSPREF
474
 
                "/etc/@MOZ_APP_NAME@/syspref.js",
475
 
%%else
476
 
                "/etc/@MOZ_APP_NAME@/pref",
 
500
                "/@MOZ_LIBDIR@/omni.ja:greprefs.js",
 
501
                "/@MOZ_LIBDIR@/omni.ja:defaults/pref/*.js",
 
502
                "/@MOZ_LIBDIR@/defaults/pref/*.js",
 
503
                "/@MOZ_LIBDIR@/defaults/pref/unix.js",
 
504
                "/@MOZ_LIBDIR@/omni.ja:defaults/preferences/*.js"
 
505
                "/@MOZ_LIBDIR@/defaults/preferences/*.js"
 
506
            ]
 
507
 
 
508
            append_dirs = [ 'defaults/preferences/*.js' ]
 
509
%%ifndef MOZ_NEW_SYSPREF
 
510
            locations.append('/@MOZ_LIBDIR@/defaults/syspref/*.js')
 
511
            append_dirs.append('defaults/syspref/*.js')
477
512
%%endif
478
 
                os.path.join(profile_path, "prefs.js"),
479
 
                os.path.join(profile_path, "user.js")
480
 
            ]
 
513
            if os.path.isdir('/@MOZ_LIBDIR@/distribution/bundles'):
 
514
                bundles = os.listdir('/@MOZ_LIBDIR@/distribution/bundles')
 
515
                bundles.sort(reverse=True)
 
516
                for d in append_dirs:
 
517
                    for bundle in bundles:
 
518
                        path = os.path.join('/@MOZ_LIBDIR@/distribution/bundles', bundle)
 
519
                        if path.endswith('.xpi'):
 
520
                            locations.append(path + ':' + d)
 
521
                        elif os.path.isdir(path):
 
522
                            locations.append(os.path.join(path, d))
 
523
 
 
524
            locations.append(os.path.join(profile_path, "prefs.js"))
 
525
            locations.append(os.path.join(profile_path, "user.js"))
481
526
 
482
527
            extensions = ExtensionINIParser(profile_path)
483
528
            for extension in extensions:
484
 
                if not extension.endswith('.xpi'):
485
 
                    extension = os.path.join(extension, "defaults", "preferences")
486
 
                locations.append(extension)
 
529
                if extension.endswith('.xpi'):
 
530
                    locations.append(extension + ':defaults/preferences/*.(J|j)(S|s)')
 
531
                elif os.path.isdir(extension):
 
532
                    locations.append(os.path.join(extension, 'defaults/preferences/*.js'))
 
533
 
 
534
            locations.append(os.path.join(profile_path, 'preferences/*.js'))
487
535
        else: locations = []
488
536
 
489
537
        if extra_paths != None:
491
539
                locations.append(extra)
492
540
 
493
541
        for location in locations:
494
 
            if location.endswith('.js'):
495
 
                self._parse_file(location)
496
 
            elif location.endswith('.xpi'):
497
 
                self._parse_xpi(location)
 
542
            m = re.match(r'^([^:]*):?(.*)', location)
 
543
            if m.group(2) == '':
 
544
                files = glob(location)
 
545
                files.sort(reverse=True)
 
546
                for f in files:
 
547
                    self._parse_file(f)
498
548
            else:
499
 
                self._parse_dir(location)
 
549
                self._parse_jar(m.group(1), m.group(2))
 
550
 
 
551
    def _should_ignore_file(self, filename):
 
552
        realpath = os.path.realpath(filename)
 
553
        package = apport.packaging.get_file_package(realpath)
 
554
        if package and apport.packaging.is_distro_package(package) and \
 
555
           package in DISTRO_ADDONS and \
 
556
           realpath[1:] not in apport.packaging.get_modified_files(package):
 
557
            return True
 
558
 
 
559
        return False
500
560
 
501
561
    def _parse_file(self, filename):
502
 
        anonsrc = anonymize_path(filename, self._profile_path)
503
562
        f = None
504
563
        self._state = Prefs.STATE_READY
505
564
        try:
506
 
            f = open(filename)
 
565
            f = _open(filename, 'r')
507
566
            try:
508
567
                linenum = 1
509
568
                state = None
510
569
                for line in f.readlines():
511
 
                    state = self._parseline(line, anonsrc, linenum, state)
 
570
                    state = self._parseline(line, filename, linenum, state)
512
571
                    linenum += 1
513
572
            except Exception as e:
514
 
                self.errors[anonsrc] = str(e)
 
573
                self.errors[filename] = str(e)
515
574
        except:
516
575
            pass
517
576
        finally:
518
577
            if f != None:
519
578
                f.close()
520
 
            if anonsrc not in self.errors:
521
 
                self.pref_sources.append(anonsrc)
522
 
 
523
 
    def _parse_dir(self, dirname):
524
 
        for filename in glob(os.path.join(dirname, '*.js')):
525
 
            self._parse_file(filename)
526
 
 
527
 
    def _parse_xpi(self, xpi):
528
 
        xpifile = None
 
579
            if filename not in self.errors \
 
580
               and not self._should_ignore_file(filename):
 
581
                self.pref_sources.append(filename)
 
582
 
 
583
    def _parse_jar(self, jar, match):
 
584
        jarfile = None
529
585
        try:
530
 
            xpifile = zipfile.ZipFile(xpi)
531
 
            entries = xpifile.namelist()
 
586
            jarfile = zipfile.ZipFile(jar)
 
587
            entries = jarfile.namelist()
 
588
            entries.sort(reverse=True)
532
589
            for entry in entries:
533
 
                if re.match(r'^defaults/preferences/*.js$', entry):
534
 
                    source = '%s:%s' % (xpi, entry)
535
 
                    anonsrc = anonymize_path(source, self._profile_path)
 
590
                if re.match(r'^' + match + '$', entry):
 
591
                    source = '%s:%s' % (jar, entry)
536
592
                    try:
537
 
                        f = xpifile.open(entry, 'r')
 
593
                        f = jarfile.open(entry, 'r')
538
594
                        linenum = 1
539
595
                        state = None
540
596
                        for line in f.readlines():
541
 
                            state = self._parseline(line, anonsrc, linenum, state)
 
597
                            state = self._parseline(line.decode('utf-8'),
 
598
                                                    source, linenum, state)
542
599
                            linenum += 1
543
600
                    except Exception as e:
544
 
                        self.errors[anonsrc] = str(e)
 
601
                        self.errors[source] = str(e)
545
602
                    finally:
546
 
                        if anonsrc not in self.errors:
547
 
                            self.pref_sources.append(anonsrc)
 
603
                        if source not in self.errors \
 
604
                           and not self._should_ignore_file(jar):
 
605
                            self.pref_sources.append(source)
548
606
        except:
549
607
            pass
550
608
        finally:
551
 
            if xpifile != None:
552
 
                xpifile.close()
 
609
            if jarfile != None:
 
610
                jarfile.close()
553
611
 
554
612
    def _maybe_add_pref(self, key, value, source, default, locked):
555
613
 
556
614
        class Pref(object):
557
 
            def __init__(self):
 
615
            def __init__(self, profile_path):
558
616
                self._default = None
559
617
                self._value = None
560
618
                self._default_source = None
561
619
                self._value_source = None
562
620
                self.locked = False
 
621
                self._profile_path = profile_path
563
622
 
564
623
            @property
565
624
            def value(self):
573
632
                    return self._value_source
574
633
                return self._default_source
575
634
 
 
635
            @property
 
636
            def anon_source(self):
 
637
                if self._value != None:
 
638
                    return anonymize_path(self._value_source, self._profile_path)
 
639
                return anonymize_path(self._default_source, self._profile_path)
 
640
 
576
641
            def set_value(self, value, source, default, locked):
577
642
                if self.locked == True:
578
643
                    return
592
657
        for match in self.whitelist:
593
658
            if re.match(match, key):
594
659
                if key not in self.prefs:
595
 
                    self.prefs[key] = Pref()
 
660
                    self.prefs[key] = Pref(self._profile_path)
596
661
 
597
662
                self.prefs[key].set_value(value, source, default, locked)
598
663
 
634
699
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
635
700
                elif c == '#':
636
701
                    state.state = Prefs.STATE_PARSE_UNTIL_EOL
637
 
                elif line[index:].startswith('pref'):
 
702
                elif line.startswith('pref', index):
638
703
                    state.default == True
639
704
                    state.next_state = Prefs.STATE_PARSE_UNTIL_OPEN_PAREN
640
705
                    state.state = Prefs.STATE_SKIP
641
706
                    state.skip = 3
642
 
                elif line[index:].startswith('user_pref'):
 
707
                elif line.startswith('user_pref', index):
643
708
                    state.next_state = Prefs.STATE_PARSE_UNTIL_OPEN_PAREN
644
709
                    state.state = Prefs.STATE_SKIP
645
710
                    state.skip = 8
646
 
                elif line[index:].startswith('lockPref'):
 
711
                elif line.startswith('lockPref', index):
647
712
                    state.default = True
648
713
                    state.locked = True
649
714
                    state.next_state = Prefs.STATE_PARSE_UNTIL_OPEN_PAREN
650
715
                    state.state = Prefs.STATE_SKIP
651
716
                    state.skip = 7
 
717
                elif not c.isspace():
 
718
                    raise PrefParseError("Unexpected character '%s' before pref" % c,
 
719
                                         anonymize_path(source, self._profile_path),
 
720
                                         linenum)
652
721
 
653
722
            elif state.state == Prefs.STATE_SKIP:
654
723
                state.skip -= 1
662
731
                elif c == '/':
663
732
                    state.state = Prefs.STATE_PARSE_UNTIL_EOL
664
733
                else:
665
 
                    raise PrefParseError("Unexpected '/'", source, linenum)
 
734
                    raise PrefParseError("Unexpected '/'",
 
735
                                         anonymize_path(source, self._profile_path),
 
736
                                         linenum)
666
737
 
667
738
            elif state.state == Prefs.STATE_PARSE_UNTIL_EOL:
668
739
                pass
685
756
                    state.next_state = state.state
686
757
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
687
758
                elif not c.isspace():
688
 
                    raise PrefParseError("Unexpected character before open parenthesis", source, linenum)
 
759
                    raise PrefParseError("Unexpected character '%s' before open parenthesis" % c,
 
760
                                         anonymize_path(source, self._profile_path),
 
761
                                         linenum)
689
762
 
690
763
            elif state.state == Prefs.STATE_PARSE_UNTIL_NAME:
691
764
                if c == '"' or c == '\'':
696
769
                    state.next_state = state.state
697
770
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
698
771
                elif not c.isspace():
699
 
                    raise PrefParseError("Unexpected character before pref name", source, linenum)
 
772
                    raise PrefParseError("Unexpected character '%s' before pref name" % c,
 
773
                                         anonymize_path(source, self._profile_path),
 
774
                                         linenum)
700
775
 
701
776
            elif state.state == Prefs.STATE_PARSE_STRING:
702
777
                if c == '\\':
726
801
                    state.next_state = state.state
727
802
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
728
803
                elif not c.isspace():
729
 
                    raise PrefParseError("Unexpected character before comma", source, linenum)
 
804
                    raise PrefParseError("Unexpected character '%s' before comma" % c,
 
805
                                         anonymize_path(source, self._profile_path),
 
806
                                         linenum)
730
807
 
731
808
            elif state.state == Prefs.STATE_PARSE_UNTIL_VALUE:
732
809
                if c == '"' or c == '\'':
733
810
                    state.tmp = ''
734
811
                    state.state = Prefs.STATE_PARSE_STRING
735
812
                    state.next_state = Prefs.STATE_PARSE_UNTIL_CLOSE_PAREN
736
 
                elif line[index:].startswith('true'):
 
813
                elif line.startswith('true', index):
737
814
                    state.tmp = True
738
815
                    state.next_state = Prefs.STATE_PARSE_UNTIL_CLOSE_PAREN
739
816
                    state.state = Prefs.STATE_SKIP
740
817
                    state.skip = 3
741
 
                elif line[index:].startswith('false'):
 
818
                elif line.startswith('false', index):
742
819
                    state.tmp = False
743
820
                    state.next_state = Prefs.STATE_PARSE_UNTIL_CLOSE_PAREN
744
821
                    state.state = Prefs.STATE_SKIP
750
827
                    state.next_state = state
751
828
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
752
829
                elif not c.isspace():
753
 
                    raise PrefParseError("Unexpected character before value", source, linenum)
 
830
                    raise PrefParseError("Unexpected character '%s' before value" % c,
 
831
                                         anonymize_path(source, self._profile_path),
 
832
                                         linenum)
754
833
 
755
834
            elif state.state == Prefs.STATE_PARSE_INT:
756
835
                if c >= '0' and c <= '9':
767
846
                    state.next_state = Prefs.STATE_PARSE_UNTIL_CLOSE_PAREN
768
847
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
769
848
                else:
770
 
                    raise PrefParseError("Error whilst parsing int", source, linenum)
 
849
                    raise PrefParseError("Unexpected character '%s' whilst parsing int" % c,
 
850
                                         anonymize_path(source, self._profile_path),
 
851
                                         linenum)
771
852
 
772
853
            elif state.state == Prefs.STATE_PARSE_UNTIL_CLOSE_PAREN:
773
854
                if state.tmp != None:
779
860
                    state.next_state = state.state
780
861
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
781
862
                elif not c.isspace():
782
 
                    raise PrefParseError("Unexpected character before close parenthesis", source, linenum)
 
863
                    raise PrefParseError("Unexpected character '%s' before close parenthesis" % c,
 
864
                                         anonymize_path(source, self._profile_path),
 
865
                                         linenum)
783
866
 
784
867
            elif state.state == Prefs.STATE_PARSE_UNTIL_SEMICOLON:
785
868
                if c == ';':
790
873
                    state.next_state = state.state
791
874
                    state.state = Prefs.STATE_COMMENT_MAYBE_START
792
875
                elif not c.isspace():
793
 
                    raise PrefParseError("Unexpected character before semicolon", source, linenum)
 
876
                    raise PrefParseError("Unexpected character '%s' before semicolon" % c,
 
877
                                         anonymize_path(source, self._profile_path),
 
878
                                         linenum)
794
879
 
795
880
            index += 1
796
881
 
800
885
        return state
801
886
 
802
887
    def __getitem__(self, key):
803
 
        if not key in self.prefs:
804
 
            raise IndexError
805
 
        return self.prefs[key]
 
888
        res = self.prefs[key]
 
889
        if res.source in self.pref_sources:
 
890
            return res
 
891
        raise KeyError
806
892
 
807
893
    def __iter__(self):
808
894
 
809
895
        class PrefsIter:
810
896
            def __init__(self, prefs):
811
897
                self.index = 0
812
 
                self.keys = prefs.prefs.keys()
 
898
                self.keys = []
 
899
                for k in prefs.prefs.keys():
 
900
                    try:
 
901
                        test = prefs[k]
 
902
                        self.keys.append(k)
 
903
                    except:
 
904
                        pass
 
905
                self.keys.sort()
813
906
 
814
 
            def next(self):
 
907
            def __next__(self):
815
908
                if self.index == len(self.keys):
816
909
                    raise StopIteration
817
910
                res = self.keys[self.index]
818
911
                self.index += 1
819
912
                return res
820
913
 
 
914
            def next(self):
 
915
                return self.__next__()
 
916
 
821
917
        return PrefsIter(self)
822
918
 
823
919
    def __len__(self):
824
 
        return len(self.prefs)
 
920
        i = 0
 
921
        for k in self:
 
922
            i += 1
 
923
        return i
825
924
 
826
925
 
827
926
class Extension:
978
1077
        if not hasattr(self, '_running'):
979
1078
            # We detect if this profile is running or not by trying to lock the lockfile
980
1079
            # If we can't lock it, then Thunderbird is running
981
 
            fd = os.open(os.path.join(self.path, ".parentlock"), os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
 
1080
            fd = os.open(os.path.join(self.path, ".parentlock"), os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0o666)
982
1081
            lock = struct.pack("hhqqi", 1, 0, 0, 0, 0)
983
1082
            try:
984
1083
                fcntl.fcntl(fd, fcntl.F_SETLK, lock)
1006
1105
            if type(self.prefs[pref].value) == int:
1007
1106
                value = str(self.prefs[pref].value)
1008
1107
            elif type(self.prefs[pref].value) == bool:
1009
 
                value = 'true' if True else 'false'
 
1108
                value = 'true' if self.prefs[pref].value == True else 'false'
1010
1109
            else:
1011
1110
                value = "\"%s\"" % self.prefs[pref].value
1012
 
            ret += pref + ': ' + value + ' (' + self.prefs[pref].source + ')\n'
 
1111
            ret += pref + ': ' + value + ' (' + self.prefs[pref].anon_source + ')\n'
1013
1112
        return ret
1014
1113
 
1015
1114
    def dump_pref_sources(self):
1016
1115
        ret = ''
1017
1116
        for source in self.prefs.pref_sources:
1018
 
            ret += source + '\n'
 
1117
            ret += anonymize_path(source, self.path) + '\n'
1019
1118
        return ret
1020
1119
 
1021
1120
    def dump_pref_errors(self):
1168
1267
                self.profiles = profiles
1169
1268
                self.index = 0
1170
1269
 
1171
 
            def next(self):
 
1270
            def __next__(self):
1172
1271
                if self.index == len(self.profiles):
1173
1272
                    raise StopIteration
1174
1273
                res = self.profiles[self.index]
1175
1274
                self.index += 1
1176
1275
                return res
1177
1276
 
 
1277
            def next(self):
 
1278
                return self.__next__()
 
1279
 
1178
1280
        return ProfilesIter(self)
1179
1281
 
1180
1282
    def __len__(self):
1235
1337
            tags += ' '
1236
1338
        report['Tags'] = tags + tag
1237
1339
 
1238
 
    ddproc = Popen(['dpkg-divert', '--truename', '/usr/bin/@MOZ_APP_NAME@'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
1340
    ddproc = Popen(['dpkg-divert', '--truename', '/usr/bin/@MOZ_APP_NAME@'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
1239
1341
    truename = ddproc.communicate()
1240
1342
    if ddproc.returncode == 0 and truename[0].strip() != '/usr/bin/@MOZ_APP_NAME@':
1241
 
        ddproc = Popen(['dpkg-divert', '--listpackage', '/usr/bin/@MOZ_APP_NAME@'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
1343
        ddproc = Popen(['dpkg-divert', '--listpackage', '/usr/bin/@MOZ_APP_NAME@'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
1242
1344
        diverter = ddproc.communicate()
1243
1345
        report['UnreportableReason'] = "/usr/bin/@MOZ_APP_NAME@ has been diverted by a third party package (%s)" % diverter[0].strip()
1244
1346
        return
1307
1409
            return 0
1308
1410
 
1309
1411
    # Put the most recent first
1310
 
    crash_reports.sort(crashes_sort)
 
1412
    crash_reports.sort(key=functools.cmp_to_key(crashes_sort))
1311
1413
 
1312
1414
    crash_reports_str = ''
1313
1415
    i = 0
1376
1478
    import apport
1377
1479
    from apport import packaging
1378
1480
    D = {}
1379
 
    D['Package'] = 'thunderbird'
 
1481
    D['Package'] = '@MOZ_APP_NAME@'
 
1482
    D['SourcePackage'] = '@MOZ_APP_NAME@'
1380
1483
    add_info(D, None)
1381
 
    for KEY in D.keys(): 
1382
 
        print '''-------------------%s: ------------------\n''' % KEY, D[KEY]
 
1484
    for KEY in D.keys():
 
1485
        print('''-------------------%s: ------------------\n%s''' % (KEY, D[KEY]))