def addWriterShareIfNotAlready(client, entry, login): if isWriter(client, entry, login): LOG.info(" - No need to add WRITER share to " + login + " on " + entry.title.text.encode(sys.getfilesystemencoding()) + " : already Writer") else: LOG.info(" - Adding WRITER share to " + login + " on " + entry.title.text.encode(sys.getfilesystemencoding())) if not args.dryRun: newScope = gdata.acl.data.AclScope(value=login, type='user') newRole = gdata.acl.data.AclRole(value="writer") newAcl_entry = gdata.docs.data.Acl(scope=newScope, role=newRole) try: uri = entry.GetAclLink( ).href + "?send-notification-emails=true" created_acl_entry = client.Post(newAcl_entry, uri) stats['addwriter'] += 1 except gdata.client.RequestError as error: LOG.error("Current ACL for entry") aclFeed = client.GetAclPermissions(entry.resource_id.text) for acl in aclFeed.entry: LOG.error( " acl : " + str(acl.scope.value) + ' (' + str(acl.scope.type) + ') is ' + str(acl.role.value) + ' of ' + entry.title.text.encode(sys.getfilesystemencoding())) logAndProposeAbort(error) else: stats['addwriter'] += 1
def makeCopy(client, entry, oldLogin, newLogin): if canTransferOwnership(entry): LOG.info("Copying : "+str(entry.title.text.encode(sys.getfilesystemencoding()))) if not args.dryRun: try: duplicated_entry = client.Copy(entry, entry.title.text.encode(sys.getfilesystemencoding())) stats['copied']+=1 #now recopying same righs on duplicated entry aclFeed = client.GetAclPermissions(entry.resource_id.text) for acl in aclFeed.entry: if acl.scope.value==oldLogin: continue if acl.scope.value==newLogin: continue try: LOG.info(" duplicating acl : "+str(acl.scope.value)+' ('+str(acl.scope.type)+') is '+str(acl.role.value)+' from '+entry.title.text.encode(sys.getfilesystemencoding())+" to "+duplicated_entry.title.text.encode(sys.getfilesystemencoding())) newScope = gdata.acl.data.AclScope(value=str(acl.scope.value), type='user') newRole = gdata.acl.data.AclRole(value=str(acl.role.value)) newAcl_entry = gdata.docs.data.Acl(scope=newScope, role=newRole) LOG.info(" dup= : "+str(newAcl_entry.scope.value)+' ('+str(newAcl_entry.scope.type)+') is '+str(newAcl_entry.role.value)) created_acl_entry = client.Post(newAcl_entry, duplicated_entry.GetAclLink().href) except gdata.client.RequestError as error : logAndProposeAbort(error) return duplicated_entry except gdata.client.RequestError as error : logAndProposeAbort(error) else: LOG.error("Manual copy required for "+entry.title.text.encode(sys.getfilesystemencoding())) raw_input("Press a key when done") return None
def removeAllRightsFor(client, entry, targetLogin): LOG.info (" - Removing ALL rights for "+targetLogin+" on "+entry.title.text.encode(sys.getfilesystemencoding())) aclFeed = client.GetAclPermissions(entry.resource_id.text) for acl in aclFeed.entry: if acl.scope.value == targetLogin: LOG.info(" removing acl : "+str(acl.scope.value)+' ('+str(acl.scope.type)+') is '+str(acl.role.value)+' of '+entry.title.text.encode(sys.getfilesystemencoding())) if not args.dryRun: try: client.Delete(acl, force=True) except gdata.client.RequestError as error : logAndProposeAbort(error)
def removeAllRightsIfNotOwned(client, entry, targetLogin): if not isOwner(client, entry, targetLogin): LOG.info (" - Removing ALL rights of "+targetLogin+" on "+entry.title.text.encode(sys.getfilesystemencoding())) aclFeed = client.GetAclPermissions(entry.resource_id.text) for acl in aclFeed.entry: if acl.scope.value==targetLogin: LOG.info(" removing acl : "+str(acl.scope.value)+' ('+str(acl.scope.type)+') is '+str(acl.role.value)+' of '+entry.title.text.encode(sys.getfilesystemencoding())) if not args.dryRun: try: client.Delete(acl, force=True) except gdata.client.RequestError as error : logAndProposeAbort(error) stats['removeoldownerright']+=1 else: LOG.debug(" - Keeping safe owner doc of "+targetLogin+" : "+entry.title.text.encode(sys.getfilesystemencoding()))
def isOwnerOfFolder(folderAsLink, login, stdToken, spreadsheetToken): folderId = folderAsLink.href.split('/')[-1] if args.verbose: LOG.debug ("Trying to access to folder '"+folderAsLink.title+"' ("+folderId+") as user : "******"owner" and acl.scope.value== login: return True return False except gdata.client.Unauthorized as error: LOG.error ("No access to folder "+folderAsLink.title.text.encode(sys.getfilesystemencoding())+" : it seems that "+login+" is not the owner of that folder") LOG.error ("Error: {0}".format(error)) return False
def downloadFeed(client, stdToken, spreadsheetToken, feed, storeFolder, storeFlat, ignoreDualCollections): feed.sort(compareDocsEntryOnName) if len(feed) == 0: LOG.info("No entries in feed - Nothing to backup") cleanStoreFolder(storeFolder) forceFolder(storeFolder) stats = { 'doc': 0, 'spreadsheet': 0, 'impress': 0, 'drawings': 0, 'images': 0, 'pdf': 0, 'other': 0, 'error': 0, 'shared': 0 } for entry in feed: ext = ".pdf" dl = False LOG.info("---\"%s\" de type %s" % (entry.title.text.encode( sys.getfilesystemencoding()), entry.GetDocumentType())) # regular expression to parse RFC3389 updated_time = datetime.datetime( *map(int, re.split('[^\d]', entry.updated.text)[:-1])) date_string = updated_time.strftime('%b %d %Y %H:%M') LOG.info(" |- Timestamp : %s" % date_string) #rights LOG.info(" |- Rights :") try: client.auth_token = stdToken aclFeed = client.GetAclPermissions(entry.resource_id.text) sharedUserAlreadyWriter = False for acl in aclFeed.entry: LOG.info(' | |- ' + str(acl.scope.value) + ' (' + str(acl.scope.type) + ') is ' + str(acl.role.value)) if str(acl.scope.value ) == args.sharedUser and acl.role.value == "writer": sharedUserAlreadyWriter = True if not args.sharedUser == None: if sharedUserAlreadyWriter: LOG.info( " " + str(args.sharedUser) + " is already a writer of that doc. no need to add new ACL " ) else: LOG.info(" Adding 'writer' ACL to : " + args.sharedUser) if not args.dryRun: newScope = gdata.acl.data.AclScope(value=sharedUser, type='user') newRole = gdata.acl.data.AclRole(value='writer') newAcl_entry = gdata.docs.data.Acl(scope=newScope, role=newRole) created_acl_entry = client.Post( newAcl_entry, entry.GetAclLink().href) aclFeed = client.GetAclPermissions( entry.resource_id.text) for acl in aclFeed.entry: LOG.info(' | |- ' + str(acl.scope.value) + ' (' + str(acl.scope.type) + ') is ' + str(acl.role.value)) stats['shared'] += 1 except gdata.client.Unauthorized as error: LOG.error( " | |- CAN'T DISPLAY ACL FOR DOCUMENT : {0}".format(error)) LOG.info(" |- Folders :") for folder in entry.InFolders(): LOG.info(" | |-" + folder.title) if entry.GetDocumentType() == "document": ext = ".doc" stats['doc'] += 1 elif entry.GetDocumentType() == "presentation": ext = ".ppt" stats['impress'] += 1 elif entry.GetDocumentType() == "drawing": ext = ".svg" stats['drawings'] += 1 logInReportFile( storeFolder, ". " + entry.title.text.encode(sys.getfilesystemencoding()) + " : Google can export drawing as SVG file, but can't reimport them! This is terrible!\n" ) logInReportFile( storeFolder, " The only option I'm aware is to share the docs, then make a copy in order to get ownership (because Google can't transfer ownership among domains !! Grrr!!)\n" ) elif entry.GetDocumentType() == "spreadsheet": ext = ".xls" stats['spreadsheet'] += 1 elif entry.GetDocumentType() == "pdf": ext = "" dl = True stats['pdf'] += 1 elif entry.GetDocumentType() == "application/vnd.ms-excel": ext = "" dl = True stats['spreadsheet'] += 1 elif entry.GetDocumentType() == "application/msword": ext = "" dl = True stats['doc'] += 1 elif entry.GetDocumentType() == "application/vnd.ms-powerpoint": ext = "" dl = True stats['impress'] += 1 elif entry.GetDocumentType() == "image/jpeg": ext = "" dl = True stats['images'] += 1 elif entry.GetDocumentType() == "image/png": ext = "" dl = True stats['images'] += 1 elif entry.GetDocumentType() == "image/svg+xml": ext = "" dl = True stats['images'] += 1 elif entry.GetDocumentType() == "text/xml": ext = "" dl = True stats['other'] += 1 elif entry.GetDocumentType() == "video/mpeg": ext = "" dl = True stats['other'] += 1 else: if (args.skip): LOG.error( " |- content type (" + entry.GetDocumentType() + ") is not handled, and skip option is set : DOCUMENT WILL BE SKIPPED ie. NOT SAVED!" ) continue else: raise Exception( "ERROR !!!!!!!! Can't handle that kind of : " + entry.GetDocumentType() + " for entry " + entry.title.text.encode(sys.getfilesystemencoding()) + " ( '--skip' option allow you to bypass this error)") filenameToCreate = computeFileNameFor(entry, ext) file = computeFileForEntry(client, stdToken, spreadsheetToken, storeFolder, entry, filenameToCreate, storeFlat, ignoreDualCollections) try: if not args.dryRun: if dl: LOG.info(" |- > DOWNLOADING...") LOG.info( " \"" + entry.title.text.encode(sys.getfilesystemencoding()) + "\" [" + entry.GetDocumentType() + "] : " + file) client.auth_token = stdToken client.Download(entry, os.path.abspath(file)) else: LOG.info(" |- > EXPORTING...") LOG.info( " \"" + entry.title.text.encode(sys.getfilesystemencoding()) + "\" [" + entry.GetDocumentType() + "] : " + file) client.auth_token = spreadsheetToken client.Export(entry, os.path.abspath(file)) except gdata.client.RequestError as error: stats['error'] += 1 if args.skip: LOG.error(" ERROR :{0}".format(error)) else: raise LOG.info(" |- > ...DONE") time.sleep(1) LOG.info("Stats : " + str(stats)) warnUserOfReportFileIfNecessary(storeFolder) return stats
def isOwner(client, entry, targetLogin): aclFeed = client.GetAclPermissions(entry.resource_id.text) for acl in aclFeed.entry: if acl.role.value == "owner" and acl.scope.value == targetLogin: return True return False
def isWriter(client, entry, login): aclFeed = client.GetAclPermissions(entry.resource_id.text) for acl in aclFeed.entry: if acl.role.value == "writer" and acl.scope.value == login: return True return False