Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <string.h>
22 : #include <stdlib.h>
23 :
24 : #include <osl/mutex.hxx>
25 : #include <rtl/random.h>
26 : #include <rtl/uuid.h>
27 : #include <rtl/digest.h>
28 :
29 : #define SWAP_INT32_TO_NETWORK(x)\
30 : { sal_uInt32 y = x;\
31 : sal_uInt8 *p = (sal_uInt8 * )&(x); \
32 : p[0] = (sal_uInt8) ( ( y >> 24 ) & 0xff );\
33 : p[1] = (sal_uInt8) ( ( y >> 16 ) & 0xff );\
34 : p[2] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\
35 : p[3] = (sal_uInt8) ( ( y ) & 0xff);\
36 : }
37 : #define SWAP_INT16_TO_NETWORK(x)\
38 : { sal_uInt16 y = x;\
39 : sal_uInt8 *p = (sal_uInt8 * )&(x); \
40 : p[0] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\
41 : p[1] = (sal_uInt8) ( ( y ) & 0xff);\
42 : }
43 :
44 : #define SWAP_NETWORK_TO_INT16(x)\
45 : { sal_uInt16 y = x;\
46 : sal_uInt8 *p = (sal_uInt8 * )&(y);\
47 : x = ( ( ((sal_uInt16)p[0]) & 0xff) << 8 ) |\
48 : ( ( (sal_uInt16)p[1]) & 0xff);\
49 : }
50 : #define SWAP_NETWORK_TO_INT32(x)\
51 : { sal_uInt32 y = x;\
52 : sal_uInt8 *p = (sal_uInt8 * )&(y); \
53 : x = ( ( ((sal_uInt32)p[0]) & 0xff) << 24 ) |\
54 : ( ( ((sal_uInt32)p[1]) & 0xff) << 16 ) |\
55 : ( ( ((sal_uInt32)p[2]) & 0xff) << 8 ) |\
56 : ( ( (sal_uInt32)p[3]) & 0xff);\
57 : }
58 :
59 : struct UUID
60 : {
61 : sal_uInt32 time_low;
62 : sal_uInt16 time_mid;
63 : sal_uInt16 time_hi_and_version;
64 : sal_uInt8 clock_seq_hi_and_reserved;
65 : sal_uInt8 clock_seq_low;
66 : sal_uInt8 node[6];
67 : };
68 :
69 4 : static void write_v3( sal_uInt8 *pUuid )
70 : {
71 : UUID uuid;
72 : // copy to avoid alignment problems
73 4 : memcpy( &uuid , pUuid , 16 );
74 :
75 4 : SWAP_NETWORK_TO_INT32( uuid.time_low );
76 4 : SWAP_NETWORK_TO_INT16( uuid.time_mid );
77 4 : SWAP_NETWORK_TO_INT16( uuid.time_hi_and_version );
78 :
79 : /* put in the variant and version bits */
80 4 : uuid.time_hi_and_version &= 0x0FFF;
81 4 : uuid.time_hi_and_version |= (3 << 12);
82 4 : uuid.clock_seq_hi_and_reserved &= 0x3F;
83 4 : uuid.clock_seq_hi_and_reserved |= 0x80;
84 :
85 4 : SWAP_INT32_TO_NETWORK( uuid.time_low );
86 4 : SWAP_INT16_TO_NETWORK( uuid.time_mid );
87 4 : SWAP_INT16_TO_NETWORK( uuid.time_hi_and_version );
88 :
89 4 : memcpy( pUuid , &uuid , 16 );
90 4 : }
91 :
92 :
93 1999 : extern "C" void SAL_CALL rtl_createUuid( sal_uInt8 *pTargetUUID ,
94 : SAL_UNUSED_PARAMETER const sal_uInt8 *,
95 : SAL_UNUSED_PARAMETER sal_Bool )
96 : {
97 : {
98 1999 : osl::MutexGuard g(osl::Mutex::getGlobalMutex());
99 : static rtlRandomPool pool = NULL;
100 1999 : if (pool == NULL) {
101 138 : pool = rtl_random_createPool();
102 138 : if (pool == NULL) {
103 0 : abort();
104 : // only possible way to signal failure here (rtl_createUuid
105 : // being part of a fixed C API)
106 : }
107 : }
108 1999 : if (rtl_random_getBytes(pool, pTargetUUID, 16) != rtl_Random_E_None) {
109 0 : abort();
110 : // only possible way to signal failure here (rtl_createUuid
111 : // being part of a fixed C API)
112 1999 : }
113 : }
114 : // See ITU-T Recommendation X.667:
115 1999 : pTargetUUID[6] &= 0x0F;
116 1999 : pTargetUUID[6] |= 0x40;
117 1999 : pTargetUUID[8] &= 0x3F;
118 1999 : pTargetUUID[8] |= 0x80;
119 1999 : }
120 :
121 :
122 4 : extern "C" void SAL_CALL rtl_createNamedUuid( sal_uInt8 *pTargetUUID,
123 : const sal_uInt8 *pNameSpaceUUID,
124 : const rtl_String *pName )
125 : {
126 4 : rtlDigest digest = rtl_digest_createMD5 ();
127 :
128 4 : rtl_digest_updateMD5( digest, pNameSpaceUUID , 16 );
129 4 : rtl_digest_updateMD5( digest, pName->buffer , pName->length );
130 :
131 4 : rtl_digest_getMD5( digest, pTargetUUID , 16 );
132 4 : rtl_digest_destroyMD5 (digest);
133 :
134 4 : write_v3(pTargetUUID);
135 4 : }
136 :
137 :
138 :
139 194 : extern "C" sal_Int32 SAL_CALL rtl_compareUuid( const sal_uInt8 *pUUID1 , const sal_uInt8 *pUUID2 )
140 : {
141 : int i;
142 : UUID u1;
143 : UUID u2;
144 194 : memcpy( &u1 , pUUID1 , 16 );
145 194 : memcpy( &u2 , pUUID2 , 16 );
146 :
147 194 : SWAP_NETWORK_TO_INT32( u1.time_low );
148 194 : SWAP_NETWORK_TO_INT16( u1.time_mid );
149 194 : SWAP_NETWORK_TO_INT16( u1.time_hi_and_version );
150 :
151 194 : SWAP_NETWORK_TO_INT32( u2.time_low );
152 194 : SWAP_NETWORK_TO_INT16( u2.time_mid );
153 194 : SWAP_NETWORK_TO_INT16( u2.time_hi_and_version );
154 :
155 : #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
156 194 : CHECK(u1.time_low, u2.time_low);
157 1 : CHECK(u1.time_mid, u2.time_mid);
158 1 : CHECK(u1.time_hi_and_version, u2.time_hi_and_version);
159 1 : CHECK(u1.clock_seq_hi_and_reserved, u2.clock_seq_hi_and_reserved);
160 1 : CHECK(u1.clock_seq_low, u2.clock_seq_low);
161 7 : for (i = 0; i < 6; i++)
162 : {
163 6 : if (u1.node[i] < u2.node[i])
164 0 : return -1;
165 6 : if (u1.node[i] > u2.node[i])
166 0 : return 1;
167 : }
168 1 : return 0;
169 :
170 : }
171 :
172 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|