| 243 | #endif // XMLDATETIME_HAS_GETEPOCH |
| 244 | |
| 245 | bool parse_time(const XMLCh* in, time_t& value) |
| 246 | { |
| 247 | xercesc::XMLDateTime xdt(in); |
| 248 | try { |
| 249 | xdt.parseDateTime(); |
| 250 | } catch (const xercesc::XMLException& ex) { |
| 251 | if (security_debug.access_error) { |
| 252 | ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: " |
| 253 | "failed to parse date/time \"%C\": %C\n", |
| 254 | to_string(in).c_str(), to_string(ex).c_str())); |
| 255 | } |
| 256 | return false; |
| 257 | } |
| 258 | |
| 259 | #if XMLDATETIME_HAS_GETEPOCH |
| 260 | value = xdt.getEpoch(); |
| 261 | #else |
| 262 | /* |
| 263 | * Doesn't seem like older Xerces' actually have a way to get the information |
| 264 | * from XMLDateTime, so we have to do it ourselves. |
| 265 | * |
| 266 | * For this we'll follow https://www.w3.org/TR/xmlschema-2/#dateTime, which |
| 267 | * is basically the same as ISO8601. |
| 268 | * The exceptions are: |
| 269 | * - We won't accept a negative datetime (-0001 is the year 2BCE), since the |
| 270 | * standard library might not be able to handle such a far back and we're |
| 271 | * certainly not expecting it. |
| 272 | * - The Schema spec says that times without timezone info should be |
| 273 | * interpreted as "local", but seems it be intentionally vague as what that |
| 274 | * means. The DDS Security 1.1 spec explicitly says in 9.4.1.3.2.2 that it |
| 275 | * would be UTC. Xerces getEpoch values match up with this in the unit test |
| 276 | * for this code, so it's also interpreting them as UTC instead of |
| 277 | * something like the local system timezone. |
| 278 | * - Since we use time_t we will accept but ignore fractional seconds. |
| 279 | * NOTE: The security spec is missing fractional seconds in a format |
| 280 | * description in a comment in example XML. This comment has been copied |
| 281 | * into many permissions files sitting in OpenDDS. |
| 282 | */ |
| 283 | |
| 284 | const std::string str = to_string(in); |
| 285 | if (str[0] == '-') { |
| 286 | if (security_debug.access_error) { |
| 287 | ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: " |
| 288 | "date/time can't be negative: \"%C\"\n", |
| 289 | str.c_str())); |
| 290 | } |
| 291 | return false; |
| 292 | } |
| 293 | |
| 294 | /* |
| 295 | * After this the expected lexical format given by the Schema spec is: |
| 296 | * yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? ((('+' | '-') hh ':' mm) | 'Z')? |
| 297 | * or alternatively as the Security spec says, except with fractional seconds: |
| 298 | * CCYY-MM-DDThh:mm:ss[.fffff...][Z|(+|-)hh:mm] |
| 299 | * See unit tests for this code for examples |
| 300 | */ |
| 301 | std::tm dttm; |
| 302 | size_t pos = 0; |
nothing calls this directly
no test coverage detected