This file is indexed.

/usr/share/pyshared/softwareproperties/ppa.py is in python-software-properties 0.82.7.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#  software-properties PPA support
#
#  Copyright (c) 2004-2009 Canonical Ltd.
#
#  Author: Michael Vogt <mvo@debian.org>
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation; either version 2 of the
#  License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#  USA

import apt_pkg
import json
import re
import subprocess
from threading import Thread
import pycurl

DEFAULT_KEYSERVER = "hkp://keyserver.ubuntu.com:80/"
# maintained until 2015
LAUNCHPAD_PPA_API = 'https://launchpad.net/api/1.0/~%s/+archive/%s'
# None means use pycurl default 
LAUNCHPAD_PPA_CERT = None

def encode(s):
    return re.sub("[^a-zA-Z0-9_-]","_", s)

def expand_ppa_line(abrev, distro_codename):
    """ Convert an abbreviated ppa name of the form 'ppa:$name' to a
        proper sources.list line of the form 'deb ...' """
    # leave non-ppa: lines unchanged
    if not abrev.startswith("ppa:"):
        return (abrev, None)
    # FIXME: add support for dependency PPAs too (once we can get them
    #        via some sort of API, see LP #385129)
    abrev = abrev.split(":")[1]
    ppa_owner = abrev.split("/")[0]
    try:
        ppa_name = abrev.split("/")[1]
    except IndexError, e:
        ppa_name = "ppa"
    sourceslistd = apt_pkg.config.find_dir("Dir::Etc::sourceparts")
    line = "deb http://ppa.launchpad.net/%s/%s/ubuntu %s main" % (
        ppa_owner, ppa_name, distro_codename)
    filename = "%s/%s-%s-%s.list" % (
        sourceslistd, encode(ppa_owner), encode(ppa_name), distro_codename)
    return (line, filename)

class CurlCallback:
    def __init__(self):
        self.contents = ''

    def body_callback(self, buf):
        self.contents = self.contents + buf

def get_ppa_info_from_lp(owner_name, ppa_name):
    lp_url = LAUNCHPAD_PPA_API % (owner_name, ppa_name)
    # we ask for a JSON structure from lp_page, we could use
    # simplejson, but the format is simple enough for the regexp
    callback = CurlCallback()
    curl = pycurl.Curl()
    curl.setopt(pycurl.SSL_VERIFYPEER, 1)
    curl.setopt(pycurl.SSL_VERIFYHOST, 2)
    curl.setopt(pycurl.WRITEFUNCTION, callback.body_callback)
    # only useful for testing
    if LAUNCHPAD_PPA_CERT:
        curl.setopt(pycurl.CAINFO, LAUNCHPAD_PPA_CERT)
    curl.setopt(pycurl.URL, str(lp_url))
    curl.setopt(pycurl.HTTPHEADER, ["Accept: application/json"])
    curl.perform()
    curl.close()
    lp_page = callback.contents
    return json.loads(lp_page)

class AddPPASigningKeyThread(Thread):
    " thread class for adding the signing key in the background "

    def __init__(self, ppa_path, keyserver=None):
        Thread.__init__(self)
        self.ppa_path = ppa_path
        self.keyserver = (keyserver if keyserver is not None
                          else DEFAULT_KEYSERVER)
        
    def run(self):
        self.add_ppa_signing_key(self.ppa_path)
        
    def add_ppa_signing_key(self, ppa_path):
        """Query and add the corresponding PPA signing key.
        
        The signing key fingerprint is obtained from the Launchpad PPA page,
        via a secure channel, so it can be trusted.
        """
        owner_name, ppa_name, distro = ppa_path[1:].split('/')
        try:
            ppa_info = get_ppa_info_from_lp(owner_name, ppa_name)
        except pycurl.error as e:
            print "Error reading %s: %s" % (lp_url, e[1])
            return False
        try:
            signing_key_fingerprint = ppa_info["signing_key_fingerprint"]
        except IndexError as e:
            print "Error: can't find signing_key_fingerprint at %s" % lp_url
            return False
        res = subprocess.call(
            ["apt-key", "adv", 
             "--keyserver", self.keyserver,
             "--recv", signing_key_fingerprint])
        return (res == 0)


if __name__ == "__main__":
    import sys
    owner_name, ppa_name = sys.argv[1].split(":")[1].split("/")
    print get_ppa_info_from_lp(owner_name, ppa_name)