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 : #include <string.h>
21 : #include <stdlib.h>
22 :
23 : #include <osl/mutex.hxx>
24 : #include <rtl/random.h>
25 : #include <rtl/uuid.h>
26 : #include <rtl/digest.h>
27 :
28 : #define SWAP_INT32_TO_NETWORK(x)\
29 : { sal_uInt32 y = x;\
30 : sal_uInt8 *p = (sal_uInt8 * )&(x); \
31 : p[0] = (sal_uInt8) ( ( y >> 24 ) & 0xff );\
32 : p[1] = (sal_uInt8) ( ( y >> 16 ) & 0xff );\
33 : p[2] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\
34 : p[3] = (sal_uInt8) ( ( y ) & 0xff);\
35 : }
36 : #define SWAP_INT16_TO_NETWORK(x)\
37 : { sal_uInt16 y = x;\
38 : sal_uInt8 *p = (sal_uInt8 * )&(x); \
39 : p[0] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\
40 : p[1] = (sal_uInt8) ( ( y ) & 0xff);\
41 : }
42 :
43 : #define SWAP_NETWORK_TO_INT16(x)\
44 : { sal_uInt16 y = x;\
45 : sal_uInt8 *p = (sal_uInt8 * )&(y);\
46 : x = ( ( ((sal_uInt16)p[0]) & 0xff) << 8 ) |\
47 : ( ( (sal_uInt16)p[1]) & 0xff);\
48 : }
49 : #define SWAP_NETWORK_TO_INT32(x)\
50 : { sal_uInt32 y = x;\
51 : sal_uInt8 *p = (sal_uInt8 * )&(y); \
52 : x = ( ( ((sal_uInt32)p[0]) & 0xff) << 24 ) |\
53 : ( ( ((sal_uInt32)p[1]) & 0xff) << 16 ) |\
54 : ( ( ((sal_uInt32)p[2]) & 0xff) << 8 ) |\
55 : ( ( (sal_uInt32)p[3]) & 0xff);\
56 : }
57 :
58 : struct UUID
59 : {
60 : sal_uInt32 time_low;
61 : sal_uInt16 time_mid;
62 : sal_uInt16 time_hi_and_version;
63 : sal_uInt8 clock_seq_hi_and_reserved;
64 : sal_uInt8 clock_seq_low;
65 : sal_uInt8 node[6];
66 : };
67 :
68 8 : static void write_v3( sal_uInt8 *pUuid )
69 : {
70 : UUID uuid;
71 : // copy to avoid alignment problems
72 8 : memcpy( &uuid , pUuid , 16 );
73 :
74 8 : SWAP_NETWORK_TO_INT32( uuid.time_low );
75 8 : SWAP_NETWORK_TO_INT16( uuid.time_mid );
76 8 : SWAP_NETWORK_TO_INT16( uuid.time_hi_and_version );
77 :
78 : /* put in the variant and version bits */
79 8 : uuid.time_hi_and_version &= 0x0FFF;
80 8 : uuid.time_hi_and_version |= (3 << 12);
81 8 : uuid.clock_seq_hi_and_reserved &= 0x3F;
82 8 : uuid.clock_seq_hi_and_reserved |= 0x80;
83 :
84 8 : SWAP_INT32_TO_NETWORK( uuid.time_low );
85 8 : SWAP_INT16_TO_NETWORK( uuid.time_mid );
86 8 : SWAP_INT16_TO_NETWORK( uuid.time_hi_and_version );
87 :
88 8 : memcpy( pUuid , &uuid , 16 );
89 8 : }
90 :
91 4651 : extern "C" void SAL_CALL rtl_createUuid( sal_uInt8 *pTargetUUID ,
92 : SAL_UNUSED_PARAMETER const sal_uInt8 *,
93 : SAL_UNUSED_PARAMETER sal_Bool )
94 : {
95 : {
96 4651 : osl::MutexGuard g(osl::Mutex::getGlobalMutex());
97 : static rtlRandomPool pool = NULL;
98 4651 : if (pool == NULL) {
99 321 : pool = rtl_random_createPool();
100 321 : if (pool == NULL) {
101 0 : abort();
102 : // only possible way to signal failure here (rtl_createUuid
103 : // being part of a fixed C API)
104 : }
105 : }
106 4651 : if (rtl_random_getBytes(pool, pTargetUUID, 16) != rtl_Random_E_None) {
107 0 : abort();
108 : // only possible way to signal failure here (rtl_createUuid
109 : // being part of a fixed C API)
110 4651 : }
111 : }
112 : // See ITU-T Recommendation X.667:
113 4651 : pTargetUUID[6] &= 0x0F;
114 4651 : pTargetUUID[6] |= 0x40;
115 4651 : pTargetUUID[8] &= 0x3F;
116 4651 : pTargetUUID[8] |= 0x80;
117 4651 : }
118 :
119 8 : extern "C" void SAL_CALL rtl_createNamedUuid( sal_uInt8 *pTargetUUID,
120 : const sal_uInt8 *pNameSpaceUUID,
121 : const rtl_String *pName )
122 : {
123 8 : rtlDigest digest = rtl_digest_createMD5 ();
124 :
125 8 : rtl_digest_updateMD5( digest, pNameSpaceUUID , 16 );
126 8 : rtl_digest_updateMD5( digest, pName->buffer , pName->length );
127 :
128 8 : rtl_digest_getMD5( digest, pTargetUUID , 16 );
129 8 : rtl_digest_destroyMD5 (digest);
130 :
131 8 : write_v3(pTargetUUID);
132 8 : }
133 :
134 388 : extern "C" sal_Int32 SAL_CALL rtl_compareUuid( const sal_uInt8 *pUUID1 , const sal_uInt8 *pUUID2 )
135 : {
136 : int i;
137 : UUID u1;
138 : UUID u2;
139 388 : memcpy( &u1 , pUUID1 , 16 );
140 388 : memcpy( &u2 , pUUID2 , 16 );
141 :
142 388 : SWAP_NETWORK_TO_INT32( u1.time_low );
143 388 : SWAP_NETWORK_TO_INT16( u1.time_mid );
144 388 : SWAP_NETWORK_TO_INT16( u1.time_hi_and_version );
145 :
146 388 : SWAP_NETWORK_TO_INT32( u2.time_low );
147 388 : SWAP_NETWORK_TO_INT16( u2.time_mid );
148 388 : SWAP_NETWORK_TO_INT16( u2.time_hi_and_version );
149 :
150 : #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
151 388 : CHECK(u1.time_low, u2.time_low);
152 2 : CHECK(u1.time_mid, u2.time_mid);
153 2 : CHECK(u1.time_hi_and_version, u2.time_hi_and_version);
154 2 : CHECK(u1.clock_seq_hi_and_reserved, u2.clock_seq_hi_and_reserved);
155 2 : CHECK(u1.clock_seq_low, u2.clock_seq_low);
156 14 : for (i = 0; i < 6; i++)
157 : {
158 12 : if (u1.node[i] < u2.node[i])
159 0 : return -1;
160 12 : if (u1.node[i] > u2.node[i])
161 0 : return 1;
162 : }
163 2 : return 0;
164 :
165 : }
166 :
167 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|