dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2006 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License version 2 as published by the Free Software Foundation. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This file contains code used to convert user-supplied object names into dbda8d6ce9 2007-07-21 drh: ** canonical UUIDs. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** A user-supplied object name is any unique prefix of a valid UUID but dbda8d6ce9 2007-07-21 drh: ** not necessarily in canonical form. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "name.h" dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** This routine takes a user-entered UUID which might be in mixed dbda8d6ce9 2007-07-21 drh: ** case and might only be a prefix of the full UUID and converts it dbda8d6ce9 2007-07-21 drh: ** into the full-length UUID in canonical form. dbda8d6ce9 2007-07-21 drh: ** 3b5514ed82 2007-09-22 drh: ** If the input is not a UUID or a UUID prefix, then try to resolve 3b5514ed82 2007-09-22 drh: ** the name as a tag. 3b5514ed82 2007-09-22 drh: ** dbda8d6ce9 2007-07-21 drh: ** Return the number of errors. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int name_to_uuid(Blob *pName, int iErrPriority){ dbda8d6ce9 2007-07-21 drh: int rc; dbda8d6ce9 2007-07-21 drh: int sz; dbda8d6ce9 2007-07-21 drh: sz = blob_size(pName); dbda8d6ce9 2007-07-21 drh: if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){ 3b5514ed82 2007-09-22 drh: Stmt q; 3b5514ed82 2007-09-22 drh: Blob uuid; 3b5514ed82 2007-09-22 drh: 3b5514ed82 2007-09-22 drh: db_prepare(&q, 3b5514ed82 2007-09-22 drh: "SELECT (SELECT uuid FROM blob WHERE rid=objid)" 3b5514ed82 2007-09-22 drh: " FROM tagxref JOIN event ON rid=objid" 3b5514ed82 2007-09-22 drh: " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%B)" 09c4adeb6f 2007-09-22 drh: " AND tagtype>0" 3b5514ed82 2007-09-22 drh: " AND value IS NULL" 3b5514ed82 2007-09-22 drh: " ORDER BY event.mtime DESC", 3b5514ed82 2007-09-22 drh: pName 3b5514ed82 2007-09-22 drh: ); 3b5514ed82 2007-09-22 drh: blob_zero(&uuid); 3b5514ed82 2007-09-22 drh: if( db_step(&q)==SQLITE_ROW ){ 3b5514ed82 2007-09-22 drh: db_column_blob(&q, 0, &uuid); 3b5514ed82 2007-09-22 drh: } 3b5514ed82 2007-09-22 drh: db_finalize(&q); 3b5514ed82 2007-09-22 drh: if( blob_size(&uuid)==0 ){ 3b5514ed82 2007-09-22 drh: fossil_error(iErrPriority, "not a valid object name: %b", pName); 3b5514ed82 2007-09-22 drh: blob_reset(&uuid); 3b5514ed82 2007-09-22 drh: return 1; 3b5514ed82 2007-09-22 drh: }else{ 3b5514ed82 2007-09-22 drh: blob_reset(pName); 3b5514ed82 2007-09-22 drh: *pName = uuid; 3b5514ed82 2007-09-22 drh: return 0; 3b5514ed82 2007-09-22 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_materialize(pName); dbda8d6ce9 2007-07-21 drh: canonical16(blob_buffer(pName), sz); dbda8d6ce9 2007-07-21 drh: if( sz==UUID_SIZE ){ dbda8d6ce9 2007-07-21 drh: rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName); dbda8d6ce9 2007-07-21 drh: if( rc ){ dbda8d6ce9 2007-07-21 drh: fossil_error(iErrPriority, "unknown object: %b", pName); dbda8d6ce9 2007-07-21 drh: blob_reset(pName); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: }else if( sz<UUID_SIZE && sz>=4 ){ dbda8d6ce9 2007-07-21 drh: char zOrig[UUID_SIZE+1]; dbda8d6ce9 2007-07-21 drh: memcpy(zOrig, blob_buffer(pName), sz); dbda8d6ce9 2007-07-21 drh: zOrig[sz] = 0; dbda8d6ce9 2007-07-21 drh: blob_reset(pName); dbda8d6ce9 2007-07-21 drh: db_blob(pName, "SELECT uuid FROM blob WHERE uuid>='%s'", zOrig); dbda8d6ce9 2007-07-21 drh: if( blob_size(pName)!=UUID_SIZE ){ dbda8d6ce9 2007-07-21 drh: fossil_error(iErrPriority, "no match: %s", zOrig); dbda8d6ce9 2007-07-21 drh: rc = 1; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: zOrig[sz-1]++; dbda8d6ce9 2007-07-21 drh: if( db_exists("SELECT 1 FROM blob WHERE uuid>%B AND uuid<'%s'", dbda8d6ce9 2007-07-21 drh: pName, zOrig) ){ dbda8d6ce9 2007-07-21 drh: zOrig[sz-1]--; dbda8d6ce9 2007-07-21 drh: fossil_error(iErrPriority, "non-unique name prefix: %s", zOrig); dbda8d6ce9 2007-07-21 drh: rc = 1; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: rc = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } e63a9fd9d0 2007-09-25 jnc: }else{ e63a9fd9d0 2007-09-25 jnc: rc = 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: return rc; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: test-name-to-uuid dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Convert a name to a full UUID. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void test_name_to_uuid(void){ dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: Blob name; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: for(i=2; i<g.argc; i++){ dbda8d6ce9 2007-07-21 drh: blob_init(&name, g.argv[i], -1); dbda8d6ce9 2007-07-21 drh: printf("%s -> ", g.argv[i]); dbda8d6ce9 2007-07-21 drh: if( name_to_uuid(&name, 1) ){ dbda8d6ce9 2007-07-21 drh: printf("ERROR: %s\n", g.zErrMsg); dbda8d6ce9 2007-07-21 drh: fossil_error_reset(); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: printf("%s\n", blob_buffer(&name)); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&name); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Convert a name to a rid. If the name is a small integer value then dbda8d6ce9 2007-07-21 drh: ** just use atoi() to do the conversion. If the name contains alphabetic dbda8d6ce9 2007-07-21 drh: ** characters or is not an existing rid, then use name_to_uuid then dbda8d6ce9 2007-07-21 drh: ** convert the uuid to a rid. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This routine is used in test routines to resolve command-line inputs dbda8d6ce9 2007-07-21 drh: ** into a rid. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int name_to_rid(const char *zName){ dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: int rid; dbda8d6ce9 2007-07-21 drh: Blob name; dbda8d6ce9 2007-07-21 drh: for(i=0; zName[i] && isdigit(zName[i]); i++){} dbda8d6ce9 2007-07-21 drh: if( zName[i]==0 ){ dbda8d6ce9 2007-07-21 drh: rid = atoi(zName); dbda8d6ce9 2007-07-21 drh: if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){ dbda8d6ce9 2007-07-21 drh: return rid; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_init(&name, zName, -1); dbda8d6ce9 2007-07-21 drh: if( name_to_uuid(&name, 1) ){ 3b5514ed82 2007-09-22 drh: fossil_fatal("%s", g.zErrMsg); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name); dbda8d6ce9 2007-07-21 drh: blob_reset(&name); dbda8d6ce9 2007-07-21 drh: return rid; dbda8d6ce9 2007-07-21 drh: }