mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-08 21:53:36 +00:00
Define/use file processing routines; fix show filelist allfields
Define and use new file handling primitives to simply code and isolate error handling. Error message cleanup. Google added a new object (userPermission) to the filesResource object which broke showDriveFiles because it has an item named 'id' which wiped out the file id. This fix makes compound column names for all dictionary objects except for labels.
This commit is contained in:
262
src/gam.py
262
src/gam.py
@ -28,7 +28,7 @@ __author__ = u'Jay Lee <jay0lee@gmail.com>'
|
|||||||
__version__ = u'3.62'
|
__version__ = u'3.62'
|
||||||
__license__ = u'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
__license__ = u'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
import sys, os, time, datetime, random, socket, csv, platform, re, calendar, base64, string, subprocess
|
import sys, os, time, datetime, random, socket, csv, platform, re, calendar, base64, string, StringIO, subprocess
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import httplib2
|
import httplib2
|
||||||
@ -206,6 +206,59 @@ def noPythonSSLExit():
|
|||||||
def printLine(message):
|
def printLine(message):
|
||||||
sys.stdout.write(message+u'\n')
|
sys.stdout.write(message+u'\n')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Open a file
|
||||||
|
#
|
||||||
|
def openFile(filename, mode='rb'):
|
||||||
|
try:
|
||||||
|
if filename != u'-':
|
||||||
|
return open(filename, mode)
|
||||||
|
if mode.startswith(u'r'):
|
||||||
|
return StringIO.StringIO(unicode(sys.stdin.read()))
|
||||||
|
return sys.stdout
|
||||||
|
except IOError as e:
|
||||||
|
systemErrorExit(6, e)
|
||||||
|
#
|
||||||
|
# Close a file
|
||||||
|
#
|
||||||
|
def closeFile(f):
|
||||||
|
try:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
except IOError as e:
|
||||||
|
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, e))
|
||||||
|
return False
|
||||||
|
#
|
||||||
|
# Read a file
|
||||||
|
#
|
||||||
|
def readFile(filename, mode='rb', continueOnError=False, displayError=True):
|
||||||
|
try:
|
||||||
|
if filename != u'-':
|
||||||
|
with open(filename, mode) as f:
|
||||||
|
return f.read()
|
||||||
|
else:
|
||||||
|
return unicode(sys.stdin.read())
|
||||||
|
except IOError as e:
|
||||||
|
if continueOnError:
|
||||||
|
if displayError:
|
||||||
|
sys.stderr.write(u'{0}{1}\n'.format(WARNING_PREFIX, e))
|
||||||
|
return None
|
||||||
|
systemErrorExit(6, e)
|
||||||
|
#
|
||||||
|
# Write a file
|
||||||
|
#
|
||||||
|
def writeFile(filename, data, mode='wb', continueOnError=False, displayError=True):
|
||||||
|
try:
|
||||||
|
with open(filename, mode) as f:
|
||||||
|
f.write(data)
|
||||||
|
return True
|
||||||
|
except IOError as e:
|
||||||
|
if continueOnError:
|
||||||
|
if displayError:
|
||||||
|
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, e))
|
||||||
|
return False
|
||||||
|
systemErrorExit(6, e)
|
||||||
|
|
||||||
def setGamDirs():
|
def setGamDirs():
|
||||||
global gamPath, gamSiteConfigDir, gamUserConfigDir, gamDriveDir, gamCacheDir
|
global gamPath, gamSiteConfigDir, gamUserConfigDir, gamDriveDir, gamCacheDir
|
||||||
gamPath = os.path.dirname(os.path.realpath(__file__))
|
gamPath = os.path.dirname(os.path.realpath(__file__))
|
||||||
@ -216,6 +269,8 @@ def setGamDirs():
|
|||||||
else:
|
else:
|
||||||
gamCacheDir = os.environ.get(u'GAMCACHEDIR', os.path.join(gamPath, u'gamcache'))
|
gamCacheDir = os.environ.get(u'GAMCACHEDIR', os.path.join(gamPath, u'gamcache'))
|
||||||
gamDriveDir = os.environ.get(u'GAMDRIVEDIR', gamPath)
|
gamDriveDir = os.environ.get(u'GAMDRIVEDIR', gamPath)
|
||||||
|
if not os.path.isfile(os.path.join(gamUserConfigDir, u'noupdatecheck.txt')):
|
||||||
|
doGAMCheckForUpdates()
|
||||||
|
|
||||||
def doGAMVersion():
|
def doGAMVersion():
|
||||||
import struct
|
import struct
|
||||||
@ -227,33 +282,29 @@ def doGAMVersion():
|
|||||||
platform.platform(), platform.machine(),
|
platform.platform(), platform.machine(),
|
||||||
gamPath)
|
gamPath)
|
||||||
|
|
||||||
def doGAMCheckForUpdates():
|
def doGAMCheckForUpdates(forceCheck=False):
|
||||||
import urllib2
|
import urllib2
|
||||||
if os.path.isfile(os.path.join(gamUserConfigDir, u'noupdatecheck.txt')):
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
current_version = float(__version__)
|
current_version = float(__version__)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return
|
return
|
||||||
if os.path.isfile(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT)):
|
|
||||||
f = open(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT), 'r')
|
|
||||||
last_check_time = int(f.readline())
|
|
||||||
f.close()
|
|
||||||
else:
|
|
||||||
last_check_time = 0
|
|
||||||
now_time = calendar.timegm(time.gmtime())
|
now_time = calendar.timegm(time.gmtime())
|
||||||
if last_check_time > now_time-604800:
|
if not forceCheck:
|
||||||
return
|
last_check_time = readFile(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT), continueOnError=True, displayError=forceCheck)
|
||||||
|
if last_check_time == None:
|
||||||
|
last_check_time = 0
|
||||||
|
if last_check_time > now_time-604800:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
c = urllib2.urlopen(GAM_APPSPOT_LATEST_VERSION)
|
c = urllib2.urlopen(GAM_APPSPOT_LATEST_VERSION)
|
||||||
try:
|
try:
|
||||||
latest_version = float(c.read())
|
latest_version = float(c.read())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return
|
return
|
||||||
|
if forceCheck or (latest_version > current_version):
|
||||||
|
print u'Version: Check, Current: {0:.2f}, Latest: {1:.2f}'.format(current_version, latest_version)
|
||||||
if latest_version <= current_version:
|
if latest_version <= current_version:
|
||||||
f = open(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT), 'w')
|
writeFile(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT), str(now_time), continueOnError=True, displayError=forceCheck)
|
||||||
f.write(str(now_time))
|
|
||||||
f.close()
|
|
||||||
return
|
return
|
||||||
a = urllib2.urlopen(GAM_APPSPOT_LATEST_VERSION_ANNOUNCEMENT)
|
a = urllib2.urlopen(GAM_APPSPOT_LATEST_VERSION_ANNOUNCEMENT)
|
||||||
announcement = a.read()
|
announcement = a.read()
|
||||||
@ -266,29 +317,23 @@ def doGAMCheckForUpdates():
|
|||||||
webbrowser.open(GAM_RELEASES)
|
webbrowser.open(GAM_RELEASES)
|
||||||
printLine(MESSAGE_GAM_EXITING_FOR_UPDATE)
|
printLine(MESSAGE_GAM_EXITING_FOR_UPDATE)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
f = open(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT), 'w')
|
writeFile(os.path.join(gamUserConfigDir, FN_LAST_UPDATE_CHECK_TXT), str(now_time), continueOnError=True, displayError=forceCheck)
|
||||||
f.write(str(now_time))
|
except (urllib2.HTTPError, urllib2.URLError):
|
||||||
f.close()
|
|
||||||
except urllib2.HTTPError:
|
|
||||||
return
|
|
||||||
except urllib2.URLError:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def checkErrorCode(e, service):
|
def checkGDataError(e, service):
|
||||||
|
|
||||||
# First check for errors that need special handling
|
# First check for errors that need special handling
|
||||||
if e[0].get('reason', '') in [u'Token invalid - Invalid token: Stateless token expired', u'Token invalid - Invalid token: Token not found']:
|
if e[0].get(u'reason', u'') in [u'Token invalid - Invalid token: Stateless token expired', u'Token invalid - Invalid token: Token not found']:
|
||||||
keep_domain = service.domain
|
keep_domain = service.domain
|
||||||
tryOAuth(service)
|
tryOAuth(service)
|
||||||
service.domain = keep_domain
|
service.domain = keep_domain
|
||||||
return False
|
return False
|
||||||
if e[0]['body'][:34] in [u'Required field must not be blank: ', u'These characters are not allowed: ']:
|
if e[0][u'body'].startswith(u'Required field must not be blank:') or e[0][u'body'].startswith(u'These characters are not allowed:'):
|
||||||
return e[0]['body']
|
return e[0]['body']
|
||||||
if e.error_code == 600 and e[0][u'body'] == u'Quota exceeded for the current request' or e[0][u'reason'] == u'Bad Gateway':
|
if e.error_code == 600 and e[0][u'body'] == u'Quota exceeded for the current request' or e[0][u'reason'] == u'Bad Gateway':
|
||||||
return False
|
return False
|
||||||
if e.error_code == 600 and e[0][u'reason'] == u'Token invalid - Invalid token: Token disabled, revoked, or expired.':
|
if e.error_code == 600 and e[0][u'reason'] == u'Token invalid - Invalid token: Token disabled, revoked, or expired.':
|
||||||
return u'403 - Token disabled, revoked, or expired. Please delete and re-create oauth.txt'
|
return u'403 - Token disabled, revoked, or expired. Please delete and re-create oauth.txt'
|
||||||
|
|
||||||
# We got a "normal" error, define the mapping below
|
# We got a "normal" error, define the mapping below
|
||||||
error_code_map = {
|
error_code_map = {
|
||||||
1000: False,
|
1000: False,
|
||||||
@ -325,8 +370,7 @@ def checkErrorCode(e, service):
|
|||||||
1800: u'Group Cannot Contain Cycle',
|
1800: u'Group Cannot Contain Cycle',
|
||||||
1801: u'Invalid value %s' % getattr(e, u'invalidInput', u'<unknown>'),
|
1801: u'Invalid value %s' % getattr(e, u'invalidInput', u'<unknown>'),
|
||||||
}
|
}
|
||||||
|
return u'{0} - {1}'.format(e.error_code, error_code_map.get(e.error_code, u'Unknown Error: {0}'.format(str(e))))
|
||||||
return u'%s - %s' % (e.error_code, error_code_map.get(e.error_code, u'Unknown Error: %s' % (str(e))))
|
|
||||||
|
|
||||||
def tryOAuth(gdataObject):
|
def tryOAuth(gdataObject):
|
||||||
global domain
|
global domain
|
||||||
@ -356,7 +400,7 @@ def callGData(service, function, soft_errors=False, throw_errors=[], **kwargs):
|
|||||||
try:
|
try:
|
||||||
return method(**kwargs)
|
return method(**kwargs)
|
||||||
except gdata.apps.service.AppsForYourDomainException, e:
|
except gdata.apps.service.AppsForYourDomainException, e:
|
||||||
terminating_error = checkErrorCode(e, service)
|
terminating_error = checkGDataError(e, service)
|
||||||
if e.error_code in throw_errors:
|
if e.error_code in throw_errors:
|
||||||
raise
|
raise
|
||||||
if not terminating_error and n != retries:
|
if not terminating_error and n != retries:
|
||||||
@ -369,13 +413,12 @@ def callGData(service, function, soft_errors=False, throw_errors=[], **kwargs):
|
|||||||
if n > 3:
|
if n > 3:
|
||||||
sys.stderr.write(u'attempt %s/%s\n' % (n+1, retries))
|
sys.stderr.write(u'attempt %s/%s\n' % (n+1, retries))
|
||||||
continue
|
continue
|
||||||
sys.stderr.write(u'Error: %s' % terminating_error)
|
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, terminating_error))
|
||||||
if soft_errors:
|
if soft_errors:
|
||||||
if n != 1:
|
if n != 1:
|
||||||
sys.stderr.write(u' - Giving up.\n')
|
sys.stderr.write(u' - Giving up.\n')
|
||||||
return
|
return
|
||||||
else:
|
sys.exit(int(e.error_code))
|
||||||
sys.exit(int(e.error_code))
|
|
||||||
|
|
||||||
def callGAPI(service, function, silent_errors=False, soft_errors=False, throw_reasons=[], retry_reasons=[], **kwargs):
|
def callGAPI(service, function, silent_errors=False, soft_errors=False, throw_reasons=[], retry_reasons=[], **kwargs):
|
||||||
method = getattr(service, function)
|
method = getattr(service, function)
|
||||||
@ -398,7 +441,7 @@ def callGAPI(service, function, silent_errors=False, soft_errors=False, throw_re
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
continue
|
continue
|
||||||
if not silent_errors:
|
if not silent_errors:
|
||||||
print u'ERROR: %s' % e.content
|
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, e.content))
|
||||||
if soft_errors:
|
if soft_errors:
|
||||||
return
|
return
|
||||||
sys.exit(5)
|
sys.exit(5)
|
||||||
@ -420,14 +463,14 @@ def callGAPI(service, function, silent_errors=False, soft_errors=False, throw_re
|
|||||||
if n > 3:
|
if n > 3:
|
||||||
sys.stderr.write(u'attempt %s/%s\n' % (n+1, retries))
|
sys.stderr.write(u'attempt %s/%s\n' % (n+1, retries))
|
||||||
continue
|
continue
|
||||||
sys.stderr.write(u'Error %s: %s - %s\n\n' % (http_status, message, reason))
|
sys.stderr.write(u'{0}{1}: {2} - {3}\n'.format(ERROR_PREFIX, http_status, message, reason))
|
||||||
if soft_errors:
|
if soft_errors:
|
||||||
if n != 1:
|
if n != 1:
|
||||||
sys.stderr.write(u' - Giving up.\n')
|
sys.stderr.write(u' - Giving up.\n')
|
||||||
return
|
return
|
||||||
sys.exit(int(http_status))
|
sys.exit(int(http_status))
|
||||||
except oauth2client.client.AccessTokenRefreshError, e:
|
except oauth2client.client.AccessTokenRefreshError, e:
|
||||||
sys.stderr.write(u'Error: Authentication Token Error - %s' % e)
|
sys.stderr.write(u'{0}Authentication Token Error: {1}\n'.format(ERROR_PREFIX, e))
|
||||||
sys.exit(403)
|
sys.exit(403)
|
||||||
except httplib2.CertificateValidationUnsupported:
|
except httplib2.CertificateValidationUnsupported:
|
||||||
noPythonSSLExit()
|
noPythonSSLExit()
|
||||||
@ -525,11 +568,9 @@ def getServiceFromDiscoveryDocument(api, version, http):
|
|||||||
else:
|
else:
|
||||||
pyinstaller_disc_file = None
|
pyinstaller_disc_file = None
|
||||||
if os.path.isfile(disc_file):
|
if os.path.isfile(disc_file):
|
||||||
with open(disc_file, 'rb') as f:
|
discovery = readFile(disc_file)
|
||||||
discovery = f.read()
|
|
||||||
elif pyinstaller_disc_file:
|
elif pyinstaller_disc_file:
|
||||||
with open(pyinstaller_disc_file, 'rb') as f:
|
discovery = readFile(pyinstaller_disc_file)
|
||||||
discovery = f.read()
|
|
||||||
else:
|
else:
|
||||||
systemErrorExit(4, MESSAGE_NO_DISCOVERY_INFORMATION.format(disc_file))
|
systemErrorExit(4, MESSAGE_NO_DISCOVERY_INFORMATION.format(disc_file))
|
||||||
return googleapiclient.discovery.build_from_document(discovery, base=u'https://www.googleapis.com', http=http)
|
return googleapiclient.discovery.build_from_document(discovery, base=u'https://www.googleapis.com', http=http)
|
||||||
@ -582,9 +623,8 @@ def buildGAPIServiceObject(api, act_as=None, soft_errors=False):
|
|||||||
oauth2servicefile = os.path.join(gamUserConfigDir, os.environ.get(u'OAUTHSERVICEFILE', 'oauth2service'))
|
oauth2servicefile = os.path.join(gamUserConfigDir, os.environ.get(u'OAUTHSERVICEFILE', 'oauth2service'))
|
||||||
oauth2servicefilejson = u'%s.json' % oauth2servicefile
|
oauth2servicefilejson = u'%s.json' % oauth2servicefile
|
||||||
oauth2servicefilep12 = u'%s.p12' % oauth2servicefile
|
oauth2servicefilep12 = u'%s.p12' % oauth2servicefile
|
||||||
try:
|
json_string = readFile(oauth2servicefilejson, continueOnError=True, displayError=True)
|
||||||
json_string = open(oauth2servicefilejson).read()
|
if not json_string:
|
||||||
except IOError, e:
|
|
||||||
printLine(MESSAGE_WIKI_INSTRUCTIONS_OAUTH2SERVICE_JSON)
|
printLine(MESSAGE_WIKI_INSTRUCTIONS_OAUTH2SERVICE_JSON)
|
||||||
printLine(GAM_WIKI_CREATE_CLIENT_SECRETS)
|
printLine(GAM_WIKI_CREATE_CLIENT_SECRETS)
|
||||||
sys.exit(6)
|
sys.exit(6)
|
||||||
@ -592,9 +632,7 @@ def buildGAPIServiceObject(api, act_as=None, soft_errors=False):
|
|||||||
try:
|
try:
|
||||||
SERVICE_ACCOUNT_EMAIL = json_data[u'web'][u'client_email']
|
SERVICE_ACCOUNT_EMAIL = json_data[u'web'][u'client_email']
|
||||||
SERVICE_ACCOUNT_CLIENT_ID = json_data[u'web'][u'client_id']
|
SERVICE_ACCOUNT_CLIENT_ID = json_data[u'web'][u'client_id']
|
||||||
f = file(oauth2servicefilep12, 'rb')
|
key = readFile(oauth2servicefilep12)
|
||||||
key = f.read()
|
|
||||||
f.close()
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# new format with config and data in the .json file...
|
# new format with config and data in the .json file...
|
||||||
SERVICE_ACCOUNT_EMAIL = json_data[u'client_email']
|
SERVICE_ACCOUNT_EMAIL = json_data[u'client_email']
|
||||||
@ -652,7 +690,7 @@ def buildDiscoveryObject(api):
|
|||||||
try:
|
try:
|
||||||
return json.loads(content)
|
return json.loads(content)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
sys.stderr.write(u'Failed to parse as JSON: ' + content+u'\n')
|
sys.stderr.write(u'{0}Failed to parse as JSON: {1}\n'.format(ERROR_PREFIX, content))
|
||||||
raise googleapiclient.errors.InvalidJsonError()
|
raise googleapiclient.errors.InvalidJsonError()
|
||||||
|
|
||||||
def commonAppsObjInit(appsObj):
|
def commonAppsObjInit(appsObj):
|
||||||
@ -685,7 +723,7 @@ def getResCalObject():
|
|||||||
def geturl(url, dst):
|
def geturl(url, dst):
|
||||||
import urllib2
|
import urllib2
|
||||||
u = urllib2.urlopen(url)
|
u = urllib2.urlopen(url)
|
||||||
f = open(dst, 'wb')
|
f = openFile(dst, 'wb')
|
||||||
meta = u.info()
|
meta = u.info()
|
||||||
try:
|
try:
|
||||||
file_size = int(meta.getheaders(u'Content-Length')[0])
|
file_size = int(meta.getheaders(u'Content-Length')[0])
|
||||||
@ -705,7 +743,7 @@ def geturl(url, dst):
|
|||||||
status = r"%10d [unknown size]" % (file_size_dl)
|
status = r"%10d [unknown size]" % (file_size_dl)
|
||||||
status = status + chr(8)*(len(status)+1)
|
status = status + chr(8)*(len(status)+1)
|
||||||
print status,
|
print status,
|
||||||
f.close()
|
closeFile(f)
|
||||||
|
|
||||||
def showReport():
|
def showReport():
|
||||||
report = sys.argv[2].lower()
|
report = sys.argv[2].lower()
|
||||||
@ -1181,8 +1219,7 @@ def doGetDomainInfo():
|
|||||||
if (len(sys.argv) < 4) or (sys.argv[3] == u'logo'):
|
if (len(sys.argv) < 4) or (sys.argv[3] == u'logo'):
|
||||||
doGetInstanceInfo()
|
doGetInstanceInfo()
|
||||||
return
|
return
|
||||||
else:
|
domainName = sys.argv[3]
|
||||||
domainName = sys.argv[3]
|
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
result = callGAPI(service=cd.domains(), function=u'get', customer=customerId, domainName=domainName)
|
result = callGAPI(service=cd.domains(), function=u'get', customer=customerId, domainName=domainName)
|
||||||
if u'creationTime' in result:
|
if u'creationTime' in result:
|
||||||
@ -2184,13 +2221,11 @@ def doPrintJobFetch():
|
|||||||
fileName = u''.join(c if c in valid_chars else u'_' for c in fileName)
|
fileName = u''.join(c if c in valid_chars else u'_' for c in fileName)
|
||||||
fileName = u'%s-%s' % (fileName, jobid)
|
fileName = u'%s-%s' % (fileName, jobid)
|
||||||
_, content = cp._http.request(uri=fileUrl, method='GET')
|
_, content = cp._http.request(uri=fileUrl, method='GET')
|
||||||
f = open(fileName, 'wb')
|
if writeFile(fileName, content, continueOnError=True):
|
||||||
f.write(content)
|
# ticket = callGAPI(service=cp.jobs(), function=u'getticket', jobid=jobid, use_cjt=True)
|
||||||
f.close()
|
result = callGAPI(service=cp.jobs(), function=u'update', jobid=jobid, semantic_state_diff=ssd)
|
||||||
#ticket = callGAPI(service=cp.jobs(), function=u'getticket', jobid=jobid, use_cjt=True)
|
checkCloudPrintResult(result)
|
||||||
result = callGAPI(service=cp.jobs(), function=u'update', jobid=jobid, semantic_state_diff=ssd)
|
print u'Printed job %s to %s' % (jobid, fileName)
|
||||||
checkCloudPrintResult(result)
|
|
||||||
print u'Printed job %s to %s' % (jobid, fileName)
|
|
||||||
|
|
||||||
def doDelPrinter():
|
def doDelPrinter():
|
||||||
cp = buildGAPIObject(u'cloudprint')
|
cp = buildGAPIObject(u'cloudprint')
|
||||||
@ -2331,9 +2366,7 @@ def doPrintJobSubmit():
|
|||||||
mimetype = mimetypes.guess_type(filepath)[0]
|
mimetype = mimetypes.guess_type(filepath)[0]
|
||||||
if mimetype == None:
|
if mimetype == None:
|
||||||
mimetype = u'application/octet-stream'
|
mimetype = u'application/octet-stream'
|
||||||
f = open(filepath, 'rb')
|
filecontent = readFile(filepath)
|
||||||
filecontent = f.read()
|
|
||||||
f.close()
|
|
||||||
form_files[u'content'] = {u'filename': content, u'content': filecontent, u'mimetype': mimetype}
|
form_files[u'content'] = {u'filename': content, u'content': filecontent, u'mimetype': mimetype}
|
||||||
#result = callGAPI(service=cp.printers(), function=u'submit', body=body)
|
#result = callGAPI(service=cp.printers(), function=u'submit', body=body)
|
||||||
body, headers = encode_multipart(form_fields, form_files)
|
body, headers = encode_multipart(form_fields, form_files)
|
||||||
@ -2641,9 +2674,8 @@ def doPhoto(users):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
f = open(filename, 'rb')
|
with open(filename, 'rb') as f:
|
||||||
image_data = f.read()
|
image_data = f.read()
|
||||||
f.close()
|
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
print u' couldn\'t open %s: %s' % (filename, e.strerror)
|
print u' couldn\'t open %s: %s' % (filename, e.strerror)
|
||||||
continue
|
continue
|
||||||
@ -2675,9 +2707,7 @@ def getPhoto(users):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
print u' no photo for %s' % user
|
print u' no photo for %s' % user
|
||||||
continue
|
continue
|
||||||
photo_file = open(filename, 'wb')
|
writeFile(filename, photo_data, continueOnError=True)
|
||||||
photo_file.write(photo_data)
|
|
||||||
photo_file.close()
|
|
||||||
|
|
||||||
def deletePhoto(users):
|
def deletePhoto(users):
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
@ -3025,13 +3055,21 @@ def showDriveFiles(users):
|
|||||||
elif attrib_type is unicode or attrib_type is bool:
|
elif attrib_type is unicode or attrib_type is bool:
|
||||||
a_file[attrib] = f_file[attrib]
|
a_file[attrib] = f_file[attrib]
|
||||||
elif attrib_type is dict:
|
elif attrib_type is dict:
|
||||||
for dict_attrib in f_file[attrib]:
|
if attrib == u'labels':
|
||||||
if dict_attrib in [u'kind', u'etags', u'etag']:
|
for dict_attrib in f_file[attrib]:
|
||||||
continue
|
if dict_attrib not in titles:
|
||||||
if dict_attrib not in titles:
|
titles.append(dict_attrib)
|
||||||
titles.append(dict_attrib)
|
files_attr[0][dict_attrib] = dict_attrib
|
||||||
files_attr[0][dict_attrib] = dict_attrib
|
a_file[dict_attrib] = f_file[attrib][dict_attrib]
|
||||||
a_file[dict_attrib] = f_file[attrib][dict_attrib]
|
else:
|
||||||
|
for dict_attrib in f_file[attrib]:
|
||||||
|
if dict_attrib in [u'kind', u'etags', u'etag']:
|
||||||
|
continue
|
||||||
|
x_attrib = u'{0}.{1}'.format(attrib, dict_attrib)
|
||||||
|
if x_attrib not in titles:
|
||||||
|
titles.append(x_attrib)
|
||||||
|
files_attr[0][x_attrib] = x_attrib
|
||||||
|
a_file[x_attrib] = f_file[attrib][dict_attrib]
|
||||||
else:
|
else:
|
||||||
print attrib_type
|
print attrib_type
|
||||||
files_attr.append(a_file)
|
files_attr.append(a_file)
|
||||||
@ -3492,9 +3530,7 @@ def downloadDriveFile(users):
|
|||||||
filename = new_filename
|
filename = new_filename
|
||||||
print convertUTF8(my_line % filename)
|
print convertUTF8(my_line % filename)
|
||||||
_, content = drive._http.request(download_url)
|
_, content = drive._http.request(download_url)
|
||||||
f = open(filename, 'wb')
|
writeFile(filename, content, continueOnError=True)
|
||||||
f.write(content)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def showDriveFileInfo(users):
|
def showDriveFileInfo(users):
|
||||||
for user in users:
|
for user in users:
|
||||||
@ -3516,7 +3552,7 @@ def showDriveFileInfo(users):
|
|||||||
if setti == u'kind':
|
if setti == u'kind':
|
||||||
continue
|
continue
|
||||||
print convertUTF8(u' %s: %s' % (setti, settin[setti]))
|
print convertUTF8(u' %s: %s' % (setti, settin[setti]))
|
||||||
print ''
|
print u''
|
||||||
elif setting_type == u"<type 'dict'>":
|
elif setting_type == u"<type 'dict'>":
|
||||||
print u'%s:' % setting
|
print u'%s:' % setting
|
||||||
for settin in feed[setting]:
|
for settin in feed[setting]:
|
||||||
@ -4384,9 +4420,7 @@ def getForward(users):
|
|||||||
def doSignature(users):
|
def doSignature(users):
|
||||||
import cgi
|
import cgi
|
||||||
if sys.argv[4].lower() == u'file':
|
if sys.argv[4].lower() == u'file':
|
||||||
fp = open(sys.argv[5], 'rb')
|
signature = cgi.escape(readFile(sys.argv[5]).replace(u'\\n', u'
').replace(u'"', u"'"))
|
||||||
signature = cgi.escape(fp.read().replace(u'\\n', u'
').replace(u'"', u"'"))
|
|
||||||
fp.close()
|
|
||||||
else:
|
else:
|
||||||
signature = cgi.escape(sys.argv[4]).replace(u'\\n', u'
').replace(u'"', u"'")
|
signature = cgi.escape(sys.argv[4]).replace(u'\\n', u'
').replace(u'"', u"'")
|
||||||
xmlsig = u'''<?xml version="1.0" encoding="utf-8"?>
|
xmlsig = u'''<?xml version="1.0" encoding="utf-8"?>
|
||||||
@ -4476,9 +4510,7 @@ def doVacation(users):
|
|||||||
end_date = sys.argv[i+1]
|
end_date = sys.argv[i+1]
|
||||||
i += 2
|
i += 2
|
||||||
elif sys.argv[i].lower() == u'file':
|
elif sys.argv[i].lower() == u'file':
|
||||||
fp = open(sys.argv[i+1], 'rb')
|
message = readFile(sys.argv[i+1])
|
||||||
message = fp.read()
|
|
||||||
fp.close()
|
|
||||||
i += 2
|
i += 2
|
||||||
else:
|
else:
|
||||||
print u'ERROR: %s is not a valid argument for "gam <users> vacation"' % sys.argv[i]
|
print u'ERROR: %s is not a valid argument for "gam <users> vacation"' % sys.argv[i]
|
||||||
@ -4916,9 +4948,6 @@ def doCreateUser():
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
body[u'externalIds'] = [externalid,]
|
body[u'externalIds'] = [externalid,]
|
||||||
i += 1
|
i += 1
|
||||||
# else:
|
|
||||||
# showUsage()
|
|
||||||
# sys.exit(2)
|
|
||||||
else:
|
else:
|
||||||
if u'customSchemas' not in body:
|
if u'customSchemas' not in body:
|
||||||
body[u'customSchemas'] = {}
|
body[u'customSchemas'] = {}
|
||||||
@ -5963,7 +5992,7 @@ def doGetUserInfo(user_email=None):
|
|||||||
for address in user[u'addresses']:
|
for address in user[u'addresses']:
|
||||||
for key in address:
|
for key in address:
|
||||||
print convertUTF8(u' %s: %s' % (key, address[key]))
|
print convertUTF8(u' %s: %s' % (key, address[key]))
|
||||||
print ''
|
print u''
|
||||||
if u'organizations' in user:
|
if u'organizations' in user:
|
||||||
print u'Organizations:'
|
print u'Organizations:'
|
||||||
for org in user[u'organizations']:
|
for org in user[u'organizations']:
|
||||||
@ -6265,9 +6294,7 @@ def doSiteVerifyShow():
|
|||||||
webserver_file_record = callGAPI(service=verif.webResource(), function=u'getToken', body={u'site':{u'type':u'SITE', u'identifier':u'http://%s/' % a_domain}, u'verificationMethod':u'FILE'})
|
webserver_file_record = callGAPI(service=verif.webResource(), function=u'getToken', body={u'site':{u'type':u'SITE', u'identifier':u'http://%s/' % a_domain}, u'verificationMethod':u'FILE'})
|
||||||
webserver_file_token = webserver_file_record[u'token']
|
webserver_file_token = webserver_file_record[u'token']
|
||||||
print u'Saving web server verification file to: %s' % webserver_file_token
|
print u'Saving web server verification file to: %s' % webserver_file_token
|
||||||
f = open(webserver_file_token, 'wb')
|
writeFile(webserver_file_token, u'google-site-verification: {0}'.format(webserver_file_token), continueOnError=True)
|
||||||
f.write(u'google-site-verification: %s' % webserver_file_token)
|
|
||||||
f.close()
|
|
||||||
print u'Verification File URL: http://%s/%s' % (a_domain, webserver_file_token)
|
print u'Verification File URL: http://%s/%s' % (a_domain, webserver_file_token)
|
||||||
print
|
print
|
||||||
webserver_meta_record = callGAPI(service=verif.webResource(), function=u'getToken', body={u'site':{u'type':u'SITE', u'identifier':u'http://%s/' % a_domain}, u'verificationMethod':u'META'})
|
webserver_meta_record = callGAPI(service=verif.webResource(), function=u'getToken', body={u'site':{u'type':u'SITE', u'identifier':u'http://%s/' % a_domain}, u'verificationMethod':u'META'})
|
||||||
@ -6472,7 +6499,7 @@ def doGenBackupCodes(users):
|
|||||||
callGAPI(service=cd.verificationCodes(), function=u'generate', userKey=user)
|
callGAPI(service=cd.verificationCodes(), function=u'generate', userKey=user)
|
||||||
codes = callGAPI(service=cd.verificationCodes(), function=u'list', userKey=user)
|
codes = callGAPI(service=cd.verificationCodes(), function=u'list', userKey=user)
|
||||||
print u'Backup verification codes for %s' % user
|
print u'Backup verification codes for %s' % user
|
||||||
print ''
|
print u''
|
||||||
try:
|
try:
|
||||||
i = 0
|
i = 0
|
||||||
while True:
|
while True:
|
||||||
@ -6537,7 +6564,7 @@ def doGetTokens(users):
|
|||||||
print u' %s: %s' % (item, token[item])
|
print u' %s: %s' % (item, token[item])
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
print u' %s: %s' % (item, token[item][:-1])
|
print u' %s: %s' % (item, token[item][:-1])
|
||||||
print ''
|
print u''
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print u' no tokens for %s' % user
|
print u' no tokens for %s' % user
|
||||||
print u''
|
print u''
|
||||||
@ -6593,15 +6620,9 @@ def doUpdateInstance():
|
|||||||
admin_secondary_email = sys.argv[4]
|
admin_secondary_email = sys.argv[4]
|
||||||
callGData(service=adminObj, function=u'UpdateAdminSecondaryEmail', adminSecondaryEmail=admin_secondary_email)
|
callGData(service=adminObj, function=u'UpdateAdminSecondaryEmail', adminSecondaryEmail=admin_secondary_email)
|
||||||
elif command == u'logo':
|
elif command == u'logo':
|
||||||
logo_file = sys.argv[4]
|
logoFile = sys.argv[4]
|
||||||
try:
|
logoImage = readFile(logoFile)
|
||||||
fp = open(logo_file, 'rb')
|
callGData(service=adminObj, function=u'UpdateDomainLogo', logoImage=logoImage)
|
||||||
logo_image = fp.read()
|
|
||||||
fp.close()
|
|
||||||
except IOError:
|
|
||||||
print u'Error: can\'t open file %s' % logo_file
|
|
||||||
sys.exit(11)
|
|
||||||
callGData(service=adminObj, function=u'UpdateDomainLogo', logoImage=logo_image)
|
|
||||||
elif command == u'mx_verify':
|
elif command == u'mx_verify':
|
||||||
result = callGData(service=adminObj, function=u'UpdateMXVerificationStatus')
|
result = callGData(service=adminObj, function=u'UpdateMXVerificationStatus')
|
||||||
print u'Verification Method: %s' % result[u'verificationMethod']
|
print u'Verification Method: %s' % result[u'verificationMethod']
|
||||||
@ -6645,15 +6666,9 @@ def doUpdateInstance():
|
|||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
callGData(service=adminObj, function=u'UpdateSSOSettings', enableSSO=enableSSO, samlSignonUri=samlSignonUri, samlLogoutUri=samlLogoutUri, changePasswordUri=changePasswordUri, ssoWhitelist=ssoWhitelist, useDomainSpecificIssuer=useDomainSpecificIssuer)
|
callGData(service=adminObj, function=u'UpdateSSOSettings', enableSSO=enableSSO, samlSignonUri=samlSignonUri, samlLogoutUri=samlLogoutUri, changePasswordUri=changePasswordUri, ssoWhitelist=ssoWhitelist, useDomainSpecificIssuer=useDomainSpecificIssuer)
|
||||||
elif command == u'sso_key':
|
elif command == u'sso_key':
|
||||||
key_file = sys.argv[4]
|
keyFile = sys.argv[4]
|
||||||
try:
|
keyData = readFile(keyFile)
|
||||||
fp = open(key_file, 'rb')
|
callGData(service=adminObj, function=u'UpdateSSOKey', signingKey=keyData)
|
||||||
key_data = fp.read()
|
|
||||||
fp.close()
|
|
||||||
except IOError:
|
|
||||||
print u'Error: can\'t open file %s' % logo_file
|
|
||||||
sys.exit(11)
|
|
||||||
callGData(service=adminObj, function=u'UpdateSSOKey', signingKey=key_data)
|
|
||||||
elif command == u'user_migrations':
|
elif command == u'user_migrations':
|
||||||
value = sys.argv[4].lower()
|
value = sys.argv[4].lower()
|
||||||
if value not in [u'true', u'false']:
|
if value not in [u'true', u'false']:
|
||||||
@ -6729,7 +6744,7 @@ def doGetInstanceInfo():
|
|||||||
target_file = sys.argv[4]
|
target_file = sys.argv[4]
|
||||||
url = 'http://www.google.com/a/cpanel/%s/images/logo.gif' % (domain)
|
url = 'http://www.google.com/a/cpanel/%s/images/logo.gif' % (domain)
|
||||||
geturl(url, target_file)
|
geturl(url, target_file)
|
||||||
sys.exit(0)
|
return
|
||||||
print u'Google Apps Domain: %s' % domain
|
print u'Google Apps Domain: %s' % domain
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
if customerId != MY_CUSTOMER:
|
if customerId != MY_CUSTOMER:
|
||||||
@ -6920,7 +6935,6 @@ def doDeleteOrg():
|
|||||||
def output_csv(csv_list, titles, list_type, todrive):
|
def output_csv(csv_list, titles, list_type, todrive):
|
||||||
csv.register_dialect(u'nixstdout', lineterminator=u'\n')
|
csv.register_dialect(u'nixstdout', lineterminator=u'\n')
|
||||||
if todrive:
|
if todrive:
|
||||||
import StringIO
|
|
||||||
string_file = StringIO.StringIO()
|
string_file = StringIO.StringIO()
|
||||||
writer = csv.DictWriter(string_file, fieldnames=titles, dialect=u'nixstdout', quoting=csv.QUOTE_MINIMAL)
|
writer = csv.DictWriter(string_file, fieldnames=titles, dialect=u'nixstdout', quoting=csv.QUOTE_MINIMAL)
|
||||||
else:
|
else:
|
||||||
@ -7908,7 +7922,7 @@ def doStatusActivityRequests():
|
|||||||
print u' Url%s: %s' % (i, results[u'fileUrl%s' % i])
|
print u' Url%s: %s' % (i, results[u'fileUrl%s' % i])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
print ''
|
print u''
|
||||||
except IndexError:
|
except IndexError:
|
||||||
results = callGData(service=audit, function=u'getAllAccountInformationRequestsStatus')
|
results = callGData(service=audit, function=u'getAllAccountInformationRequestsStatus')
|
||||||
print u'Current Activity Requests:'
|
print u'Current Activity Requests:'
|
||||||
@ -8350,8 +8364,7 @@ def doDeleteOAuth():
|
|||||||
try:
|
try:
|
||||||
credentials.revoke_uri = oauth2client.GOOGLE_REVOKE_URI
|
credentials.revoke_uri = oauth2client.GOOGLE_REVOKE_URI
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
print u'Error: Authorization doesn\'t exist'
|
systemErrorExit(1, u'Authorization doesn\'t exist')
|
||||||
sys.exit(1)
|
|
||||||
disable_ssl_certificate_validation = False
|
disable_ssl_certificate_validation = False
|
||||||
if os.path.isfile(os.path.join(gamUserConfigDir, u'noverifyssl.txt')):
|
if os.path.isfile(os.path.join(gamUserConfigDir, u'noverifyssl.txt')):
|
||||||
disable_ssl_certificate_validation = True
|
disable_ssl_certificate_validation = True
|
||||||
@ -8368,7 +8381,7 @@ def doDeleteOAuth():
|
|||||||
try:
|
try:
|
||||||
credentials.revoke(http)
|
credentials.revoke(http)
|
||||||
except oauth2client.client.TokenRevokeError, e:
|
except oauth2client.client.TokenRevokeError, e:
|
||||||
print u'Error: %s' % e
|
sys.stderr.write(u'{0}{1}\n'.format(ERROR_PREFIX, e.message))
|
||||||
os.remove(oauth2file)
|
os.remove(oauth2file)
|
||||||
|
|
||||||
class cmd_flags(object):
|
class cmd_flags(object):
|
||||||
@ -8555,6 +8568,8 @@ def batch_worker():
|
|||||||
q.task_done()
|
q.task_done()
|
||||||
|
|
||||||
def run_batch(items):
|
def run_batch(items):
|
||||||
|
import Queue, threading
|
||||||
|
global q
|
||||||
total_items = len(items)
|
total_items = len(items)
|
||||||
current_item = 0
|
current_item = 0
|
||||||
python_cmd = [sys.executable.lower(),]
|
python_cmd = [sys.executable.lower(),]
|
||||||
@ -8564,8 +8579,7 @@ def run_batch(items):
|
|||||||
num_worker_threads = int(os.environ.get(u'GAM_THREADS', '5'))
|
num_worker_threads = int(os.environ.get(u'GAM_THREADS', '5'))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
num_worker_threads = 5
|
num_worker_threads = 5
|
||||||
import Queue, threading
|
num_worker_threads = min(total_items, num_worker_threads)
|
||||||
global q
|
|
||||||
q = Queue.Queue(maxsize=num_worker_threads) # q.put() gets blocked when trying to create more items than there are workers
|
q = Queue.Queue(maxsize=num_worker_threads) # q.put() gets blocked when trying to create more items than there are workers
|
||||||
print u'starting %s worker threads...' % num_worker_threads
|
print u'starting %s worker threads...' % num_worker_threads
|
||||||
for i in range(num_worker_threads):
|
for i in range(num_worker_threads):
|
||||||
@ -8591,10 +8605,9 @@ try:
|
|||||||
if os.name == u'nt':
|
if os.name == u'nt':
|
||||||
sys.argv = win32_unicode_argv() # cleanup sys.argv on Windows
|
sys.argv = win32_unicode_argv() # cleanup sys.argv on Windows
|
||||||
setGamDirs()
|
setGamDirs()
|
||||||
doGAMCheckForUpdates()
|
|
||||||
if sys.argv[1].lower() == u'batch':
|
if sys.argv[1].lower() == u'batch':
|
||||||
import shlex
|
import shlex
|
||||||
f = file(sys.argv[2], 'rb')
|
f = openFile(sys.argv[2])
|
||||||
items = list()
|
items = list()
|
||||||
for line in f:
|
for line in f:
|
||||||
argv = shlex.split(line)
|
argv = shlex.split(line)
|
||||||
@ -8606,16 +8619,12 @@ try:
|
|||||||
if argv[0] == u'gam':
|
if argv[0] == u'gam':
|
||||||
argv = argv[1:]
|
argv = argv[1:]
|
||||||
items.append(argv)
|
items.append(argv)
|
||||||
|
closeFile(f)
|
||||||
run_batch(items)
|
run_batch(items)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif sys.argv[1].lower() == u'csv':
|
elif sys.argv[1].lower() == u'csv':
|
||||||
csv_filename = sys.argv[2]
|
csv_filename = sys.argv[2]
|
||||||
if csv_filename == u'-':
|
f = openFile(csv_filename)
|
||||||
import StringIO
|
|
||||||
input_string = unicode(sys.stdin.read())
|
|
||||||
f = StringIO.StringIO(input_string)
|
|
||||||
else:
|
|
||||||
f = file(csv_filename, 'rb')
|
|
||||||
input_file = csv.DictReader(f)
|
input_file = csv.DictReader(f)
|
||||||
if sys.argv[3].lower() != 'gam':
|
if sys.argv[3].lower() != 'gam':
|
||||||
print 'ERROR: "gam csv <filename>" should be followed by a full GAM command...'
|
print 'ERROR: "gam csv <filename>" should be followed by a full GAM command...'
|
||||||
@ -8632,6 +8641,7 @@ try:
|
|||||||
else:
|
else:
|
||||||
systemErrorExit(2, MESSAGE_HEADER_NOT_FOUND_IN_CSV_HEADERS.format(arg[1:], ','.join(row.keys())))
|
systemErrorExit(2, MESSAGE_HEADER_NOT_FOUND_IN_CSV_HEADERS.format(arg[1:], ','.join(row.keys())))
|
||||||
items.append(argv)
|
items.append(argv)
|
||||||
|
closeFile(f)
|
||||||
run_batch(items)
|
run_batch(items)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif sys.argv[1].lower() == u'version':
|
elif sys.argv[1].lower() == u'version':
|
||||||
|
Reference in New Issue
Block a user