1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sal.hxx" 30 31 #include <string.h> 32 #include <stdlib.h> 33 34 #include <osl/mutex.hxx> 35 #include <rtl/random.h> 36 #include <rtl/uuid.h> 37 #include <rtl/digest.h> 38 39 #define SWAP_INT32_TO_NETWORK(x)\ 40 { sal_uInt32 y = x;\ 41 sal_uInt8 *p = (sal_uInt8 * )&(x); \ 42 p[0] = (sal_uInt8) ( ( y >> 24 ) & 0xff );\ 43 p[1] = (sal_uInt8) ( ( y >> 16 ) & 0xff );\ 44 p[2] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\ 45 p[3] = (sal_uInt8) ( ( y ) & 0xff);\ 46 } 47 #define SWAP_INT16_TO_NETWORK(x)\ 48 { sal_uInt16 y = x;\ 49 sal_uInt8 *p = (sal_uInt8 * )&(x); \ 50 p[0] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\ 51 p[1] = (sal_uInt8) ( ( y ) & 0xff);\ 52 } 53 54 #define SWAP_NETWORK_TO_INT16(x)\ 55 { sal_uInt16 y = x;\ 56 sal_uInt8 *p = (sal_uInt8 * )&(y);\ 57 x = ( ( ((sal_uInt16)p[0]) & 0xff) << 8 ) |\ 58 ( ( (sal_uInt16)p[1]) & 0xff);\ 59 } 60 #define SWAP_NETWORK_TO_INT32(x)\ 61 { sal_uInt32 y = x;\ 62 sal_uInt8 *p = (sal_uInt8 * )&(y); \ 63 x = ( ( ((sal_uInt32)p[0]) & 0xff) << 24 ) |\ 64 ( ( ((sal_uInt32)p[1]) & 0xff) << 16 ) |\ 65 ( ( ((sal_uInt32)p[2]) & 0xff) << 8 ) |\ 66 ( ( (sal_uInt32)p[3]) & 0xff);\ 67 } 68 69 typedef struct _UUID 70 { 71 sal_uInt32 time_low; 72 sal_uInt16 time_mid; 73 sal_uInt16 time_hi_and_version; 74 sal_uInt8 clock_seq_hi_and_reserved; 75 sal_uInt8 clock_seq_low; 76 sal_uInt8 node[6]; 77 } UUID; 78 79 static void write_v3( sal_uInt8 *pUuid ) 80 { 81 UUID uuid; 82 // copy to avoid alignment problems 83 memcpy( &uuid , pUuid , 16 ); 84 85 SWAP_NETWORK_TO_INT32( uuid.time_low ); 86 SWAP_NETWORK_TO_INT16( uuid.time_mid ); 87 SWAP_NETWORK_TO_INT16( uuid.time_hi_and_version ); 88 89 /* put in the variant and version bits */ 90 uuid.time_hi_and_version &= 0x0FFF; 91 uuid.time_hi_and_version |= (3 << 12); 92 uuid.clock_seq_hi_and_reserved &= 0x3F; 93 uuid.clock_seq_hi_and_reserved |= 0x80; 94 95 SWAP_INT32_TO_NETWORK( uuid.time_low ); 96 SWAP_INT16_TO_NETWORK( uuid.time_mid ); 97 SWAP_INT16_TO_NETWORK( uuid.time_hi_and_version ); 98 99 memcpy( pUuid , &uuid , 16 ); 100 } 101 102 103 extern "C" void SAL_CALL rtl_createUuid( sal_uInt8 *pTargetUUID , 104 const sal_uInt8 *, sal_Bool ) 105 { 106 { 107 osl::MutexGuard g(osl::Mutex::getGlobalMutex()); 108 static rtlRandomPool pool = NULL; 109 if (pool == NULL) { 110 pool = rtl_random_createPool(); 111 if (pool == NULL) { 112 abort(); 113 // only possible way to signal failure here (rtl_createUuid 114 // being part of a fixed C API) 115 } 116 } 117 if (rtl_random_getBytes(pool, pTargetUUID, 16) != rtl_Random_E_None) { 118 abort(); 119 // only possible way to signal failure here (rtl_createUuid 120 // being part of a fixed C API) 121 } 122 } 123 // See ITU-T Recommendation X.667: 124 pTargetUUID[6] &= 0x0F; 125 pTargetUUID[6] |= 0x40; 126 pTargetUUID[8] &= 0x3F; 127 pTargetUUID[8] |= 0x80; 128 } 129 130 131 extern "C" void SAL_CALL rtl_createNamedUuid( sal_uInt8 *pTargetUUID, 132 const sal_uInt8 *pNameSpaceUUID, 133 const rtl_String *pName ) 134 { 135 rtlDigest digest = rtl_digest_createMD5 (); 136 137 rtl_digest_updateMD5( digest, pNameSpaceUUID , 16 ); 138 rtl_digest_updateMD5( digest, pName->buffer , pName->length ); 139 140 rtl_digest_getMD5( digest, pTargetUUID , 16 ); 141 rtl_digest_destroyMD5 (digest); 142 143 write_v3(pTargetUUID); 144 } 145 146 147 148 extern "C" sal_Int32 SAL_CALL rtl_compareUuid( const sal_uInt8 *pUUID1 , const sal_uInt8 *pUUID2 ) 149 { 150 int i; 151 UUID u1; 152 UUID u2; 153 memcpy( &u1 , pUUID1 , 16 ); 154 memcpy( &u2 , pUUID2 , 16 ); 155 156 SWAP_NETWORK_TO_INT32( u1.time_low ); 157 SWAP_NETWORK_TO_INT16( u1.time_mid ); 158 SWAP_NETWORK_TO_INT16( u1.time_hi_and_version ); 159 160 SWAP_NETWORK_TO_INT32( u2.time_low ); 161 SWAP_NETWORK_TO_INT16( u2.time_mid ); 162 SWAP_NETWORK_TO_INT16( u2.time_hi_and_version ); 163 164 #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; 165 CHECK(u1.time_low, u2.time_low); 166 CHECK(u1.time_mid, u2.time_mid); 167 CHECK(u1.time_hi_and_version, u2.time_hi_and_version); 168 CHECK(u1.clock_seq_hi_and_reserved, u2.clock_seq_hi_and_reserved); 169 CHECK(u1.clock_seq_low, u2.clock_seq_low); 170 for (i = 0; i < 6; i++) 171 { 172 if (u1.node[i] < u2.node[i]) 173 return -1; 174 if (u1.node[i] > u2.node[i]) 175 return 1; 176 } 177 return 0; 178 179 } 180 181