LCOV - code coverage report
Current view: top level - src/plugins/hexcode - hexcode.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 96 115 83.5 %
Date: 2019-09-12 12:28:41 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "hexcode.h"
      10             : 
      11             : #ifndef HAVE_KDBCONFIG
      12             : #include "kdbconfig.h"
      13             : #endif
      14             : 
      15             : #include <kdbhelper.h>
      16             : 
      17             : #include <stdlib.h>
      18             : #include <string.h>
      19             : 
      20             : /**
      21             :  * Gives the integer number 0-15 to a corresponding
      22             :  * hex character '0'-'9', 'a'-'f' or 'A'-'F'.
      23             :  */
      24         120 : static inline int elektraHexcodeConvFromHex (char c)
      25             : {
      26         120 :         if (c == '0')
      27             :                 return 0;
      28          92 :         else if (c == '1')
      29             :                 return 1;
      30          92 :         else if (c == '2')
      31             :                 return 2;
      32          62 :         else if (c == '3')
      33             :                 return 3;
      34          38 :         else if (c == '4')
      35             :                 return 4;
      36          38 :         else if (c == '5')
      37             :                 return 5;
      38          30 :         else if (c == '6')
      39             :                 return 6;
      40          30 :         else if (c == '7')
      41             :                 return 7;
      42          30 :         else if (c == '8')
      43             :                 return 8;
      44          30 :         else if (c == '9')
      45             :                 return 9;
      46          30 :         else if (c == 'a' || c == 'A')
      47             :                 return 10;
      48          24 :         else if (c == 'b' || c == 'B')
      49             :                 return 11;
      50          16 :         else if (c == 'c' || c == 'C')
      51             :                 return 12;
      52           8 :         else if (c == 'd' || c == 'D')
      53             :                 return 13;
      54           0 :         else if (c == 'e' || c == 'E')
      55             :                 return 14;
      56           0 :         else if (c == 'f' || c == 'F')
      57             :                 return 15;
      58             :         else
      59           0 :                 return 0; /* Unknown escape char */
      60             : }
      61             : 
      62             : /** Reads the value of the key and decodes all escaping
      63             :  * codes into the buffer.
      64             :  * @pre the buffer needs to be as large as value's size.
      65             :  * @param cur the key holding the value to decode
      66             :  * @param buf the buffer to write to
      67             :  */
      68          24 : void elektraHexcodeDecode (Key * cur, CHexData * hd)
      69             : {
      70          24 :         size_t valsize = keyGetValueSize (cur);
      71          24 :         const char * val = keyValue (cur);
      72             : 
      73          24 :         if (!val) return;
      74             : 
      75             :         size_t out = 0;
      76         144 :         for (size_t in = 0; in < valsize - 1; ++in)
      77             :         {
      78         144 :                 char c = val[in];
      79         144 :                 char * n = hd->buf + out;
      80             : 
      81         144 :                 if (c == hd->escape)
      82             :                 {
      83          50 :                         in += 2; /* Advance twice (2 hex numbers) */
      84          50 :                         char first = val[in - 1];
      85          50 :                         char second = val[in];
      86             :                         int res;
      87             : 
      88          50 :                         res = elektraHexcodeConvFromHex (second);
      89          50 :                         res += elektraHexcodeConvFromHex (first) * 16;
      90          50 :                         *n = res & 255;
      91             :                 }
      92             :                 else
      93             :                 {
      94          94 :                         *n = c;
      95             :                 }
      96         144 :                 ++out; /* Only one char is written */
      97             :         }
      98             : 
      99          24 :         hd->buf[out] = 0; // null termination for keyString()
     100             : 
     101          24 :         keySetRaw (cur, hd->buf, out + 1);
     102             : }
     103             : 
     104             : 
     105          20 : int elektraHexcodeGet (Plugin * handle, KeySet * returned, Key * parentKey)
     106             : {
     107             :         /* get all keys */
     108             : 
     109          20 :         if (!strcmp (keyName (parentKey), "system/elektra/modules/hexcode"))
     110             :         {
     111          20 :                 KeySet * pluginConfig =
     112          20 :                         ksNew (30, keyNew ("system/elektra/modules/hexcode", KEY_VALUE, "hexcode plugin waits for your orders", KEY_END),
     113             :                                keyNew ("system/elektra/modules/hexcode/exports", KEY_END),
     114             :                                keyNew ("system/elektra/modules/hexcode/exports/get", KEY_FUNC, elektraHexcodeGet, KEY_END),
     115             :                                keyNew ("system/elektra/modules/hexcode/exports/set", KEY_FUNC, elektraHexcodeSet, KEY_END),
     116             :                                keyNew ("system/elektra/modules/hexcode/exports/open", KEY_FUNC, elektraHexcodeOpen, KEY_END),
     117             :                                keyNew ("system/elektra/modules/hexcode/exports/close", KEY_FUNC, elektraHexcodeClose, KEY_END),
     118             : #include "readme_hexcode.c"
     119             :                                keyNew ("system/elektra/modules/hexcode/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
     120          20 :                 ksAppend (returned, pluginConfig);
     121          20 :                 ksDel (pluginConfig);
     122          20 :                 return 1;
     123             :         }
     124             : 
     125           0 :         CHexData * hd = elektraPluginGetData (handle);
     126           0 :         if (!hd->buf)
     127             :         {
     128           0 :                 hd->buf = elektraMalloc (1000);
     129           0 :                 hd->bufalloc = 1000;
     130             :         }
     131             : 
     132             :         Key * cur;
     133           0 :         ksRewind (returned);
     134           0 :         while ((cur = ksNext (returned)) != 0)
     135             :         {
     136           0 :                 size_t valsize = keyGetValueSize (cur);
     137           0 :                 if (valsize > hd->bufalloc)
     138             :                 {
     139           0 :                         hd->bufalloc = valsize;
     140           0 :                         hd->buf = realloc (hd->buf, hd->bufalloc);
     141             :                 }
     142             : 
     143           0 :                 elektraHexcodeDecode (cur, hd);
     144             :         }
     145             : 
     146             :         return 1; /* success */
     147             : }
     148             : 
     149             : 
     150             : /**
     151             :  * Gives the integer number 0-15 to a corresponding
     152             :  * hex character '0'-'9', 'a'-'f' or 'A'-'F'.
     153             :  */
     154             : static inline char elektraHexcodeConvToHex (int c)
     155             : {
     156         136 :         switch (c)
     157             :         {
     158             :         case 0:
     159             :                 return '0';
     160             :         case 1:
     161             :                 return '1';
     162             :         case 2:
     163             :                 return '2';
     164             :         case 3:
     165             :                 return '3';
     166             :         case 4:
     167             :                 return '4';
     168             :         case 5:
     169             :                 return '5';
     170             :         case 6:
     171             :                 return '6';
     172             :         case 7:
     173             :                 return '7';
     174             :         case 8:
     175             :                 return '8';
     176             :         case 9:
     177             :                 return '9';
     178             :         case 10:
     179             :                 return 'A';
     180             :         case 11:
     181             :                 return 'B';
     182             :         case 12:
     183             :                 return 'C';
     184             :         case 13:
     185             :                 return 'D';
     186             :         case 14:
     187             :                 return 'E';
     188             :         case 15:
     189             :                 return 'F';
     190             :         default:
     191             :                 return '0';
     192             :         }
     193             : }
     194             : 
     195             : 
     196             : /** Reads the value of the key and encodes it in
     197             :  * c-style in the buffer.
     198             :  *
     199             :  * @param cur the key which value is to encode
     200             :  * @param buf the buffer
     201             :  * @pre the buffer needs to have thrice as much space as the value's size
     202             :  */
     203          26 : void elektraHexcodeEncode (Key * cur, CHexData * hd)
     204             : {
     205          26 :         size_t valsize = keyGetValueSize (cur);
     206          26 :         const char * val = keyValue (cur);
     207             : 
     208          26 :         if (!val) return;
     209             : 
     210             :         size_t out = 0;
     211         200 :         for (size_t in = 0; in < valsize - 1; ++in)
     212             :         {
     213         200 :                 unsigned char c = val[in];
     214             : 
     215             :                 // need to encode char?
     216         200 :                 if (hd->hd[c & 255])
     217             :                 {
     218          68 :                         hd->buf[out] = hd->escape;
     219          68 :                         out++;
     220         136 :                         hd->buf[out] = elektraHexcodeConvToHex (c / 16);
     221          68 :                         out++;
     222         136 :                         hd->buf[out] = elektraHexcodeConvToHex (c % 16);
     223          68 :                         out++;
     224             :                 }
     225             :                 else
     226             :                 {
     227             :                         // just copy one character
     228         132 :                         hd->buf[out] = val[in];
     229             :                         // advance out cursor
     230         132 :                         out++;
     231             :                 }
     232             :         }
     233             : 
     234          26 :         hd->buf[out] = 0; // null termination for keyString()
     235             : 
     236          26 :         keySetRaw (cur, hd->buf, out + 1);
     237             : }
     238             : 
     239             : 
     240           2 : int elektraHexcodeSet (Plugin * handle, KeySet * returned, Key * parentKey ELEKTRA_UNUSED)
     241             : {
     242             :         /* set all keys */
     243           2 :         CHexData * hd = elektraPluginGetData (handle);
     244           2 :         if (!hd->buf)
     245             :         {
     246           2 :                 hd->buf = elektraMalloc (1000);
     247           2 :                 hd->bufalloc = 1000;
     248             :         }
     249             : 
     250             :         Key * cur;
     251           2 :         ksRewind (returned);
     252           6 :         while ((cur = ksNext (returned)) != 0)
     253             :         {
     254           2 :                 size_t valsize = keyGetValueSize (cur);
     255           2 :                 if (valsize * 3 > hd->bufalloc)
     256             :                 {
     257           0 :                         hd->bufalloc = valsize * 3;
     258           0 :                         hd->buf = realloc (hd->buf, hd->bufalloc);
     259             :                 }
     260             : 
     261           2 :                 elektraHexcodeEncode (cur, hd);
     262             :         }
     263             : 
     264           2 :         return 1; /* success */
     265             : }
     266             : 
     267          22 : int elektraHexcodeOpen (Plugin * handle, Key * key ELEKTRA_UNUSED)
     268             : {
     269          22 :         CHexData * hd = calloc (1, sizeof (CHexData));
     270             : 
     271             :         /* Store for later use...*/
     272          22 :         elektraPluginSetData (handle, hd);
     273             : 
     274          22 :         KeySet * config = elektraPluginGetConfig (handle);
     275             : 
     276          22 :         Key * escape = ksLookupByName (config, "/escape", 0);
     277          22 :         hd->escape = '\\';
     278          22 :         if (escape && keyGetBaseNameSize (escape) && keyGetValueSize (escape) == 3)
     279             :         {
     280             :                 int res;
     281           0 :                 res = elektraHexcodeConvFromHex (keyString (escape)[1]);
     282           0 :                 res += elektraHexcodeConvFromHex (keyString (escape)[0]) * 16;
     283             : 
     284           0 :                 hd->escape = res & 255;
     285             :         }
     286             : 
     287          22 :         Key * root = ksLookupByName (config, "/chars", 0);
     288          22 :         if (!root)
     289             :         {
     290             :                 /* Some default config */
     291          20 :                 hd->hd['\0'] = 1;
     292          20 :                 hd->hd['\n'] = 1;
     293          20 :                 hd->hd['\\'] = 1;
     294          20 :                 hd->hd[' '] = 1;
     295             :         }
     296             :         else
     297             :         {
     298             :                 Key * cur = 0;
     299          12 :                 while ((cur = ksNext (config)) != 0)
     300             :                 {
     301             :                         /* ignore all keys not direct below */
     302          10 :                         if (keyRel (root, cur) == 1)
     303             :                         {
     304             :                                 /* ignore invalid size */
     305          10 :                                 if (keyGetBaseNameSize (cur) != 3) continue;
     306             : 
     307             :                                 int res;
     308          10 :                                 res = elektraHexcodeConvFromHex (keyBaseName (cur)[1]);
     309          10 :                                 res += elektraHexcodeConvFromHex (keyBaseName (cur)[0]) * 16;
     310             : 
     311             :                                 /* Hexencode this character! */
     312          10 :                                 hd->hd[res & 255] = 1;
     313             :                         }
     314             :                 }
     315             :         }
     316             : 
     317          22 :         return 0;
     318             : }
     319             : 
     320          22 : int elektraHexcodeClose (Plugin * handle, Key * key ELEKTRA_UNUSED)
     321             : {
     322          22 :         CHexData * hd = elektraPluginGetData (handle);
     323             : 
     324          22 :         elektraFree (hd->buf);
     325          22 :         elektraFree (hd);
     326             : 
     327          22 :         return 0;
     328             : }
     329             : 
     330          20 : Plugin * ELEKTRA_PLUGIN_EXPORT
     331             : {
     332             :         // clang-format off
     333          20 :         return elektraPluginExport("hexcode",
     334             :                 ELEKTRA_PLUGIN_GET,     &elektraHexcodeGet,
     335             :                 ELEKTRA_PLUGIN_SET,     &elektraHexcodeSet,
     336             :                 ELEKTRA_PLUGIN_OPEN,    &elektraHexcodeOpen,
     337             :                 ELEKTRA_PLUGIN_CLOSE,   &elektraHexcodeClose,
     338             :                 ELEKTRA_PLUGIN_END);
     339             : }
     340             : 

Generated by: LCOV version 1.13