📄 cimobjectpath.cpp
字号:
class CIMObjectPathRep{public: CIMObjectPathRep() { } CIMObjectPathRep(const CIMObjectPathRep& x) : _host(x._host), _nameSpace(x._nameSpace), _className(x._className), _keyBindings(x._keyBindings) { } CIMObjectPathRep( const String& host, const CIMNamespaceName& nameSpace, const CIMName& className, const Array<CIMKeyBinding>& keyBindings) : _host(host), _nameSpace(nameSpace), _className(className), _keyBindings(keyBindings) { } ~CIMObjectPathRep() { } CIMObjectPathRep& operator=(const CIMObjectPathRep& x) { if (&x != this) { _host = x._host; _nameSpace = x._nameSpace; _className = x._className; _keyBindings = x._keyBindings; } return *this; } static Boolean isValidHostname(const String& hostname) { //------------------------------------------------------------------ // Validate the hostname. The hostname value may or may not be a // fully-qualified domain name (e.g., xyz.company.com) or may be an // IP address. A port number may follow the hostname. // Hostnames must match one of the following regular expressions: // ^([A-Za-z0-9][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*(:[0-9]*)?$ // ^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)(:[0-9]*)?$ // Note for Bug#1462. Be careful here, from RFC 1123: // - The syntax of a legal Internet host name was specified in // RFC-952 [DNS:4]. One aspect of host name syntax is hereby // changed: the restriction on the first character is relaxed to // allow either a letter or a digit. // - If a dotted-decimal number can be entered without identifying // delimiters, then a full syntactic check must be made, because // a segment of a host domain name is now allowed to begin with a // digit and could legally be entirely numeric (see Section 6.1.2.4). // However, a valid host name can never have the dotted-decimal form // #.#.#.#, since at least the highest-level component label will be // alphabetic. // The algorithm below has been updated accordingly. //------------------------------------------------------------------ Uint32 i = 0; Boolean isValid = false; if (isascii(hostname[0]) && isdigit(hostname[0])) { //-------------------------------------------------------------- // Attempt to validate an IP address, but keep in mind that it // might be a host name, since the leading character can now be // a digit. //-------------------------------------------------------------- isValid = true; for (Uint32 octet=1; octet<=4; octet++) { Uint32 octetValue = 0; //---------------------------------------------------------- // If a non-digit is encountered in the input parameter, // then break from here and attempt to validate as host name. //---------------------------------------------------------- if (!(isascii(hostname[i]) && isdigit(hostname[i]))) { isValid = false; break; } // skip over digits while (isascii(hostname[i]) && isdigit(hostname[i])) { octetValue = octetValue*10 + (hostname[i] - '0'); i++; } if (octetValue > 255) { isValid = false; break; } // Check for invalid character in IP address if ((octet != 4) && (hostname[i++] != '.')) { isValid = false; break; } // Check for the case where it's a valid host name that happens // to have 4 (or more) leading all-numeric host segments. if ((octet == 4) && (hostname[i] != ':') && hostname[i] != char(0)) { isValid = false; break; } } } if (!isValid) // if it is not a valid IP address { i = 0; // reset index for host name check // Validate a host name isValid = true; Boolean expectHostSegment = true; Boolean hostSegmentIsNumeric; while (expectHostSegment == true) { expectHostSegment = false; hostSegmentIsNumeric = true; // assume all-numeric host segment if (!(isascii(hostname[i]) && (isalnum(hostname[i]) || (hostname[i] == '_')))) { return false; } while (isascii(hostname[i]) && (isalnum(hostname[i]) || (hostname[i] == '-') || (hostname[i] == '_'))) { // If a non-digit is encountered, set "all-numeric" // flag to false if (isalpha(hostname[i]) || (hostname[i] == '-') || (hostname[i] == '_')) { hostSegmentIsNumeric = false; } i++; } if (hostname[i] == '.') { i++; expectHostSegment = true; } } // If the last Host Segment is all numeric, then return false. // RFC 1123 says "highest-level component label will be alphabetic". if (hostSegmentIsNumeric) { return false; } } if (!isValid) // if not a valid IP address or host name { return false; } // Check for a port number: if (hostname[i] == ':') { i++; if (!(isascii(hostname[i]) && isdigit(hostname[i]))) { return false; } i++; while (isascii(hostname[i]) && isdigit(hostname[i])) { i++; } } return (hostname[i] == char(0)); } // // Contains port as well (e.g., myhost:1234). // String _host; CIMNamespaceName _nameSpace; CIMName _className; Array<CIMKeyBinding> _keyBindings;};CIMObjectPath::CIMObjectPath(){ _rep = new CIMObjectPathRep();}CIMObjectPath::CIMObjectPath(const CIMObjectPath& x){ _rep = new CIMObjectPathRep(*x._rep);}CIMObjectPath::CIMObjectPath(const String& objectName){ // Test the objectName out to see if we get an exception CIMObjectPath tmpRef; tmpRef.set(objectName); _rep = new CIMObjectPathRep(*tmpRef._rep);}CIMObjectPath::CIMObjectPath( const String& host, const CIMNamespaceName& nameSpace, const CIMName& className, const Array<CIMKeyBinding>& keyBindings){ // Test the objectName out to see if we get an exception CIMObjectPath tmpRef; tmpRef.set(host, nameSpace, className, keyBindings); _rep = new CIMObjectPathRep(*tmpRef._rep);}CIMObjectPath::~CIMObjectPath(){ delete _rep;}CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x){ *_rep = *x._rep; return *this;}void CIMObjectPath::clear(){ _rep->_host.clear(); _rep->_nameSpace.clear(); _rep->_className.clear(); _rep->_keyBindings.clear();}void CIMObjectPath::set( const String& host, const CIMNamespaceName& nameSpace, const CIMName& className, const Array<CIMKeyBinding>& keyBindings){ setHost(host); setNameSpace(nameSpace); setClassName(className); setKeyBindings(keyBindings);}Boolean _parseHostElement( const String& objectName, char*& p, String& host){ // See if there is a host name (true if it begins with "//"): // Host is of the form <hostname>:<port> and begins with "//" // and ends with "/": if (p[0] != '/' || p[1] != '/') { return false; } p += 2; char* slash = strchr(p, '/'); if (!slash) { throw MalformedObjectNameException(objectName); } String hostname = String(p, (Uint32)(slash - p)); if (!CIMObjectPathRep::isValidHostname(hostname)) { throw MalformedObjectNameException(objectName); } host = hostname; // Do not step past the '/'; it will be consumed by the namespace parser p = slash; return true;}Boolean _parseNamespaceElement( const String& objectName, char*& p, CIMNamespaceName& nameSpace){ // If we don't find a valid namespace name followed by a ':', we // assume we're not looking at a namespace name. char* colon = strchr(p, ':'); if (!colon) { return false; } // A ':' as part of a keybinding value should not be interpreted as // a namespace delimiter. Since keybinding pairs follow the first '.' // in the object path string, the ':' delimiter only counts if it // appears before the '.'. char* dot = strchr(p, '.'); if (dot && (dot < colon)) { return false; } //---------------------------------------------------------------------- // Validate the namespace path. Namespaces must match the following // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*" //---------------------------------------------------------------------- String namespaceName = String(p, (Uint32)(colon - p)); if (!CIMNamespaceName::legal(namespaceName)) { throw MalformedObjectNameException(objectName); } nameSpace = namespaceName; p = colon+1; return true;}/** ATTN-RK: The DMTF specification for the string form of an object path makes it impossible for a parser to distinguish between a key values of String type and Reference type. Given the ambiguity, this implementation takes a guess at the type of a quoted key value. If the value can be parsed into a CIMObjectPath with at least one key binding, the type is set to REFERENCE. Otherwise, the type is set to STRING. Note: This algorithm appears to be in line with what the Sun WBEM Services implementation does. To be totally correct, it would be necessary to retrieve the class definition and look up the types of the key properties to determine how to interpret the key values. This is clearly too inefficient for internal transformations between CIMObjectPaths and String values.*/void _parseKeyBindingPairs( const String& objectName, char*& p, Array<CIMKeyBinding>& keyBindings){ // Get the key-value pairs: while (*p) { // Get key part: char* equalsign = strchr(p, '='); if (!equalsign) { throw MalformedObjectNameException(objectName); } *equalsign = 0; if (!CIMName::legal(p)) throw MalformedObjectNameException(objectName); CIMName keyName (p); // Get the value part: String valueString; p = equalsign + 1; CIMKeyBinding::Type type; if (*p == '"') { // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE p++; while (*p && *p != '"') { if (*p == '\\') { *p++; if ((*p != '\\') && (*p != '"')) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -