Updated code to validate both <RegularExpression> and <ReplacementString>
Some checks failed
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled

This commit is contained in:
Ross Scroggs
2025-04-01 12:49:03 -07:00
parent defac7d9a8
commit c81121df58
4 changed files with 31 additions and 22 deletions

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.05.19'
__version__ = '7.05.20'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -1723,6 +1723,16 @@ def getREPattern(flags=0):
return validateREPattern(patstr, flags)
missingArgumentExit(Cmd.OB_RE_PATTERN)
def getREPatternReplacement(flags=0):
pattern = getREPattern(flags)
replacement = getString(Cmd.OB_STRING, minLen=0)
try:
re.sub(pattern, replacement, '')
return (pattern, replacement)
except re.error as e:
Cmd.Backup()
usageErrorExit(f'{Cmd.OB_RE_REPLACEMENT} {Msg.ERROR}: {e}')
def getSheetEntity(allowBlankSheet):
if Cmd.ArgumentsRemaining():
sheet = Cmd.Current()
@@ -14521,7 +14531,7 @@ def _getTagReplacement(myarg, tagReplacements, allowSubs):
if myarg == 'replace':
trregex = None
elif myarg == 'replaceregex':
trregex = (getREPattern(re.IGNORECASE), getString(Cmd.OB_STRING, minLen=0))
trregex = getREPatternReplacement(re.IGNORECASE)
else:
return False
matchTag = getString(Cmd.OB_TAG)
@@ -14600,10 +14610,7 @@ def _getTagReplacement(myarg, tagReplacements, allowSubs):
if trregex is None:
tagReplacements['tags'][matchTag] = {'value': matchReplacement}
else:
try:
tagReplacements['tags'][matchTag] = {'value': re.sub(trregex[0], trregex[1], matchReplacement)}
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(trregex[1], str(e)))
tagReplacements['tags'][matchTag] = {'value': re.sub(trregex[0], trregex[1], matchReplacement)}
return True
def _getTagReplacementFieldValues(user, i, count, tagReplacements, results=None):
@@ -14688,10 +14695,7 @@ def _getTagReplacementFieldValues(user, i, count, tagReplacements, results=None)
tag['value'] = _substituteForUser(tag['template'], user, userName)
trregex = tag.get('trregex', None)
if trregex is not None:
try:
tag['value'] = re.sub(trregex[0], trregex[1], tag['value'])
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(trregex[1], str(e)))
tag['value'] = re.sub(trregex[0], trregex[1], tag['value'])
RTL_PATTERN = re.compile(r'(?s){RTL}.*?{/RTL}')
RT_PATTERN = re.compile(r'(?s){RT}.*?{/RT}')
@@ -38560,7 +38564,7 @@ def _getCalendarEventAttribute(myarg, body, parameters, function):
elif myarg == 'description':
body['description'] = getStringWithCRsNLs()
elif function == 'update' and myarg == 'replacedescription':
parameters['replaceDescription'].append((getREPattern(re.IGNORECASE), getString(Cmd.OB_STRING, minLen=0)))
parameters['replaceDescription'].append(getREPatternReplacement(re.IGNORECASE))
elif myarg == 'location':
body['location'] = getString(Cmd.OB_STRING, minLen=0)
elif myarg == 'source':
@@ -39109,10 +39113,7 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
if 'description' in updateFieldList and 'description' in event:
body['description'] = event['description']
for replacement in parameters['replaceDescription']:
try:
body['description'] = re.sub(replacement[0], replacement[1], body['description'])
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(replacement[1], str(e)))
body['description'] = re.sub(replacement[0], replacement[1], body['description'])
if 'attendees' in updateFieldList:
if not parameters['clearAttendees']:
if 'attendees' in event:
@@ -52835,7 +52836,7 @@ def getDriveFileAttribute(myarg, body, parameters, updateCmd):
elif myarg =='stripnameprefix':
parameters[DFA_STRIPNAMEPREFIX] = getString(Cmd.OB_STRING, minLen=0)
elif myarg == 'replacefilename':
parameters[DFA_REPLACEFILENAME].append((getREPattern(re.IGNORECASE), getString(Cmd.OB_STRING, minLen=0)))
parameters[DFA_REPLACEFILENAME].append(getREPatternReplacement(re.IGNORECASE))
elif myarg in {'convert', 'ocr'}:
deprecatedArgument(myarg)
stderrWarningMsg(Msg.USE_MIMETYPE_TO_SPECIFY_GOOGLE_FORMAT)
@@ -57380,10 +57381,7 @@ def writeReturnIdLink(returnIdLink, mimeType, result):
def processFilenameReplacements(name, replacements):
for replacement in replacements:
try:
name = re.sub(replacement[0], replacement[1], name)
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(replacement[1], str(e)))
name = re.sub(replacement[0], replacement[1], name)
return name
def addTimestampToFilename(parameters, body):
@@ -58395,7 +58393,7 @@ def getCopyMoveOptions(myarg, copyMoveOptions):
elif myarg =='stripnameprefix':
copyMoveOptions['stripNamePrefix'] = getString(Cmd.OB_STRING, minLen=0)
elif myarg == 'replacefilename':
copyMoveOptions['replaceFilename'].append((getREPattern(re.IGNORECASE), getString(Cmd.OB_STRING, minLen=0)))
copyMoveOptions['replaceFilename'].append(getREPatternReplacement(re.IGNORECASE))
elif myarg == 'showpermissionmessages':
copyMoveOptions['showPermissionMessages'] = getBoolean()
elif myarg == 'sendemailifrequired':

View File

@@ -991,6 +991,7 @@ class GamCLArgs():
OB_RESOURCE_ENTITY = 'ResourceEntity'
OB_RESOURCE_ID = 'ResourceID'
OB_RE_PATTERN = 'REPattern'
OB_RE_REPLACEMENT = 'REReplacement'
OB_ROLE_ASSIGNMENT_ID = 'RoleAssignmentID'
OB_ROLE_ITEM = 'RoleItem'
OB_ROLE_LIST = 'RoleList'

View File

@@ -465,7 +465,6 @@ REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE = 'reason only valid wi
REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create'
RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n'
REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because acknowledge_device_touch_requirement not specified.\nDeprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by your domain again.\nThis requires physical access to the device and is very time consuming to perform for each device.\nPlease add "acknowledge_device_touch_requirement" to the GAM command if you understand this and wish to proceed with the deprovision.\nPlease also be aware that deprovisioning can have an effect on your device license count.\nSee https://support.google.com/chrome/a/answer/3523633 for full details.'
REGEX_REPLACEMENT_ERROR = 'Regular expression replacement string "{0}" error: {1}'
REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>'
REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again'
REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}'