예제 #1
0
static void test_sectionRead (char * fileName)
{
	Key * parentKey = keyNew ("user/tests/ini-section-read", KEY_VALUE, srcdir_file (fileName), KEY_END);
	KeySet * conf = ksNew (0, KS_END);
	PLUGIN_OPEN ("ini");

	KeySet * ks = ksNew (0, KS_END);

	succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful");
	succeed_if (output_error (parentKey), "error in kdbGet");
	succeed_if (output_warnings (parentKey), "warnings in kdbGet");

	Key * key = ksLookupByName (ks, "user/tests/ini-section-read/akey/looking/like/sections", KDB_O_NONE);
	exit_if_fail (key, "section like key not found not found");
	succeed_if (!strcmp ("value", keyString (key)), "section like key contained invalid data");

	key = ksLookupByName (ks, "user/tests/ini-section-read/emptysection", KDB_O_NONE);
	exit_if_fail (key, "empty section key not found");
	succeed_if (keyIsBinary (key), "empty section key is not a binary key");
	succeed_if (!keyValue (key), "section key contains non null data");

	key = ksLookupByName (ks, "user/tests/ini-section-read/section1", KDB_O_NONE);
	exit_if_fail (key, "section1 key not found");
	succeed_if (keyIsBinary (key), "section1 key is not a binary key");
	succeed_if (!keyValue (key), "section1 contains non null data");

	key = ksLookupByName (ks, "user/tests/ini-section-read/section1/key1", KDB_O_NONE);
	exit_if_fail (key, "key1 not found not found");
	succeed_if (!strcmp ("value1", keyString (key)), "key1 contained invalid data");

	key = ksLookupByName (ks, "user/tests/ini-section-read/section1/key/with/subkey", KDB_O_NONE);
	exit_if_fail (key, "key with subkey not found not found");
	succeed_if (!strcmp ("value2", keyString (key)), "key with subkey contained invalid data");

	key = ksLookupByName (ks, "user/tests/ini-section-read/section2/with/subkey", KDB_O_NONE);
	exit_if_fail (key, "section2 key not found");
	succeed_if (keyIsBinary (key), "section2 key is not a binary key");
	succeed_if (!keyValue (key), "section2 contains non null data");

	key = ksLookupByName (ks, "user/tests/ini-section-read/section2/with/subkey/key2", KDB_O_NONE);
	exit_if_fail (key, "key2 not found not found");
	succeed_if (!strcmp ("value2", keyString (key)), "key2 contained invalid data");

	ksDel (ks);
	keyDel (parentKey);

	PLUGIN_CLOSE ();
}
예제 #2
0
파일: keyvalue.c 프로젝트: tryge/libelektra
/**
 * @internal
 *
 * Set raw  data as the value of a key.
 * If NULL pointers are passed, key value is cleaned.
 * This method will not change or set the key type, and should only
 * be used internally in elektra.
 *
 * @param key the key object to work with
 * @param newBinary array of bytes to set as the value
 * @param dataSize number bytes to use from newBinary, including the final NULL
 * @return The number of bytes actually set in internal buffer.
 * @retval 1 if it was a string which was deleted
 * @retval 0 if it was a binary which was deleted
 * @see keySetType(), keySetString(), keySetBinary()
 * @ingroup keyvalue
 */
ssize_t keySetRaw(Key *key, const void *newBinary, size_t dataSize)
{
    if (!key) return -1;
    if (key->flags & KEY_FLAG_RO_VALUE) return -1;

    if (!dataSize || !newBinary)
    {
        if (key->data.v) {
            elektraFree (key->data.v);
            key->data.v=0;
        }
        key->dataSize = 0;
        set_bit(key->flags, KEY_FLAG_SYNC);
        if (keyIsBinary(key)) return 0;
        return 1;
    }

    key->dataSize=dataSize;
    if (key->data.v)
    {
        char *p=0;
        p=realloc(key->data.v,key->dataSize);
        if (0==p) return -1;
        key->data.v=p;
    } else {
        char *p=elektraMalloc(key->dataSize);
        if (0==p) return -1;
        key->data.v=p;
    }


    memcpy(key->data.v,newBinary,key->dataSize);
    set_bit(key->flags, KEY_FLAG_SYNC);
    return keyGetValueSize (key);
}
예제 #3
0
파일: keyvalue.c 프로젝트: tryge/libelektra
/**
 * Get the value of a key as a binary.
 *
 * If the type is not binary -1 will be returned.
 *
 * When the binary data is empty (this is not the same as ""!)
 * 0 will be returned and the returnedBinary will not be changed.
 *
 * For string values see keyGetString() and keyIsString().
 *
 * When the returnedBinary is to small to hold the data
 * (its maximum size is given by maxSize),
 * the returnedBinary will not be changed and -1 is returned.
 *
 * @par Example:
 * @code
Key *key = keyNew ("user/keyname", KEY_TYPE, KEY_TYPE_BINARY, KEY_END);
char buffer[300];

if (keyGetBinary(key,buffer,sizeof(buffer)) == -1)
{
	// handle error
}
 * @endcode
 *
 * @param key the object to gather the value from
 * @param returnedBinary pre-allocated memory to store a copy of the key value
 * @param maxSize number of bytes of pre-allocated memory in @p returnedBinary
 * @return the number of bytes actually copied to @p returnedBinary
 * @retval 0 if the binary is empty
 * @retval -1 on NULL pointers
 * @retval -1 if maxSize is 0
 * @retval -1 if maxSize is too small for string
 * @retval -1 if maxSize is larger than SSIZE_MAX
 * @retval -1 on type mismatch: binary expected, but found string
 * @see keyValue(), keyGetValueSize(), keySetBinary()
 * @see keyGetString() and keySetString() as preferred alternative to binary
 * @see keyIsBinary() to see how to check for binary type
 * @ingroup keyvalue
 */
ssize_t keyGetBinary(const Key *key, void *returnedBinary, size_t maxSize)
{
    if (!key) return -1;
    if (!returnedBinary) return -1;
    if (!maxSize) return -1;

    if (maxSize > SSIZE_MAX) return -1;

    if (!keyIsBinary(key))
    {
        /*errno=KDB_ERR_TYPEMISMATCH;*/
        return -1;
    }

    if (!key->data.v)
    {
        return 0;
    }

    if (key->dataSize > maxSize)
    {
        /*errno=KDB_ERR_TRUNC;*/
        return -1;
    }

    memcpy(returnedBinary,key->data.v,key->dataSize);
    return key->dataSize;
}
예제 #4
0
파일: ini.c 프로젝트: tryge/libelektra
static short isSectionKey(Key *key)
{
	if (!key) return 0;
	if (keyIsBinary(key))
		return 1;
	else 
		return 0;
}
예제 #5
0
파일: stream.c 프로젝트: tryge/libelektra
/**
 * Generate a C-Style key and stream it.
 *
 * This keyset can be used to include as c-code for
 * applikations using elektra.
 *
 * @param key the key object to work with
 * @param stream the file pointer where to send the stream
 * @param options KDB_O_SHOWINDICES, KDB_O_IGNORE_COMMENT, KDB_O_SHOWINFO
 * @retval 1 on success
 * @ingroup stream
 */
int keyGenerate(const Key * key, FILE *stream, option_t options)
{
	size_t s;
	char * str;

	size_t c;
	char * com;

	size_t n;
	char * nam;

	n = keyGetNameSize (key);
	if (n>1)
	{
		nam = (char*) elektraMalloc (n);
		if (nam == NULL) return -1;
		keyGetName (key, nam, n);
		fprintf(stream,"\tkeyNew (\"%s\"", nam);
		elektraFree (nam);
	}

	s = keyGetValueSize (key);
	if (s>1)
	{
		str = (char*) elektraMalloc (s);
		if (str == NULL) return -1;
		if (keyIsBinary(key)) keyGetBinary(key, str, s);
		else keyGetString (key, str, s);
		fprintf(stream,", KEY_VALUE, \"%s\"", str);
		elektraFree (str);
	}

	c = keyGetCommentSize (key);
	if (c>1)
	{
		com = (char*) elektraMalloc (c);
		if (com == NULL) return -1;
		keyGetComment (key, com, c);
		fprintf(stream,", KEY_COMMENT, \"%s\"", com);
		elektraFree (com);
	}

	if (! (keyGetMode(key) == 0664 || (keyGetMode(key) == 0775)))
	{
		fprintf(stream,", KEY_MODE, 0%3o", keyGetMode(key));
	}

	fprintf(stream,", KEY_END)");

	if (options == 0) return 1; /* dummy to make icc happy */
	return 1;
}
예제 #6
0
파일: keyvalue.c 프로젝트: tryge/libelektra
/**
 * Returns the number of bytes needed to store the key value, including the
 * NULL terminator.
 *
 * It returns the correct size, independent of the Key Type.
 * If it is a binary there might be '\\0' values in it.
 *
 * For an empty string you need one byte to store the ending NULL.
 * For that reason 1 is returned. This is not true for binary data,
 * so there might be returned 0 too.
 *
 * A binary key has no '\\0' termination. String types have it, so to there
 * length will be added 1 to have enough space to store it.
 *
 * This method can be used with elektraMalloc() before keyGetString() or keyGetBinary()
 * is called.
 *
 * @code
char *buffer;
buffer = elektraMalloc (keyGetValueSize (key));
// use this buffer to store the value (binary or string)
// pass keyGetValueSize (key) for maxSize
 * @endcode
 *
 * @param key the key object to work with
 * @return the number of bytes needed to store the key value
 * @retval 1 when there is no data and type is not binary
 * @retval 0 when there is no data and type is binary
 * @retval -1 on null pointer
 * @see keyGetString(), keyGetBinary(), keyValue()
 * @ingroup keyvalue
 */
ssize_t keyGetValueSize(const Key *key)
{
    if (!key) return -1;

    if (!key->data.v)
    {
        /*errno=KDB_ERR_NODATA;*/
        if (keyIsBinary(key)) return 0;
        else return 1;
    }

    return key->dataSize;
}
예제 #7
0
파일: keyvalue.c 프로젝트: tryge/libelektra
/**
 * Return a pointer to the real internal @p key value.
 *
 * This is a much more efficient version of keyGetString()
 * keyGetBinary(), and you should use it if you are responsible enough to
 * not mess up things. You are not allowed to modify anything
 * in the returned string. If you need a copy of the Value, consider
 * to use keyGetString() or keyGetBinary() instead.
 *
 * @section string String Handling
 *
 * If @p key is string (keyIsString()), you may cast the returned as a
 * @c "char *" because you'll get a NULL terminated regular string.
 *
 * keyValue() returns "" in string mode when there is no value. The reason is
 * @code
key=keyNew(0);
keySetString(key,"");
keyValue(key); // you would expect "" here
keyDel(key);
 * @endcode
 *
 * @section binary Binary Data Handling
 *
 * If the data is binary, the size of the value must be determined by
 * keyGetValueSize(), any strlen() operations are not suitable to determine
 * the size.
 *
 * keyValue() returns 0 in binary mode when there is no value. The reason is
 * @code
key=keyNew(0);
keySetBinary(key, 0, 0);
keyValue(key); // you would expect 0 here

keySetBinary(key,"", 1);
keyValue(key); // you would expect "" (a pointer to '\0') here

int i=23;
keySetBinary(key, (void*)&i, 4);
(int*)keyValue(key); // you would expect a pointer to (int)23 here
keyDel(key);
 * @endcode
 *
 * @note Note that the Key structure keeps its own size field that is calculated
 * by library internal calls, so to avoid inconsistencies, you
 * must never use the pointer returned by keyValue() method to set a new
 * value. Use keySetString() or keySetBinary() instead.
 *
 * @warning Binary keys will return a NULL pointer when there is no data in contrast
 * to keyName(), keyBaseName(), keyOwner() and keyComment(). For string value the
 * behaviour is the same.
 *
 * @par Example:
 * @code
KDB *handle = kdbOpen();
KeySet *ks=ksNew(0, KS_END);
Key *current=0;

kdbGetByName(handle,ks,"system/sw/my",KDB_O_SORT|KDB_O_RECURSIVE);

ksRewind(ks);
while (current=ksNext(ks)) {
	size_t size=0;

	if (keyIsBin(current)) {
		size=keyGetValueSize(current);
		printf("Key %s has a value of size %d bytes. Value: <BINARY>\nComment: %s",
			keyName(current),
			size,
			keyComment(current));
	} else {
		size=elektraStrLen((char *)keyValue(current));
		printf("Key %s has a value of size %d bytes. Value: %s\nComment: %s",
			keyName(current),
			size,
			(char *)keyValue(current),
			keyComment(current));
	}
}

ksDel (ks);
kdbClose (handle);
 * @endcode
 *
 * @param key the key object to work with
 * @return a pointer to internal value
 * @retval "" when there is no data and key is not binary
 * @retval 0 where there is no data and key is binary
 * @retval 0 on NULL pointer
 * @see keyGetValueSize(), keyGetString(), keyGetBinary()
 * @ingroup keyvalue
 */
const void *keyValue(const Key *key)
{
    if (!key) return 0;

    if (!key->data.v)
    {
        /*errno=KDB_ERR_NOKEY;*/
        if (keyIsBinary(key)) return 0;
        else return "";
    }

    return key->data.v;
}
예제 #8
0
파일: keyvalue.c 프로젝트: tryge/libelektra
/**
 * Get the c-string representing the value.
 *
 * Will return (null) on null pointers.
 * Will return (binary) on binary data not ended
 * with a null byte.
 *
 * It is not checked if it is actually a string,
 * only if it terminates for security reasons.
 *
 * @return the c-string of the value
 * @retval "(null)" on null keys
 * @retval "" if no data found
 * @retval "(binary)" on binary keys
 * @ingroup keyvalue
 * @param key the key object to get the string from
 */
const char *keyString(const Key *key)
{
    if (!key) return "(null)";

    if (!key->data.c)
    {
        return "";
    }

    if (keyIsBinary(key))
    {
        return "(binary)";
    }

    return key->data.c;
}
예제 #9
0
static void test_keyFlags (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

	KeySet * ks = ksNew (10, keyNew ("user/tests/storage/testKey", KEY_FLAGS, KEY_BINARY, KEY_VALUE, "test key", KEY_END), KS_END);
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");

	Key * found = ksLookupByName (ks, "user/tests/storage/testKey", 0);
	succeed_if (found, "did not find key");
	succeed_if (keyIsBinary (found) == 1, "Key is not binary.");

	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
예제 #10
0
파일: c.c 프로젝트: sanssecours/libelektra
/**
 * Generate a C-Style key and stream it.
 *
 * This keyset can be used to include as c-code for
 * applikations using elektra.
 *
 * @param key the key object to work with
 * @param stream the file pointer where to send the stream
 * @param options KDB_O_SHOWINDICES, KDB_O_IGNORE_COMMENT, KDB_O_SHOWINFO
 * @retval 1 on success
 * @ingroup stream
 */
int keyGenerate (const Key * key, FILE * stream, option_t options)
{
	size_t n = keyGetNameSize (key);
	if (n > 1)
	{
		char * nam = (char *) elektraMalloc (n);
		if (nam == NULL) return -1;
		keyGetName (key, nam, n);
		fprintf (stream, "\tkeyNew (\"%s\"", nam);
		elektraFree (nam);
	}

	size_t s = keyGetValueSize (key);
	if (s > 1)
	{
		char * str = (char *) elektraMalloc (s);
		if (str == NULL) return -1;
		if (keyIsBinary (key))
		{
			keyGetBinary (key, str, s);
			fprintf (stream, ", KEY_SIZE, \"%zd\"", keyGetValueSize (key));
		}
		else
		{
			keyGetString (key, str, s);
		}
		fprintf (stream, ", KEY_VALUE, \"%s\"", str);
		elektraFree (str);
	}

	const Key * meta;
	Key * dup = keyDup (key);
	keyRewindMeta (dup);
	while ((meta = keyNextMeta (dup)))
	{
		fprintf (stream, ", KEY_META, \"%s\", \"%s\"", keyName (meta), keyString (meta));
	}
	keyDel (dup);

	fprintf (stream, ", KEY_END)");

	if (options == 0) return 1; /* dummy to make icc happy */
	return 1;
}
static void test_enc_and_dec_with_binary()
{
	elektraCryptoHandle *handle;
	KeySet *config;
	Key *errorKey = keyNew(KEY_END);
	const unsigned char original[] = { 0x00, 0x01, 0x02, 0x03 };
	unsigned char content[64];
	unsigned long read = 0;

	Key *k = keyNew("user/plugins/crypto/gcrypt/test-enc-dec-bin", KEY_END);
	keySetBinary(k, original, sizeof(original));

	getWorkingConfiguration(&config);
	succeed_if( elektraCryptoInit(errorKey) == 1, "crypto initialization failed" );

	// 1. encrypt
	succeed_if( elektraCryptoHandleCreate(&handle, config, errorKey) == 1, "handle initialization with compliant config failed" );
	succeed_if( elektraCryptoEncrypt(handle, k, errorKey) == 1, "encryption failed" );
	elektraCryptoHandleDestroy(handle);

	// 2. decrypt
	succeed_if( elektraCryptoHandleCreate(&handle, config, errorKey) == 1, "handle initialization with compliant config failed" );
	succeed_if( elektraCryptoDecrypt(handle, k, errorKey) == 1, "decryption failed" );
	elektraCryptoHandleDestroy(handle);

	// 3. check result
	succeed_if( keyIsBinary(k) == 1, "key is of non-binary type");
	read = keyGetBinary(k, content, sizeof(content));
	succeed_if( read == sizeof(original), "decrypted value is of different length than original" );
	if(read == sizeof(original))
	{
		succeed_if( memcmp(original, content, read) == 0, "decrypted value differs from original");
	}

	keyDel(k);
	keyDel(errorKey);
	ksDel(config);
	elektraCryptoTeardown();
}
예제 #12
0
void test_key ()
{
	KeySet * ks;
	Key * cur;
	int counter;

	printf ("Testing Key from xml\n");

	ks = ksNew (0, KS_END);
	exit_if_fail (ksFromXMLfile (ks, srcdir_file ("xmltool/key.xml")) == 0, "ksFromXMLfile(key.xml) failed.");
	counter = 0;
	ksRewind (ks);
	while ((cur = ksNext (ks)))
	{
		counter++;
		/* Prepend key root */
		// snprintf(buf, sizeof(buf), "%s/%s", root, keyName(cur));
		// keySetName(cur, buf);

		/* Make tests ... */
		// printf ("counter: %d - name: %s - value: %s\n", counter, (char*) keyName(cur), (char*)keyValue(cur));
		switch (counter)
		{
		case 1:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenBinaryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetMode (cur) == 0440, "could not get mode");
			break;
		case 2:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenDirectoryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			break;
		case 3:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenStringKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "String key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			succeed_if (keyGetUID (cur) == 0, "could not get uid value");
			succeed_if (keyGetGID (cur) == 20, "could not get gid value");
			break;
		case 4:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectBinaryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with standard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetGID (cur) == 40, "could not get gid value");
			break;
		case 5:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectDirectoryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory key with standard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			break;
		case 6:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectStringKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "String key with\nstandard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			succeed_if (keyGetUID (cur) == 20, "could not get uid value");
			break;
		case 7:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Bin@a€ry Key") == 0, "wrong name");
			succeed_if (keyValue (cur) == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetMode (cur) == 230, "could not get mode");
			// <key type="binary" basename="Ug.ly:Bin@a€ry Key"><comment>Binary key with ugly name</comment></key>
			break;
		case 8:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Dir@ect€ory Key") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			// <key type="directory" basename="Ug.ly:Dir@ect€ory Key"><comment>Directory with ugly name</comment></key>
			break;
		case 9:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:St@ri€n.g Key") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "With a string value") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "string key with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			// <key type="string" basename="Ug.ly:St@ri€n.g Key" value="With a string value"><comment>string key with ugly
			// name</comment></key>
			break;
		}
	}

	ksDel (ks);
}
예제 #13
0
파일: kdbtools.c 프로젝트: tryge/libelektra
/*
 * Processes the current <key> node from reader, converting from XML
 * to a Key object, and ksAppendKey() it to ks.
 *
 * See keyToStream() for an example of a <key> node.
 *
 * This function is completelly dependent on libxml.
 * 
 * @param ks where to put the resulting reded key
 * @param context a prent key name, so a full name can be calculated
 *        if the XML node for the current key only provides a basename
 * @param reader where to read from
 */
static int consumeKeyNode(KeySet *ks, const char *context, xmlTextReaderPtr reader)
{
	xmlChar *nodeName=0;
	xmlChar *keyNodeName=0;
	xmlChar *buffer=0;
	xmlChar *privateContext=0;
	Key *newKey=0;
	int appended=0;

	/* printf("%s", KDB_SCHEMA_PATH); */
	
	keyNodeName=xmlTextReaderName(reader);
	if (!strcmp((char *)keyNodeName,"key")) {
		mode_t isdir=0;
		int isbin=0;
		int end=0;
		
		newKey=keyNew(0);

		/* a <key> must have one of the following:
		   - a "name" attribute, used as an absolute name overriding the context
		   - a "basename" attribute, that will be appended to the current context
		   - a "parent" plus "basename" attributes, both appended to current context
		   - only a "parent", appended to current context
		*/
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"name");
		if (buffer) {
			/* set absolute name */
			keySetName(newKey,(char *)buffer);
			xmlFree(buffer); buffer=0;
		} else {
			/* logic for relative name calculation */
			
			privateContext=xmlTextReaderGetAttribute(reader,
				(const xmlChar *)"parent");
			buffer=xmlTextReaderGetAttribute(reader,
				(const xmlChar *)"basename");

			if (context) keySetName(newKey,context);
			if (privateContext) keyAddName(newKey, (char *)privateContext);
			if (buffer) keyAddName(newKey,(char *)buffer);

			xmlFree(privateContext); privateContext=0;
			xmlFree(buffer); buffer=0;
		}


		/* test for a short value attribute, instead of <value> bellow */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"value");
		if (buffer) {
			keySetRaw(newKey,buffer,elektraStrLen((char *)buffer));
			xmlFree(buffer); buffer=0;
		}

		/* Parse UID */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"uid");
		if (buffer) {
			int errsave = errno;
			char * endptr;
			long int uid = strtol ((const char *)buffer, &endptr, 10);
			errno = errsave;
			if (endptr != '\0' && *endptr == '\0')
			{
				keySetUID(newKey,uid);
			}
			xmlFree(buffer); buffer=0;
		}

		/* Parse GID */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"gid");
		if (buffer) {
			int errsave = errno;
			char * endptr;
			long int gid = strtol ((const char *)buffer, &endptr, 10);
			errno = errsave;
			if (endptr != '\0' && *endptr == '\0')
			{
				keySetGID(newKey,gid);
			}
			xmlFree(buffer); buffer=0;
		}

		/* Parse mode permissions */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"mode");
		int errsave = errno;
		if (buffer) keySetMode(newKey,strtol((char *)buffer,0,0));
		errno = errsave;
		xmlFree(buffer);



		if (xmlTextReaderIsEmptyElement(reader)) {
			/* we have a <key ..../> element */
			if (newKey && !appended) {
				ksAppendKey(ks,newKey);
				appended=1;
				end=1;
			}
		}

		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"type");
		if (buffer)
		{
			if (!strcmp((char *)buffer,"binary")) isbin = 1;
			else if (!strcmp((char *)buffer,"bin")) isbin = 1;
		}
		xmlFree(buffer);

		/* If "isdir" appears, everything different from "0", "false" or "no"
		marks it as a dir key */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"isdir");
		if (!isdir && buffer)
		{
			if (	strcmp((char *)buffer,"0") &&
				strcmp((char *)buffer,"false") &&
				strcmp((char *)buffer,"no"))
				isdir = 1;
			else	isdir = 0;
		}
		xmlFree(buffer);

		if (isdir) keySetDir(newKey);
		if (isbin) keySetMeta (newKey, "binary", "");

		// TODO: should parse arbitrary attributes as metadata

		/* Parse everything else */
		while (!end) {
			xmlTextReaderRead(reader);
			nodeName=xmlTextReaderName(reader);

			if (!strcmp((char *)nodeName,"value")) {
				if (xmlTextReaderIsEmptyElement(reader) ||
					xmlTextReaderNodeType(reader)==15)
				{
					xmlFree (nodeName);
					continue;
				}
					
				xmlTextReaderRead(reader);
				buffer=xmlTextReaderValue(reader);
				
				if (buffer) {
					/* Key's value type was already set above */
					if (keyIsBinary(newKey)) {
						/* TODO binary values
						char *unencoded=0;
						size_t unencodedSize;
						
						unencodedSize=elektraStrLen((char *)buffer)/2;
						unencoded=elektraMalloc(unencodedSize);
						unencodedSize=kdbbDecode((char *)buffer,unencoded);
						if (!unencodedSize) return -1;
							keySetRaw(newKey,unencoded,unencodedSize);
						elektraFree (unencoded);
						*/
					} else keySetRaw(newKey,buffer,elektraStrLen((char *)buffer));
				}
				xmlFree(buffer);
			} else if (!strcmp((char *)nodeName,"comment")) {
				ssize_t commentSize=0;
				
				if (xmlTextReaderIsEmptyElement(reader) ||
					xmlTextReaderNodeType(reader)==15)
				{
					xmlFree (nodeName);
					continue;
				}
					
				xmlTextReaderRead(reader);
				buffer=xmlTextReaderValue(reader);
				
				if ((commentSize=keyGetCommentSize(newKey)) > 1) {
					/*Multiple line comment*/
					char *tmpComment=0;
					tmpComment=elektraMalloc(commentSize+
						xmlStrlen(buffer)*sizeof(xmlChar)+1);

					if (tmpComment) {
						keyGetComment(newKey,tmpComment,commentSize);

						strcat(tmpComment,"\n");
						strcat(tmpComment,(char *)buffer);

						keySetComment(newKey,tmpComment);

						elektraFree (tmpComment); tmpComment=0;
					}
				} else keySetComment(newKey,(char *)buffer);
				xmlFree(buffer);
			} else if (!strcmp((char *)nodeName,"key")) {
				/* Here we found </key> or a sub <key>.
				   So include current key in the KeySet. */
				if (newKey && !appended) {
					ksAppendKey(ks,newKey);
					appended=1;
				}
				
				if (xmlTextReaderNodeType(reader)==15)
					/* found a </key> */
					end=1;
				else {
					/* found a sub <key> */
					/* prepare the context (parent) */
					consumeKeyNode(ks,newKey->key,reader);
				}
			}

			xmlFree (nodeName);
		}

		if (privateContext) xmlFree(privateContext);

		/* seems like we forgot the key, lets delete it */
		if (newKey && !appended) {
			keyDel (newKey);
			appended=1;
		}
	}

	xmlFree(keyNodeName);
	
	return 0;
}
예제 #14
0
파일: stream.c 프로젝트: tryge/libelektra
/**
 * Output every information of a single key depending on options.
 *
 * The format is not very strict and only intend to be read
 * by human eyes for debugging purposes. Don't rely on the
 * format in your applications.
 *
 * @param k the key object to work with
 * @param stream the file pointer where to send the stream
 * @param options see text above
 * @see ksOutput()
 * @retval 1 on success
 * @retval -1 on allocation errors
 * @ingroup stream
 */
int keyOutput (const Key * k, FILE *stream, option_t options)
{
	time_t t;
	size_t s;
	char * tmc;
	char * str;

	size_t c;
	char * com;

	size_t n;
	char * nam;

	n = keyGetNameSize (k);
	if (n>1)
	{
		nam = (char*) elektraMalloc (n);
		if (nam == NULL) return -1;
		keyGetName (k, nam, n);

		fprintf(stream,"Name[%d]: %s : ", (int)n, nam);

		elektraFree (nam);
	}

	s = keyGetValueSize (k);
	if (options & KEY_VALUE && s>1)
	{
		str = (char*) elektraMalloc (s);
		if (str == NULL) return -1;
		if (keyIsBinary(k))
		{
			/*
			char * bin;
			bin = (char*) elektraMalloc (s*3+1);
			keyGetBinary(k, str, s);
			kdbbEncode (str, s, bin);
			elektraFree (bin);
			*/
			keyGetBinary (k, str, s);
			fprintf(stream,"Binary[%d]: %s : ", (int)s, str);
		} else {
			keyGetString (k, str, s);
			fprintf(stream,"String[%d]: %s : ", (int)s, str);
		}

		elektraFree (str);
	}

	c = keyGetCommentSize (k);
	if (options & KEY_COMMENT && c>1)
	{
		com = (char*) elektraMalloc (c);
		if (com == NULL) return -1;
		keyGetComment (k, com, c);

		fprintf(stream,"Comment[%d]: %s : ", (int)c, com);

		elektraFree (com);
	}


	if (options & KDB_O_SHOWMETA) fprintf(stream," : ");
	if (options & KEY_UID) fprintf(stream,"UID: %d : ", (int)keyGetUID (k));
	if (options & KEY_GID) fprintf(stream,"GID: %d : ", (int)keyGetGID (k));
	if (options & KEY_MODE) fprintf(stream,"Mode: %o : ", (int)keyGetMode (k));

	if (options & KEY_ATIME)
	{
		t=keyGetATime(k);
		tmc = ctime (& t);
		tmc[24] = '\0';
		fprintf(stream,"ATime: %s : ", tmc);
	}

	if (options & KEY_MTIME)
	{
		t=keyGetMTime(k);
		tmc = ctime (& t);
		tmc[24] = '\0';
		fprintf(stream,"MTime: %s : ", tmc);
	}

	if (options & KEY_CTIME)
	{
		t=keyGetCTime(k);
		tmc = ctime (& t);
		tmc[24] = '\0';
		fprintf(stream,"CTime: %s : ", tmc);
	}

	if (options & KDB_O_SHOWFLAGS)
	{
		if (!(options & KDB_O_SHOWMETA)) fprintf(stream, " ");
		fprintf (stream,"Flags: ");
		if (keyIsBinary(k)) fprintf(stream,"b");
		if (keyIsString(k)) fprintf(stream,"s");
		if (keyIsInactive(k)) fprintf(stream,"i");
		if (keyNeedSync(k)) fprintf(stream,"s");
	}

	fprintf(stream,"\n");
	return 1;
}