#!/usr/bin/env python # # Copyright (c) 2010 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Chromoting Directory API client implementation. Used for testing/debugging # purposes. Requires Python 2.6: json module is not available in earlier # versions. import os import httplib import json import urllib import urllib2 import random import sys DEFAULT_DIRECTORY_SERVER = 'www.googleapis.com' auth_filepath = os.path.join(os.path.expanduser('~'), '.chromotingDirectoryAuthToken') def random_uuid(): return ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x" % tuple(map(lambda x: random.randrange(0,65536), range(8)))) class Host: def __init__(self, parameters=None): if parameters != None: self.host_id = parameters[u"hostId"] self.host_name = parameters[u"hostName"] self.public_key = parameters[u"publicKey"] # Following fields may be missing, use get() for them. self.jabber_id = parameters.get(u"jabberId") self.created_time = parameters.get(u"createdTime") self.updated_time = parameters.get(u"updatedTime") self.status = parameters.get(u"status") else: self.host_id = random_uuid() import socket self.host_name = socket.gethostname() self.public_key = None self.jabber_id = None self.created_time = None self.updated_time = None self.status = None class HostDirectoryError(Exception): def __init__(self, message, response): Exception.__init__(self, message) print response self._response = response class HostDirectory: def __init__(self, username, auth_token, server=DEFAULT_DIRECTORY_SERVER): self._username = username self._auth_token = auth_token self._base_url = '/chromoting/v1/@me/hosts' self._http = httplib.HTTPSConnection(server) self._headers = {"Authorization": "GoogleLogin auth=" + self._auth_token, "Content-Type": "application/json" } def add_host(self, host): host_json = { 'data': { 'hostId': host.host_id, 'hostName': host.host_name, 'publicKey': host.public_key, } } if host.jabber_id: host_json['data']['jabberId'] = host.jabber_id post_data = json.dumps(host_json) self._http.request("POST", self._base_url, post_data, self._headers) response = self._http.getresponse() if response.status != 200: raise HostDirectoryError(response.reason, response.read()) data = response.read() def get_hosts(self): self._http.request("GET", self._base_url, headers=self._headers) response = self._http.getresponse() if response.status != 200: raise HostDirectoryError(response.reason, response.read()) data = response.read() data = json.loads(data)[u'data'] results = [] if data.has_key(u'items'): for item in data[u'items']: results.append(Host(item)) return results def delete_host(self, host_id): url = self._base_url + '/' + host_id self._http.request("DELETE", url, headers=self._headers) response = self._http.getresponse() if response.status / 100 != 2: # Normally 204 is returned raise HostDirectoryError(response.reason, response.read()) data = response.read() def usage(): sys.stderr.write( ("Usage:\n" + " Login: \t\t%(cmd)s login\n" + " Register host: \t%(cmd)s insert --hostId=" + " --hostName= \\\n" + "\t\t\t --publicKey= --jabberId=\n" + " List hosts: \t\t%(cmd)s list\n" + " Delete a host: \t%(cmd)s delete \n") % {"cmd" : sys.argv[0]}) return 1 class CommandError(Exception): def __init__(self, message): Exception.__init__(self, message) def load_auth_token(): try: lines = open(auth_filepath).readlines() except IOError: raise CommandError(("Can't open file (%s). Please run " + "'%s login' and try again.") % (auth_filepath, sys.argv[0])) if len(lines) != 2: raise CommandError(("Invalid auth file (%s). Please run " + "'%s login' and try again.") % (auth_filepath, sys.argv[0])) return map(lambda x: x.strip(), lines) def login_cmd(args): """login command""" if len(args) != 0: return usage() import getpass import gaia_auth print "Email:", email = raw_input() passwd = getpass.getpass("Password: ") authenticator = gaia_auth.GaiaAuthenticator('chromoting'); auth_token = authenticator.authenticate(email, passwd) # Set permission mask for created file. os.umask(0066) auth_file = open(auth_filepath, 'w') auth_file.write(email) auth_file.write('\n') auth_file.write(auth_token) auth_file.close() print 'Auth token: ', auth_token print '...saved in', auth_filepath def list_cmd(args): """list command""" if len(args) != 0: return usage() (username, token) = load_auth_token() client = HostDirectory(username, token) print '%36s %30s %s' % ("HOST ID", "HOST NAME", "JABBER ID") for host in client.get_hosts(): print '%36s %30s %s' % (host.host_id, host.host_name, host.jabber_id) return 0 def insert_cmd(args): """insert command""" (username, token) = load_auth_token() client = HostDirectory(username, token) host = Host() for arg in args: if arg.startswith("--hostId="): host.host_id = arg[len("--hostId="):] elif arg.startswith("--hostName="): host.host_name = arg[len("--hostName="):] elif arg.startswith("--publicKey="): host.public_key = arg[len("--publicKey="):] elif arg.startswith("--jabberId="): host.jabber_id = arg[len("--jabberId="):] else: return usage() client.add_host(host) return 0 def delete_cmd(args): """delete command""" if len(args) != 1: return usage() host_id = args[0] (username, token) = load_auth_token() client = HostDirectory(username, token) client.delete_host(host_id) return 0 def main(): import sys args = sys.argv[1:] if len(args) == 0: return usage() command = args[0] try: if command == "help": usage() elif command == "login": return login_cmd(args[1:]) elif command == "list": return list_cmd(args[1:]) elif command == "insert": return insert_cmd(args[1:]) elif command == "delete": return delete_cmd(args[1:]) else: raise CommandError("Unknown command: %s" % command); except CommandError as e: sys.stderr.write("%s\n" % e.args[0]) return 1 return 0 if __name__ == '__main__': sys.exit(main())