Example #1
0
/**
 * Set the value for @p key as @p newStringValue.
 *
 * The function will allocate and save a private copy of @p newStringValue, so
 * the parameter can be freed after the call.
 *
 * String values will be saved in backend storage, when kdbSetKey() will be
 * called, in UTF-8 universal encoding, regardless of the program's current
 * encoding, when iconv plugin is present.
 *
 * @note The type will be set to KEY_TYPE_STRING.
 * When the type of the key is already a string type it won't be changed.
 *
 * @param key the key to set the string value
 * @param newStringValue NULL-terminated text string to be set as @p key's
 * 	value
 * @return the number of bytes actually saved in private struct including final
 * 	NULL
 * @retval 1 if newStringValue is a NULL pointer, this will make the
 *           string empty (string only containing null termination)
 * @retval -1 if key is a NULL pointer
 * @see keyGetString(), keyValue(), keyString()
 * @ingroup keyvalue
 */
ssize_t keySetString(Key *key, const char *newStringValue)
{
    ssize_t ret=0;

    if (!key) return -1;

    keySetMeta (key, "binary", 0);

    if (!newStringValue || newStringValue[0] == '\0') ret=keySetRaw(key,0,0);
    else ret=keySetRaw(key,newStringValue,elektraStrLen(newStringValue));

    return ret;
}
Example #2
0
/** Reads the value of the key and decodes all escaping
  * codes into the buffer.
  * @pre the buffer needs to be as large as value's size.
  * @param cur the key holding the value to decode
  * @param buf the buffer to write to
  */
void elektraHexcodeDecode (Key * cur, CHexData * hd)
{
	size_t valsize = keyGetValueSize (cur);
	const char * val = keyValue (cur);

	if (!val) return;

	size_t out = 0;
	for (size_t in = 0; in < valsize - 1; ++in)
	{
		char c = val[in];
		char * n = hd->buf + out;

		if (c == hd->escape)
		{
			in += 2; /* Advance twice (2 hex numbers) */
			char first = val[in - 1];
			char second = val[in];
			int res;

			res = elektraHexcodeConvFromHex (second);
			res += elektraHexcodeConvFromHex (first) * 16;
			*n = res & 255;
		}
		else
		{
			*n = c;
		}
		++out; /* Only one char is written */
	}

	hd->buf[out] = 0; // null termination for keyString()

	keySetRaw (cur, hd->buf, out + 1);
}
Example #3
0
/** Reads the value of the key and encodes it in
  * c-style in the buffer.
  *
  * @param cur the key which value is to encode
  * @param buf the buffer
  * @pre the buffer needs to have thrice as much space as the value's size
  */
void elektraHexcodeEncode (Key * cur, CHexData * hd)
{
	size_t valsize = keyGetValueSize (cur);
	const char * val = keyValue (cur);

	if (!val) return;

	size_t out = 0;
	for (size_t in = 0; in < valsize - 1; ++in)
	{
		unsigned char c = val[in];

		// need to encode char?
		if (hd->hd[c & 255])
		{
			hd->buf[out] = hd->escape;
			out++;
			hd->buf[out] = elektraHexcodeConvToHex (c / 16);
			out++;
			hd->buf[out] = elektraHexcodeConvToHex (c % 16);
			out++;
		}
		else
		{
			// just copy one character
			hd->buf[out] = val[in];
			// advance out cursor
			out++;
		}
	}

	hd->buf[out] = 0; // null termination for keyString()

	keySetRaw (cur, hd->buf, out + 1);
}
Example #4
0
/**
 * Set the value of a key as a binary.
 *
 * A private copy of @p newBinary will allocated and saved inside @p key,
 * so the parameter can be deallocated after the call.
 *
 * Binary values might be encoded in another way then string values
 * depending on the plugin. Typically character encodings should not take
 * place on binary data.
 * Consider using a string key instead.
 *
 * When newBinary is a NULL pointer the binary will be freed and 0 will
 * be returned.
 *
 * @note The meta data "binary" will be set to mark that the key is
 * binary from now on. When the key is already binary the meta data
 * won't be changed. This will only happen in the successful case,
 * but not when -1 is returned.
 *
 * @param key the object on which to set the value
 * @param newBinary is a pointer to any binary data or NULL to free the previous set data
 * @param dataSize number of bytes to copy from @p newBinary
 * @return the number of bytes actually copied to internal struct storage
 * @retval 0 when the internal binary was freed and is now a null pointer
 * @retval -1 if key is a NULL pointer
 * @retval -1 when dataSize is 0 (but newBinary not NULL) or larger than SSIZE_MAX
 * @see keyGetBinary()
 * @see keyIsBinary() to check if the type is binary
 * @see keyGetString() and keySetString() as preferred alternative to binary
 * @ingroup keyvalue
 */
ssize_t keySetBinary(Key *key, const void *newBinary, size_t dataSize)
{
    ssize_t ret=0;

    if (!key) return -1;

    if (!dataSize && newBinary) return -1;
    if (dataSize > SSIZE_MAX) return -1;
    if (key->flags & KEY_FLAG_RO_VALUE) return -1;

    keySetMeta (key, "binary", "");

    ret = keySetRaw(key,newBinary,dataSize);


    return ret;
}
Example #5
0
/*
 * 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;
}