1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>      /* for sprintf */
18
19#include "apr.h"
20#include "apr_uuid.h"
21#include "apr_errno.h"
22#include "apr_lib.h"
23
24
25APU_DECLARE(void) apr_uuid_format(char *buffer, const apr_uuid_t *uuid)
26{
27    const unsigned char *d = uuid->data;
28
29    sprintf(buffer,
30            "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
31            d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
32            d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
33}
34
35/* convert a pair of hex digits to an integer value [0,255] */
36#if 'A' == 65
37static unsigned char parse_hexpair(const char *s)
38{
39    int result;
40    int temp;
41
42    result = s[0] - '0';
43    if (result > 48)
44	result = (result - 39) << 4;
45    else if (result > 16)
46	result = (result - 7) << 4;
47    else
48	result = result << 4;
49
50    temp = s[1] - '0';
51    if (temp > 48)
52	result |= temp - 39;
53    else if (temp > 16)
54	result |= temp - 7;
55    else
56	result |= temp;
57
58    return (unsigned char)result;
59}
60#else
61static unsigned char parse_hexpair(const char *s)
62{
63    int result;
64
65    if (isdigit(*s)) {
66        result = (*s - '0') << 4;
67    }
68    else {
69        if (isupper(*s)) {
70            result = (*s - 'A' + 10) << 4;
71        }
72        else {
73            result = (*s - 'a' + 10) << 4;
74        }
75    }
76
77    ++s;
78    if (isdigit(*s)) {
79        result |= (*s - '0');
80    }
81    else {
82        if (isupper(*s)) {
83            result |= (*s - 'A' + 10);
84        }
85        else {
86            result |= (*s - 'a' + 10);
87        }
88    }
89
90    return (unsigned char)result;
91}
92#endif
93
94APU_DECLARE(apr_status_t) apr_uuid_parse(apr_uuid_t *uuid,
95                                         const char *uuid_str)
96{
97    int i;
98    unsigned char *d = uuid->data;
99
100    for (i = 0; i < 36; ++i) {
101	char c = uuid_str[i];
102	if (!apr_isxdigit(c) &&
103	    !(c == '-' && (i == 8 || i == 13 || i == 18 || i == 23)))
104            /* ### need a better value */
105	    return APR_BADARG;
106    }
107    if (uuid_str[36] != '\0') {
108        /* ### need a better value */
109	return APR_BADARG;
110    }
111
112    d[0] = parse_hexpair(&uuid_str[0]);
113    d[1] = parse_hexpair(&uuid_str[2]);
114    d[2] = parse_hexpair(&uuid_str[4]);
115    d[3] = parse_hexpair(&uuid_str[6]);
116
117    d[4] = parse_hexpair(&uuid_str[9]);
118    d[5] = parse_hexpair(&uuid_str[11]);
119
120    d[6] = parse_hexpair(&uuid_str[14]);
121    d[7] = parse_hexpair(&uuid_str[16]);
122
123    d[8] = parse_hexpair(&uuid_str[19]);
124    d[9] = parse_hexpair(&uuid_str[21]);
125
126    for (i = 6; i--;)
127	d[10 + i] = parse_hexpair(&uuid_str[i*2+24]);
128
129    return APR_SUCCESS;
130}
131