LCOV - code coverage report
Current view: top level - src/plugins/mozprefs - mozprefs.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 123 133 92.5 %
Date: 2019-09-12 12:28:41 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Source for mozprefs plugin
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include "mozprefs.h"
      11             : 
      12             : #include <kdbhelper.h>
      13             : #include <kdbutility.h>
      14             : 
      15             : #include <ctype.h>
      16             : #include <stdio.h>
      17             : #include <stdlib.h>
      18             : #include <string.h>
      19             : 
      20             : typedef enum
      21             : {
      22             :         PREF = 0,
      23             :         USER,
      24             :         LOCK,
      25             :         STICKY,
      26             :         PREF_END,
      27             : } PrefType;
      28             : 
      29             : 
      30             : const char * function[] = { "pref", "user_pref", "lockPref", "sticky_pref" };
      31             : const char * prefix[] = { "pref", "user", "lock", "sticky" };
      32             : 
      33          26 : static Key * prefToKey (Key * parentKey, PrefType type, const char * pref)
      34             : {
      35          26 :         Key * key = keyNew (keyName (parentKey), KEY_END);
      36          26 :         keyAddBaseName (key, prefix[type]);
      37          26 :         char * localString = elektraStrDup (pref);
      38          26 :         char * cPtr = strstr (localString, ",");
      39          26 :         *cPtr = '\0';
      40          26 :         char * sPtr = localString;
      41          26 :         ++sPtr;
      42          26 :         *sPtr++ = '\0';
      43          26 :         char * ePtr = cPtr - 1;
      44          26 :         elektraRstrip (sPtr, &ePtr);
      45          26 :         size_t keyLen = ePtr - sPtr;
      46          26 :         char * prefKey = elektraMalloc (keyLen + 1);
      47          26 :         snprintf (prefKey, keyLen + 1, "%s", sPtr);
      48          26 :         char * tPtr = strtok (prefKey, ".");
      49          26 :         if (tPtr) keyAddBaseName (key, tPtr);
      50          78 :         while ((tPtr = strtok (NULL, ".")) != NULL)
      51             :         {
      52          52 :                 keyAddBaseName (key, tPtr);
      53             :         }
      54          26 :         elektraFree (prefKey);
      55          26 :         sPtr = cPtr + 1;
      56          26 :         sPtr = elektraLskip (sPtr);
      57          26 :         ePtr = strrchr (sPtr, ')');
      58          26 :         *ePtr-- = '\0';
      59          26 :         elektraRstrip (sPtr, &ePtr);
      60          26 :         size_t argLen = ePtr - sPtr + 1;
      61          26 :         char * prefArg = elektraMalloc (argLen + 1);
      62          26 :         snprintf (prefArg, argLen + 1, "%s", sPtr);
      63          26 :         if (!strcmp (prefArg, "true") || !(strcmp (prefArg, "false")))
      64             :         {
      65          11 :                 keySetMeta (key, "type", "boolean");
      66          11 :                 keySetString (key, prefArg);
      67             :         }
      68          15 :         else if (prefArg[0] == '"' && prefArg[strlen (prefArg) - 1] == '"')
      69             :         {
      70             :                 // TODO: else if list
      71           8 :                 keySetMeta (key, "type", "string");
      72           8 :                 *prefArg = '\0';
      73           8 :                 *(prefArg + (strlen (prefArg + 1))) = '\0';
      74           8 :                 keySetString (key, (prefArg + 1));
      75             :         }
      76             :         else
      77             :         {
      78           7 :                 keySetMeta (key, "type", "integer");
      79           7 :                 keySetString (key, prefArg);
      80             :         }
      81          26 :         elektraFree (prefArg);
      82          26 :         elektraFree (localString);
      83          26 :         return key;
      84             : }
      85             : 
      86             : 
      87          41 : int elektraMozprefsGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
      88             : {
      89          41 :         if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/mozprefs"))
      90             :         {
      91          31 :                 KeySet * contract =
      92          31 :                         ksNew (30, keyNew ("system/elektra/modules/mozprefs", KEY_VALUE, "mozprefs plugin waits for your orders", KEY_END),
      93             :                                keyNew ("system/elektra/modules/mozprefs/exports", KEY_END),
      94             :                                keyNew ("system/elektra/modules/mozprefs/exports/get", KEY_FUNC, elektraMozprefsGet, KEY_END),
      95             :                                keyNew ("system/elektra/modules/mozprefs/exports/set", KEY_FUNC, elektraMozprefsSet, KEY_END),
      96             : #include ELEKTRA_README
      97             :                                keyNew ("system/elektra/modules/mozprefs/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
      98          31 :                 ksAppend (returned, contract);
      99          31 :                 ksDel (contract);
     100             : 
     101          31 :                 return 1; // success
     102             :         }
     103             :         // get all keys
     104          10 :         const char * fileName = keyString (parentKey);
     105          10 :         FILE * fp = fopen (fileName, "r");
     106          10 :         int len = 1024;
     107          10 :         char * buffer = elektraMalloc (len * sizeof (char));
     108             :         Key * key;
     109             : 
     110          46 :         while (fgets (buffer, len, fp))
     111             :         {
     112          26 :                 if (buffer[strlen (buffer) - 1] != '\n')
     113             :                 {
     114           0 :                         fseek (fp, ((len - 1) * (-1)), SEEK_CUR);
     115           0 :                         len *= 2;
     116           0 :                         elektraRealloc ((void **) &buffer, len * sizeof (char));
     117           0 :                         continue;
     118             :                 }
     119             :                 else
     120             :                 {
     121          26 :                         buffer[strlen (buffer) - 1] = '\0';
     122             :                 }
     123          26 :                 char * ptr = buffer;
     124          26 :                 ptr = elektraLskip (ptr);
     125          26 :                 if (!strncmp (buffer, "//", 2)) continue;
     126          32 :                 for (PrefType p = PREF; p < PREF_END; ++p)
     127             :                 {
     128          58 :                         if (!strncmp (ptr, function[p], strlen (function[p])))
     129             :                         {
     130          26 :                                 key = prefToKey (parentKey, p, ptr + strlen (function[p]));
     131          26 :                                 ksAppendKey (returned, key);
     132          26 :                                 goto loop_end;
     133             :                         }
     134             :                 }
     135             :         loop_end:
     136          26 :                 continue;
     137             :         }
     138          10 :         elektraFree (buffer);
     139          10 :         fclose (fp);
     140          10 :         return 1; // success
     141             : }
     142             : 
     143          20 : static char * keyNameToPrefName (const char * prefName)
     144             : {
     145          20 :         char * buffer = elektraCalloc (strlen (prefName) + 1);
     146          20 :         char * src = (char *) prefName;
     147          20 :         char * dst = buffer;
     148          20 :         unsigned short flag = 0;
     149         262 :         while (*src)
     150             :         {
     151         222 :                 switch (*src)
     152             :                 {
     153             :                 case '\\':
     154           0 :                         if (flag)
     155             :                         {
     156           0 :                                 *dst++ = *src;
     157           0 :                                 flag = 0;
     158             :                         }
     159             :                         else
     160             :                                 flag = 1;
     161             :                         break;
     162             :                 case '/':
     163          40 :                         *dst++ = '.';
     164          40 :                         break;
     165             :                 default:
     166         182 :                         *dst++ = *src;
     167         182 :                         break;
     168             :                 }
     169         222 :                 ++src;
     170             :         }
     171          20 :         return buffer;
     172             : }
     173             : 
     174             : static inline const char * prefTypToFunction (PrefType pref)
     175             : {
     176          20 :         if (pref >= PREF_END) return NULL;
     177          20 :         return function[pref];
     178             : }
     179             : 
     180             : // returns a string representing the preference value depending on
     181             : // it's type as a quoted string, integer or boolean value
     182             : 
     183          20 : static char * prefArgToString (const Key * key)
     184             : {
     185          20 :         const Key * typeMeta = keyGetMeta (key, "type");
     186          20 :         char * buffer = NULL;
     187          20 :         if (!strcmp (keyString (typeMeta), "boolean"))
     188             :         {
     189           9 :                 buffer = elektraStrDup (keyString (key));
     190             :         }
     191          11 :         else if (!strcmp (keyString (typeMeta), "string"))
     192             :         {
     193           6 :                 ssize_t len = keyGetValueSize (key) + 2; // size of string + leading and trailing '"'
     194           6 :                 buffer = elektraCalloc (len);
     195           6 :                 snprintf (buffer, len, "\"%s\"", keyString (key));
     196             :         }
     197           5 :         else if (!strcmp (keyString (typeMeta), "integer"))
     198             :         {
     199           5 :                 buffer = elektraStrDup (keyString (key));
     200             :         }
     201             :         else
     202             :         {
     203           0 :                 ssize_t len = keyGetValueSize (key) + 2;
     204           0 :                 buffer = elektraCalloc (len);
     205           0 :                 snprintf (buffer, len, "\"%s\"", keyString (key));
     206             :         }
     207          20 :         return buffer;
     208             : }
     209             : 
     210          20 : static void writeKey (FILE * fp, const Key * parentKey, const Key * key)
     211             : {
     212          20 :         char * prefName = (char *) keyName (key) + strlen (keyName (parentKey)) + 1; // skip parentKey name + '/'
     213          20 :         unsigned short flag = 0;
     214          20 :         PrefType pref = PREF;
     215          46 :         for (; pref < PREF_END; ++pref)
     216             :         {
     217          46 :                 if (!strncmp (prefName, prefix[pref], strlen (prefix[pref])))
     218             :                 {
     219          20 :                         flag = 1;
     220          20 :                         prefName += strlen (prefix[pref]) + 1; // skip prefix len + '/'
     221          20 :                         break;
     222             :                 }
     223             :         }
     224          20 :         if (!flag) return;
     225             : 
     226          20 :         char * realPrefName = keyNameToPrefName (prefName);
     227          20 :         if (!realPrefName) return;
     228          20 :         const char * functionName = prefTypToFunction (pref);
     229          20 :         char * argString = NULL;
     230          20 :         if (!functionName) goto write_cleanup;
     231          20 :         argString = prefArgToString (key);
     232          20 :         if (!argString) goto write_cleanup;
     233          20 :         fprintf (fp, "%s(\"%s\", %s);\n", functionName, realPrefName, argString);
     234             : write_cleanup:
     235          20 :         if (realPrefName) elektraFree (realPrefName);
     236          20 :         if (argString) elektraFree (argString);
     237             : }
     238             : 
     239           8 : int elektraMozprefsSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
     240             : {
     241             :         // get all keys
     242             :         // this function is optional
     243             : 
     244           8 :         FILE * fp = fopen (keyString (parentKey), "w");
     245           8 :         if (!fp) return -1;
     246             :         Key * cur;
     247          28 :         while ((cur = ksNext (returned)) != NULL)
     248             :         {
     249          20 :                 if (!strcmp (keyName (parentKey), keyName (cur))) continue;
     250          20 :                 writeKey (fp, parentKey, cur);
     251             :         }
     252           8 :         fclose (fp);
     253           8 :         return 1; // success
     254             : }
     255             : 
     256          75 : Plugin * ELEKTRA_PLUGIN_EXPORT
     257             : {
     258             :         // clang-format off
     259          75 :         return elektraPluginExport ("mozprefs",
     260             :                         ELEKTRA_PLUGIN_GET,     &elektraMozprefsGet,
     261             :                         ELEKTRA_PLUGIN_SET,     &elektraMozprefsSet,
     262             :                         ELEKTRA_PLUGIN_END);
     263             : }
     264             : 

Generated by: LCOV version 1.13