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 :
|