Handle showsize/showsizeunits independently

This commit is contained in:
Ross Scroggs
2026-03-10 09:30:37 -07:00
parent a987ff4eac
commit 4f992f4d41
3 changed files with 75 additions and 60 deletions

View File

@@ -7498,7 +7498,7 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
[filenamematchpattern <REMatchPattern>] [filenamematchpattern <REMatchPattern>]
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
[excludetrashed] [excludetrashed]
[showsize|showsizeunits] [showmimetypesize] [showsize] [showsizeunits] [showmimetypesize]
[showlastmodification] [pathdelimiter <Character>] [showlastmodification] [pathdelimiter <Character>]
(addcsvdata <FieldName> <String>)* (addcsvdata <FieldName> <String>)*
[summary none|only|plus] [summaryuser <String>] [summary none|only|plus] [summaryuser <String>]
@@ -7514,7 +7514,7 @@ gam <UserTypeEntity> show filecounts
[filenamematchpattern <REMatchPattern>] [filenamematchpattern <REMatchPattern>]
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
[excludetrashed] [excludetrashed]
[showsize|showsizeunits] [showmimetypesize] [showsize] [showsizeunits] [showmimetypesize]
[showlastmodification] [pathdelimiter <Character>] [showlastmodification] [pathdelimiter <Character>]
[summary none|only|plus] [summaryuser <String>] [summary none|only|plus] [summaryuser <String>]
@@ -7584,7 +7584,7 @@ gam <UserTypeEntity> print filelist [todrive <ToDriveAttribute>*]
[excludetrashed] [excludetrashed]
[maxfiles <Integer>] [nodataheaders <String>] [maxfiles <Integer>] [nodataheaders <String>]
[countsonly [summary none|only|plus] [summaryuser <String>] [countsonly [summary none|only|plus] [summaryuser <String>]
[showsource] [showsize|showsizeunits] [showmimetypesize]] [showsource] [showsize] [showsizeunits] [showmimetypesize]]
[countsrowfilter] [countsrowfilter]
[filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree] [filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)] [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]

View File

@@ -1,8 +1,16 @@
7.35.03
Updated `gam <UserTypeEntity> print filelist|filecounts` to handle options `showsize` and `showsizeunits` as independent options.
* `showsize` - Display a column `Size` with a byte count
* `showsizeunits` - Display a column `SizeUnits` with a formatted size with units
If you select both options, you can sort multiple rows using the `Size` column.
7.35.02 7.35.02
Added option `showsizeunits` to `gam gam <UserTypeEntity> print filelist|filecounts` as an alternative to option `showsize`. Added option `showsizeunits` to `gam gam <UserTypeEntity> print filelist|filecounts` as an alternative to option `showsize`.
* `showsize` - 31549200951 - This is a byte count * `showsize` - 31549200951 - This is a byte count
* `showsizeunits' - 31.55 GB - This is as shown in the Admin console * `showsizeunits` - 31.55 GB - This is as shown in the Admin console
7.35.01 7.35.01

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.35.02' __version__ = '7.35.03'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
# pylint: disable=wrong-import-position # pylint: disable=wrong-import-position
@@ -9505,31 +9505,31 @@ def getOSPlatform():
return f'{myos} {pltfrm}' return f'{myos} {pltfrm}'
def inspect_untrusted_cert(url): def inspect_untrusted_cert(url):
"""Bypasses validation momentarily to extract the untrusted Issuer.""" """Bypasses validation momentarily to extract the untrusted Issuer."""
parsed = urlparse(url if '://' in url else f'https://{url}') parsed = urlparse(url if '://' in url else f'https://{url}')
host = parsed.hostname host = parsed.hostname
port = parsed.port or 443 port = parsed.port or 443
# Create an unverified context purely for diagnostic extraction # Create an unverified context purely for diagnostic extraction
ctx = ssl.create_default_context() ctx = ssl.create_default_context()
ctx.check_hostname = False ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE ctx.verify_mode = ssl.CERT_NONE
try: try:
with socket.create_connection((host, port), timeout=5) as sock: with socket.create_connection((host, port), timeout=5) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock: with ctx.wrap_socket(sock, server_hostname=host) as ssock:
der_cert = ssock.getpeercert(binary_form=True) der_cert = ssock.getpeercert(binary_form=True)
cert = x509.load_der_x509_certificate(der_cert, default_backend()) cert = x509.load_der_x509_certificate(der_cert, default_backend())
issuer = cert.issuer.rfc4514_string() issuer = cert.issuer.rfc4514_string()
subject = cert.subject.rfc4514_string() subject = cert.subject.rfc4514_string()
try: try:
san_ext = cert.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME) san_ext = cert.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
# Loop through the list of SANs (DNS names, IP addresses, etc.) # Loop through the list of SANs (DNS names, IP addresses, etc.)
sans = [str(name.value) for name in san_ext.value] sans = [str(name.value) for name in san_ext.value]
san_str = ", ".join(sans) san_str = ", ".join(sans)
except x509.ExtensionNotFound: except x509.ExtensionNotFound:
san_str = "None" san_str = "None"
return f"Untrusted Issuer: {issuer}\n Server Subject: {subject}\n SANs: {san_str}" return f"Untrusted Issuer: {issuer}\n Server Subject: {subject}\n SANs: {san_str}"
except Exception as e: except Exception as e:
return f"Failed to retrieve diagnostic certificate: {e}" return f"Failed to retrieve diagnostic certificate: {e}"
# gam checkconnection # gam checkconnection
def doCheckConnection(): def doCheckConnection():
@@ -59020,7 +59020,7 @@ SIZE_FIELD_CHOICE_MAP = {
# [excludetrashed] # [excludetrashed]
# [maxfiles <Integer>] [nodataheaders <String>] # [maxfiles <Integer>] [nodataheaders <String>]
# [countsonly [summary none|only|plus] [summaryuser <String>] # [countsonly [summary none|only|plus] [summaryuser <String>]
# [showsource] [showsize|showsizeunits] [showmimetypesize]] # [showsource] [showsize] [showsizeunits] [showmimetypesize]]
# [countsrowfilter] # [countsrowfilter]
# [filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree] # [filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)] # [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
@@ -59047,7 +59047,7 @@ def printFileList(users):
if 'mimeType' not in DFF.fieldsList: if 'mimeType' not in DFF.fieldsList:
DFF.fieldsList.append('mimeType') DFF.fieldsList.append('mimeType')
skipObjects.discard(sizeField) skipObjects.discard(sizeField)
if showSize and sizeField not in DFF.fieldsList: if (showSize or showSizeUnits) and sizeField not in DFF.fieldsList:
DFF.fieldsList.append(sizeField) DFF.fieldsList.append(sizeField)
if (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None): if (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None):
_setSkipObjects(skipObjects, [sizeField], DFF.fieldsList) _setSkipObjects(skipObjects, [sizeField], DFF.fieldsList)
@@ -59244,7 +59244,9 @@ def printFileList(users):
row['Source'] = sourceId row['Source'] = sourceId
row['Name'] = sourceName row['Name'] = sourceName
if showSize: if showSize:
row['Size'] = sizeTotal if not showSizeUnits else formatFileSize(sizeTotal) row['Size'] = sizeTotal
if showSizeUnits:
row['SizeUnits'] = formatFileSize(sizeTotal)
if addCSVData: if addCSVData:
row.update(addCSVData) row.update(addCSVData)
for mimeType, mtinfo in sorted(mimeTypeInfo.items()): for mimeType, mtinfo in sorted(mimeTypeInfo.items()):
@@ -59334,24 +59336,12 @@ def printFileList(users):
summaryUser = getString(Cmd.OB_STRING) summaryUser = getString(Cmd.OB_STRING)
elif myarg == 'showsource': elif myarg == 'showsource':
showSource = True showSource = True
if countsOnly: elif myarg == 'showsize':
if not showSize:
csvPFco.SetTitles(['Owner', 'Source', 'Name', 'Total'])
else:
csvPFco.SetTitles(['Owner', 'Source', 'Name', 'Total', 'Size'])
csvPFco.SetSortAllTitles()
elif myarg in {'showsizeunits', 'showsize', 'showmimetypesize'}:
showSize = True showSize = True
if countsOnly: elif myarg == 'showsizeunits':
if not showSource: showSizeUnits = True
csvPFco.SetTitles(['Owner', 'Total', 'Size']) elif myarg == 'showmimetypesize':
else: showMimeTypeSize = showSize = True
csvPFco.SetTitles(['Owner', 'Source', 'Name', 'Total', 'Size'])
csvPFco.SetSortAllTitles()
if myarg == 'showsizeunits':
showSizeUnits = True
elif myarg == 'showmimetypesize':
showMimeTypeSize = True
elif myarg == 'sizefield': elif myarg == 'sizefield':
sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True) sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True)
elif myarg == 'delimiter': elif myarg == 'delimiter':
@@ -59382,6 +59372,15 @@ def printFileList(users):
continueOnInvalidQuery = getBoolean() continueOnInvalidQuery = getBoolean()
else: else:
FJQC.GetFormatJSONQuoteChar(myarg) FJQC.GetFormatJSONQuoteChar(myarg)
if countsOnly:
titles = ['Owner', 'Total'] if not showSource else ['Owner', 'Source', 'Name', 'Total']
if showSize:
titles.append('Size')
if showSizeUnits:
titles.append('SizeUnits')
csvPFco.SetTitles(titles)
csvPFco.SetSortAllTitles()
if not filepath and not fullpath: if not filepath and not fullpath:
showDepth = False showDepth = False
noSelect = noFileSelectFileIdEntity(fileIdEntity) noSelect = noFileSelectFileIdEntity(fileIdEntity)
@@ -59447,9 +59446,11 @@ def printFileList(users):
csvPF.AddJSONTitles(sorted(addCSVData.keys())) csvPF.AddJSONTitles(sorted(addCSVData.keys()))
else: else:
csvPFco.AddTitles(sorted(addCSVData.keys())) csvPFco.AddTitles(sorted(addCSVData.keys()))
csvPFco.MoveTitlesToEnd(['Total'])
if showSize: if showSize:
csvPFco.MoveTitlesToEnd(['Size']) csvPFco.MoveTitlesToEnd(['Size'])
csvPFco.MoveTitlesToEnd(['Total']) if showSizeUnits:
csvPFco.MoveTitlesToEnd(['SizeUnits'])
csvPFco.SetSortAllTitles() csvPFco.SetSortAllTitles()
if filepath and not countsOnly: if filepath and not countsOnly:
csvPF.AddTitles('paths') csvPF.AddTitles('paths')
@@ -60157,7 +60158,7 @@ def _updateLastModificationRow(row, lastModification):
# [filenamematchpattern <REMatchPattern>] # [filenamematchpattern <REMatchPattern>]
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] # <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
# [excludetrashed] (addcsvdata <FieldName> <String>)* # [excludetrashed] (addcsvdata <FieldName> <String>)*
# [showsize|showsizeunits] [showmimetypesize] # [showsize] [showsizeunits] [showmimetypesize]
# [showlastmodification] [pathdelimiter <Character>] # [showlastmodification] [pathdelimiter <Character>]
# (addcsvdata <FieldName> <String>)* # (addcsvdata <FieldName> <String>)*
# [summary none|only|plus] [summaryuser <String>] # [summary none|only|plus] [summaryuser <String>]
@@ -60172,14 +60173,14 @@ def _updateLastModificationRow(row, lastModification):
# [filenamematchpattern <REMatchPattern>] # [filenamematchpattern <REMatchPattern>]
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] # <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
# [excludetrashed] # [excludetrashed]
# [showsize|showsizeunits] [showmimetypesize] # [showsize] [showsizeunits] [showmimetypesize]
# [showlastmodification] [pathdelimiter <Character>] # [showlastmodification] [pathdelimiter <Character>]
# [summary none|only|plus] [summaryuser <String>] # [summary none|only|plus] [summaryuser <String>]
def printShowFileCounts(users): def printShowFileCounts(users):
def _setSelectionFields(): def _setSelectionFields():
if DLP.showOwnedBy is not None: if DLP.showOwnedBy is not None:
fieldsList.extend(OWNED_BY_ME_FIELDS_TITLES) fieldsList.extend(OWNED_BY_ME_FIELDS_TITLES)
if showSize or (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None): if (showSize or showSizeUnits) or (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None):
fieldsList.append(sizeField) fieldsList.append(sizeField)
if showLastModification: if showLastModification:
fieldsList.extend(['id,name,modifiedTime,lastModifyingUser(me, displayName, emailAddress),parents']) fieldsList.extend(['id,name,modifiedTime,lastModifyingUser(me, displayName, emailAddress),parents'])
@@ -60212,7 +60213,9 @@ def printShowFileCounts(users):
kvList = [Ent.USER, user] kvList = [Ent.USER, user]
dataList = [Ent.Choose(Ent.DRIVE_FILE_OR_FOLDER, countTotal), countTotal] dataList = [Ent.Choose(Ent.DRIVE_FILE_OR_FOLDER, countTotal), countTotal]
if showSize: if showSize:
dataList.extend([Ent.Singular(Ent.SIZE), sizeTotal if not showSizeUnits else formatFileSize(sizeTotal)]) dataList.extend(['Size', sizeTotal])
if showSizeUnits:
dataList.extend(['SizeUnits', formatFileSize(sizeTotal)])
if sharedDriveId: if sharedDriveId:
dataList.extend(['Item cap', f"{countTotal/SHARED_DRIVE_MAX_FILES_FOLDERS:.2%}"]) dataList.extend(['Item cap', f"{countTotal/SHARED_DRIVE_MAX_FILES_FOLDERS:.2%}"])
printEntityKVList(kvList, dataList, i, count) printEntityKVList(kvList, dataList, i, count)
@@ -60231,7 +60234,9 @@ def printShowFileCounts(users):
else: else:
row = {'User': user, 'Total': countTotal} row = {'User': user, 'Total': countTotal}
if showSize: if showSize:
row['Size'] = sizeTotal if not showSizeUnits else formatFileSize(sizeTotal) row['Size'] = sizeTotal
if showSizeUnits:
row['SizeUnits'] = formatFileSize(sizeTotal)
if showLastModification: if showLastModification:
_updateLastModificationRow(row, lastModification) _updateLastModificationRow(row, lastModification)
if addCSVData: if addCSVData:
@@ -60270,13 +60275,13 @@ def printShowFileCounts(users):
elif myarg == 'showsize': elif myarg == 'showsize':
showSize = True showSize = True
elif myarg == 'showsizeunits': elif myarg == 'showsizeunits':
showSizeUnits = showSize = True showSizeUnits = True
elif myarg == 'showmimetypesize':
showMimeTypeSize = showSize = True
elif myarg == 'sizefield': elif myarg == 'sizefield':
sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True) sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True)
elif myarg == 'showlastmodification': elif myarg == 'showlastmodification':
showLastModification = True showLastModification = True
elif myarg == 'showmimetypesize':
showMimeTypeSize = showSize = True
elif myarg == 'summary': elif myarg == 'summary':
summary = getChoice(FILECOUNT_SUMMARY_CHOICE_MAP, mapChoice=True) summary = getChoice(FILECOUNT_SUMMARY_CHOICE_MAP, mapChoice=True)
elif myarg == 'summaryuser': elif myarg == 'summaryuser':
@@ -60305,6 +60310,8 @@ def printShowFileCounts(users):
_setSelectionFields() _setSelectionFields()
if csvPF: if csvPF:
sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total'] sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total']
if showSizeUnits:
sortTitles.insert(sortTitles.index('Total')+1, 'SizeUnits')
if showSize: if showSize:
sortTitles.insert(sortTitles.index('Total')+1, 'Size') sortTitles.insert(sortTitles.index('Total')+1, 'Size')
if showLastModification: if showLastModification: