1 /*
2 * Copyright (c) 2011-2014 LEVAI Daniel
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25
26 #include "common.h"
27 #include "commands.h"
28
29
30 char swap_keys(xmlNodePtr *, xmlNodePtr *);
31
32
33 extern db_parameters db_params;
34 extern xmlNodePtr keychain;
35
36
37 void
cmd_swap(const char * e_line,command * commands)38 cmd_swap(const char *e_line, command *commands)
39 {
40 xmlNodePtr key_src = NULL, key_dst = NULL, key_finish = NULL;
41
42 char *modified = NULL;
43 char insert = 0;
44 char *line = NULL, *cmd = NULL, *inv = NULL;
45 unsigned long int idx_src = 0, idx_dst = 0;
46
47
48 line = strdup(e_line); malloc_check(line);
49
50
51 cmd = strtok(line, " "); /* command name */
52 if (!cmd) {
53 puts(commands->usage);
54
55 free(line); line = NULL;
56 return;
57 }
58
59 if (strcmp(cmd, "insert") == 0)
60 insert = 1;
61
62
63 cmd = strtok(NULL, " "); /* first parameter, the source index number */
64 if (!cmd) {
65 puts(commands->usage);
66
67 free(line); line = NULL;
68 return;
69 }
70
71 errno = 0;
72 idx_src = strtoul((const char *)cmd, &inv, 10);
73 if (inv[0] != '\0' || errno != 0 || cmd[0] == '-') {
74 puts(commands->usage);
75
76 free(line); line = NULL;
77 return;
78 }
79
80
81 cmd = strtok(NULL, " "); /* second parameter, the destination index number */
82 if (!cmd) {
83 puts(commands->usage);
84
85 free(line); line = NULL;
86 return;
87 }
88
89 errno = 0;
90 idx_dst = strtoul((const char *)cmd, &inv, 10);
91 if (inv[0] != '\0' || errno != 0 || cmd[0] == '-') {
92 puts(commands->usage);
93
94 free(line); line = NULL;
95 return;
96 }
97
98
99 free(line); line = NULL;
100
101
102 /* No funny stuff!!! :) */
103 if (idx_src == idx_dst) {
104 puts("The two indices are the same!");
105 return;
106 }
107
108 key_src = find_key(idx_src);
109 if (!key_src) {
110 puts("Invalid source index!");
111 return;
112 }
113 key_dst = find_key(idx_dst);
114 if (!key_dst) {
115 puts("Invalid destination index!");
116 return;
117 }
118
119
120 if (!swap_keys(&key_src, &key_dst)) {
121 if (insert)
122 puts("Error while preparing to insert key!");
123 else
124 puts("Error while trying to swap keys!");
125
126 return;
127 }
128
129
130 if (insert) {
131 /* Inserting is basically swapping the two indices, then shift the surrounding indices ...
132 *
133 * if (idx_src > idx_dst)
134 * ... from the bottom to the top
135 *
136 * if (idx_src < idx_dst)
137 * ... from the top to the bottom
138 */
139
140 key_finish = key_src;
141 key_src = key_dst;
142
143 /* We skip one node; it's the text node for formatting */
144 if (idx_src > idx_dst)
145 key_dst = key_src->prev->prev;
146 else
147 key_dst = key_src->next->next;
148
149 while (key_dst) {
150 /* finish */
151 if (key_dst == key_finish)
152 break;
153
154 if (key_dst->type != XML_ELEMENT_NODE) {
155 puts("Error while trying to insert key! Please check your key list and reload your database without saving, if necessary!");
156 if (getenv("KC_DEBUG"))
157 puts("key_dst is non-element node!");
158
159 return;
160 }
161
162 if (!swap_keys(&key_src, &key_dst)) {
163 puts("Error while trying to insert key! Please check your key list and reload your database without saving, if necessary!");
164 if (getenv("KC_DEBUG"))
165 puts("swap_key() error while shifting nodes!");
166
167 return;
168 }
169
170 if (idx_src > idx_dst)
171 key_dst = key_src->prev->prev;
172 else
173 key_dst = key_src->next->next;
174 }
175 }
176
177 /* Update the current keychain's modified timestamp */
178 modified = malloc(TIME_MAXLEN); malloc_check(modified);
179 snprintf(modified, TIME_MAXLEN, "%d", (int)time(NULL));
180
181 xmlSetProp(keychain, BAD_CAST "modified", BAD_CAST modified);
182
183 free(modified); modified = NULL;
184
185 if (insert)
186 printf("Key %lu was inserted at %lu\n", idx_src, idx_dst);
187 else
188 printf("Key %lu was swapped with %lu\n", idx_src, idx_dst);
189
190 puts("Key indices may have been changed. Make sure to 'list', before using them again!");
191
192 db_params.dirty = 1;
193 } /* cmd_swap() */
194
195
196 char
swap_keys(xmlNodePtr * key_src,xmlNodePtr * key_dst)197 swap_keys(xmlNodePtr *key_src, xmlNodePtr *key_dst)
198 {
199 xmlNodePtr key_tmp_src = NULL, key_tmp_dst = NULL;
200
201
202 /* duplicate the source key */
203 key_tmp_src = xmlCopyNode(*key_src, 2);
204 if (!key_tmp_src) {
205 puts("Error duplicating source entry!");
206
207 if (getenv("KC_DEBUG"))
208 puts("xmlCopyNode() error!");
209
210 return(0);
211 }
212
213 /* duplicate the destination key */
214 key_tmp_dst = xmlCopyNode(*key_dst, 2);
215 if (!key_tmp_dst) {
216 puts("Error duplicating destination entry!");
217
218 if (getenv("KC_DEBUG"))
219 puts("xmlCopyNode() error!");
220
221 return(0);
222 }
223
224
225 /* We need two key_tmp_* variables, because xmlReplaceNode() unlinks both its parameters */
226 xmlReplaceNode(*key_src, key_tmp_dst);
227 xmlFreeNode(*key_src);
228
229 xmlReplaceNode(*key_dst, key_tmp_src);
230 xmlFreeNode(*key_dst);
231
232 *key_src = key_tmp_src; /* the original "source" index */
233 *key_dst = key_tmp_dst; /* the original "destination" index */
234
235 return(1);
236 } /* swap_keys() */
237