protected void checkValue(String value, Map attrsToModify) throws ServiceException { // means to delete/unset the attribute if (value == null || value.equals("")) return; switch (mType) { case TYPE_BOOLEAN: if ("TRUE".equals(value) || "FALSE".equals(value)) return; else throw AccountServiceException.INVALID_ATTR_VALUE(mName + " must be TRUE or FALSE", null); case TYPE_BINARY: case TYPE_CERTIFICATE: byte[] binary = ByteUtil.decodeLDAPBase64(value); if (binary.length > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value length(" + binary.length + ") larger than max allowed: " + mMax, null); return; case TYPE_DURATION: if (!DURATION_PATTERN.matcher(value).matches()) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " " + DURATION_PATTERN_DOC, null); long l = DateUtil.getTimeInterval(value, 0); if (l < mMin) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " is shorter than minimum allowed: " + mMinDuration, null); if (l > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " is longer than max allowed: " + mMaxDuration, null); return; case TYPE_EMAIL: if (value.length() > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value length(" + value.length() + ") larger than max allowed: " + mMax, null); validEmailAddress(value, false); return; case TYPE_EMAILP: if (value.length() > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value length(" + value.length() + ") larger than max allowed: " + mMax, null); validEmailAddress(value, true); return; case TYPE_CS_EMAILP: if (value.length() > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value length(" + value.length() + ") larger than max allowed: " + mMax, null); String[] emails = value.split(","); for (String email : emails) validEmailAddress(email, true); return; case TYPE_ENUM: if (mEnumSet.contains(value)) return; else throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must be one of: " + mValue, null); case TYPE_GENTIME: if (GENTIME_PATTERN.matcher(value).matches()) return; else throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must be a valid generalized time: yyyyMMddHHmmssZ", null); case TYPE_ID: // For bug 21776 we check format for id only if the Provisioning class mandates // that all attributes of type id must be an UUID. // if (!Provisioning.getInstance().idIsUUID()) return; if (ID_PATTERN.matcher(value).matches()) return; else throw AccountServiceException.INVALID_ATTR_VALUE(mName + " must be a valid id", null); case TYPE_INTEGER: try { int v = Integer.parseInt(value); if (v < mMin) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value(" + v + ") smaller than minimum allowed: " + mMin, null); if (v > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value(" + v + ") larger than max allowed: " + mMax, null); return; } catch (NumberFormatException e) { throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must be a valid integer: " + value, e); } case TYPE_LONG: try { long v = Long.parseLong(value); if (v < mMin) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value(" + v + ") smaller than minimum allowed: " + mMin, null); if (v > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value(" + v + ") larger than max allowed: " + mMax, null); return; } catch (NumberFormatException e) { throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must be a valid long: " + value, e); } case TYPE_PORT: try { int v = Integer.parseInt(value); if (v >= 0 && v <= 65535) return; throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must be a valid port: " + value, null); } catch (NumberFormatException e) { throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must be a valid port: " + value, null); } case TYPE_STRING: case TYPE_ASTRING: case TYPE_OSTRING: case TYPE_CSTRING: case TYPE_PHONE: if (value.length() > mMax) throw AccountServiceException.INVALID_ATTR_VALUE( mName + " value length(" + value.length() + ") larger than max allowed: " + mMax, null); // TODO return; case TYPE_REGEX: if (mRegex.matcher(value).matches()) return; else throw AccountServiceException.INVALID_ATTR_VALUE( mName + " must match the regex: " + mValue, null); default: ZimbraLog.misc.warn("unknown type(" + mType + ") for attribute: " + value); return; } }
protected AttributeInfo( String attrName, int id, String parentId, int groupId, AttributeCallback callback, AttributeType type, AttributeOrder order, String value, boolean immutable, String min, String max, AttributeCardinality cardinality, Set<AttributeClass> requiredIn, Set<AttributeClass> optionalIn, Set<AttributeFlag> flags, List<String> globalConfigValues, List<String> defaultCOSValues, List<String> defaultExternalCOSValues, List<String> globalConfigValuesUpgrade, List<String> defaultCOSValuesUpgrade, String description, List<AttributeServerType> requiresRestart, Version since, Version deprecatedSince) { mName = attrName; mImmutable = immutable; mCallback = callback; mType = type; mOrder = order; mValue = value; mId = id; mParentOid = parentId; mGroupId = groupId; mCardinality = cardinality; mRequiredInClasses = requiredIn; mOptionalInClasses = optionalIn; mFlags = flags; mGlobalConfigValues = globalConfigValues; mGlobalConfigValuesUpgrade = globalConfigValuesUpgrade; mDefaultCOSValues = defaultCOSValues; mDefaultExternalCOSValues = defaultExternalCOSValues; mDefaultCOSValuesUpgrade = defaultCOSValuesUpgrade; mDescription = description; mRequiresRestart = requiresRestart; mSince = since; mDeprecatedSince = deprecatedSince; mMin = parseLong(attrName, AttributeManager.A_MIN, min, Long.MIN_VALUE); mMax = parseLong(attrName, AttributeManager.A_MAX, max, Long.MAX_VALUE); switch (mType) { case TYPE_INTEGER: mMin = Integer.MIN_VALUE; mMax = Integer.MAX_VALUE; if (!StringUtil.isNullOrEmpty(min)) { Integer i = parseInt(min); if (i == null) { ZimbraLog.misc.warn( "Invalid value '%s' for property %s of attribute %s. Defaulting to %d.", min, AttributeManager.A_MIN, attrName, mMin); } else { mMin = i; } } if (!StringUtil.isNullOrEmpty(max)) { Integer i = parseInt(max); if (i == null) { ZimbraLog.misc.warn( "Invalid value '%s' for property %s of attribute %s. Defaulting to %d.", max, AttributeManager.A_MAX, attrName, mMax); } else { mMax = i; } } break; case TYPE_LONG: mMin = Long.MIN_VALUE; mMax = Long.MAX_VALUE; if (!StringUtil.isNullOrEmpty(min)) { Long l = parseLong(min); if (l == null) { ZimbraLog.misc.warn( "Invalid value '%s' for property %s of attribute %s. Defaulting to %d.", min, AttributeManager.A_MIN, attrName, mMin); } else { mMin = l; } } if (!StringUtil.isNullOrEmpty(max)) { Long l = parseLong(max); if (l == null) { ZimbraLog.misc.warn( "Invalid value '%s' for property %s of attribute %s. Defaulting to %d.", max, AttributeManager.A_MAX, attrName, mMax); } else { mMax = l; } } break; case TYPE_ENUM: String enums[] = value.split(","); mEnumSet = new HashSet<String>(enums.length); for (int i = 0; i < enums.length; i++) { mEnumSet.add(enums[i]); } break; case TYPE_REGEX: mRegex = Pattern.compile(value); break; case TYPE_DURATION: mMin = 0; mMax = Long.MAX_VALUE; mMinDuration = "0"; mMaxDuration = Long.toString(mMax); if (!StringUtil.isNullOrEmpty(min)) { mMin = DateUtil.getTimeInterval(min, -1); if (mMin < 0) { mMin = 0; ZimbraLog.misc.warn( "Invalid value '%s' for property %s of attribute %s. Defaulting to 0.", min, AttributeManager.A_MIN, attrName); } else { mMinDuration = min; } } if (!StringUtil.isNullOrEmpty(max)) { mMax = DateUtil.getTimeInterval(max, -1); if (mMax < 0) { mMax = Long.MAX_VALUE; ZimbraLog.misc.warn( "Invalid value '%s' for property %s of attribute %s. Defaulting to %d.", max, AttributeManager.A_MAX, attrName, mMax); } else { mMaxDuration = max; } } break; } }