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 : #ifndef HAVE_KDBCONFIG
10 : #include "kdbconfig.h"
11 : #endif
12 :
13 : #include <ctype.h>
14 : #include <stdio.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 :
18 : #include "validation.h"
19 :
20 : static int validateKey (Key *, Key *);
21 :
22 61 : int elektraValidationGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey ELEKTRA_UNUSED)
23 : {
24 : KeySet * n;
25 61 : ksAppend (returned,
26 61 : n = ksNew (30,
27 : keyNew ("system/elektra/modules/validation", KEY_VALUE, "validation plugin waits for your orders", KEY_END),
28 : keyNew ("system/elektra/modules/validation/exports", KEY_END),
29 : keyNew ("system/elektra/modules/validation/exports/get", KEY_FUNC, elektraValidationGet, KEY_END),
30 : keyNew ("system/elektra/modules/validation/exports/set", KEY_FUNC, elektraValidationSet, KEY_END),
31 : keyNew ("system/elektra/modules/validation/exports/ksLookupRE", KEY_FUNC, ksLookupRE, KEY_END),
32 : keyNew ("system/elektra/modules/validation/exports/validateKey", KEY_FUNC, validateKey, KEY_END),
33 : #include "readme_validation.c"
34 : keyNew ("system/elektra/modules/validation/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END));
35 61 : ksDel (n);
36 61 : return 1;
37 : }
38 :
39 36 : static int validateKey (Key * key, Key * parentKey)
40 : {
41 36 : const Key * regexMeta = keyGetMeta (key, "check/validation");
42 :
43 36 : const Key * icaseMeta = keyGetMeta (key, "check/validation/ignorecase");
44 36 : const Key * matchMeta = keyGetMeta (key, "check/validation/match");
45 36 : const Key * invertMeta = keyGetMeta (key, "check/validation/invert");
46 36 : const Key * typeMeta = keyGetMeta (key, "check/validation/type");
47 :
48 36 : int lineValidation = 0;
49 36 : int wordValidation = 0;
50 36 : int icaseValidation = 0;
51 36 : int invertValidation = 0;
52 :
53 36 : if (icaseMeta) icaseValidation = 1;
54 36 : if (invertMeta) invertValidation = 1;
55 36 : if (matchMeta)
56 : {
57 32 : char * matchCopy = elektraStrDup (keyString (matchMeta));
58 32 : char * ptr = matchCopy;
59 192 : while (*ptr)
60 : {
61 128 : *ptr = toupper (*ptr);
62 128 : ++ptr;
63 : }
64 32 : if (!strcmp (matchCopy, "LINE")) lineValidation = 1;
65 32 : if (!strcmp (matchCopy, "WORD")) wordValidation = 1;
66 32 : if (!strcmp (matchCopy, "ANY"))
67 : {
68 0 : lineValidation = 0;
69 0 : wordValidation = 0;
70 : }
71 32 : elektraFree (matchCopy);
72 : }
73 :
74 36 : int cflags = REG_NOSUB | REG_EXTENDED;
75 36 : if (icaseValidation) cflags |= REG_ICASE;
76 36 : if (lineValidation) cflags |= REG_NEWLINE;
77 36 : if (typeMeta)
78 : {
79 0 : char * typeCopy = elektraStrDup (keyString (typeMeta));
80 0 : char * ptr = typeCopy;
81 0 : while (*ptr)
82 : {
83 0 : *ptr = toupper (*ptr);
84 0 : ++ptr;
85 : }
86 0 : if (!strcmp (typeCopy, "ERE"))
87 0 : cflags |= REG_EXTENDED;
88 0 : else if (!strcmp (typeCopy, "BRE"))
89 0 : cflags &= REG_EXTENDED;
90 0 : elektraFree (typeCopy);
91 : }
92 :
93 36 : char * regexString = NULL;
94 36 : int freeString = 0;
95 36 : if (lineValidation || wordValidation)
96 : {
97 32 : regexString = elektraMalloc (keyGetValueSize (regexMeta) + 2);
98 32 : freeString = 1;
99 32 : sprintf (regexString, "^%s$", keyString (regexMeta));
100 : }
101 : else
102 : {
103 4 : regexString = (char *) keyString (regexMeta);
104 : }
105 :
106 : regex_t regex;
107 : regmatch_t offsets;
108 36 : int ret = regcomp (®ex, regexString, cflags);
109 :
110 36 : if (ret != 0)
111 : {
112 : char buffer[1000];
113 0 : regerror (ret, ®ex, buffer, 999);
114 0 : ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (parentKey, "Could not compile regex. Reason: %s", buffer);
115 0 : regfree (®ex);
116 0 : if (freeString) elektraFree (regexString);
117 : return 0;
118 : }
119 36 : int match = 0;
120 36 : if (!wordValidation)
121 : {
122 20 : ret = regexec (®ex, keyString (key), 1, &offsets, 0);
123 20 : if (ret == 0) match = 1;
124 : }
125 : else
126 : {
127 : char * savePtr;
128 : char * token;
129 16 : char * string = (char *) keyString (key);
130 52 : while ((token = strtok_r (string, " \t\n", &savePtr)) != NULL)
131 : {
132 28 : ret = regexec (®ex, token, 1, &offsets, 0);
133 28 : if (ret == 0)
134 : {
135 : match = 1;
136 : break;
137 : }
138 : string = NULL;
139 : }
140 : }
141 36 : if (invertValidation) match = !match;
142 :
143 36 : if (!match)
144 : {
145 14 : const Key * msg = keyGetMeta (key, "check/validation/message");
146 14 : if (msg)
147 : {
148 2 : ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (parentKey, "Key value failed to validate. Reason: %s", keyString (msg));
149 2 : regfree (®ex);
150 2 : if (freeString) elektraFree (regexString);
151 : return 0;
152 : }
153 : else
154 : {
155 : char buffer[1000];
156 12 : regerror (ret, ®ex, buffer, 999);
157 12 : ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (parentKey, "Key value failed to validate. Reason: %s", buffer);
158 12 : regfree (®ex);
159 12 : if (freeString) elektraFree (regexString);
160 : return 0;
161 : }
162 : }
163 :
164 22 : regfree (®ex);
165 22 : if (freeString) elektraFree (regexString);
166 : return 1;
167 : }
168 :
169 37 : int elektraValidationSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
170 : {
171 37 : Key * cur = 0;
172 :
173 97 : while ((cur = ksNext (returned)) != 0)
174 : {
175 37 : const Key * regexMeta = keyGetMeta (cur, "check/validation");
176 :
177 37 : if (!regexMeta) continue;
178 36 : int rc = validateKey (cur, parentKey);
179 36 : if (!rc) return -1;
180 : }
181 :
182 : return 1; /* success */
183 : }
184 :
185 161 : Plugin * ELEKTRA_PLUGIN_EXPORT
186 : {
187 : // clang-format off
188 161 : return elektraPluginExport("validation",
189 : ELEKTRA_PLUGIN_GET, &elektraValidationGet,
190 : ELEKTRA_PLUGIN_SET, &elektraValidationSet,
191 : ELEKTRA_PLUGIN_END);
192 : }
193 :
|