r10913: This patch isn't as big as it looks ...
[kamenim/samba.git] / source4 / lib / ldb / modules / timestamps.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb timestamps module
29  *
30  *  Description: add object timestamping functionality
31  *
32  *  Author: Simo Sorce
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include <time.h>
39
40 static int timestamps_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
41                                     enum ldb_scope scope, struct ldb_parse_tree *tree,
42                                     const char * const *attrs, struct ldb_message ***res)
43 {
44         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n");
45         return ldb_next_search_bytree(module, base, scope, tree, attrs, res);
46 }
47
48 static int add_time_element(struct ldb_module *module, struct ldb_message *msg, 
49                             const char *attr_name, const char *time_string, unsigned int flags)
50 {
51         struct ldb_message_element *attribute = NULL;
52
53         int i;
54
55         for (i = 0; i < msg->num_elements; i++) {
56                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
57                         return 0;
58                 }
59         }
60
61         if (ldb_msg_add_string(msg, attr_name, time_string) != 0) {
62                 return -1;
63         }
64
65         for (i = 0; i < msg->num_elements; i++) {
66                 if (ldb_attr_cmp(attr_name, msg->elements[i].name) == 0) {
67                         attribute = &msg->elements[i];
68                         break;
69                 }
70         }
71
72         if (!attribute) {
73                 return -1;
74         }
75
76         attribute->flags = flags;
77
78         return 0;
79 }
80
81 /* add_record: add crateTimestamp/modifyTimestamp attributes */
82 static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg)
83 {
84         struct ldb_message *msg2 = NULL;
85         struct tm *tm;
86         char *timestr;
87         time_t timeval;
88         int ret, i;
89
90         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n");
91
92         /* do not manipulate our control entries */
93         if (ldb_dn_is_special(msg->dn)) {
94                 return ldb_next_add_record(module, msg);
95         }
96
97         timeval = time(NULL);
98         tm = gmtime(&timeval);
99         if (!tm) {
100                 return -1;
101         }
102
103         msg2 = talloc(module, struct ldb_message);
104         if (!msg2) {
105                 return -1;
106         }
107
108         /* formatted like: 20040408072012.0Z */
109         timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z",
110                                   tm->tm_year+1900, tm->tm_mon+1,
111                                   tm->tm_mday, tm->tm_hour, tm->tm_min,
112                                   tm->tm_sec);
113         if (!timestr) {
114                 return -1;
115         }
116
117         msg2->dn = msg->dn;
118         msg2->num_elements = msg->num_elements;
119         msg2->private_data = msg->private_data;
120         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
121         for (i = 0; i < msg2->num_elements; i++) {
122                 msg2->elements[i] = msg->elements[i];
123         }
124
125         add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD);
126         add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD);
127         add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD);
128         add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD);
129
130         if (msg2) {
131                 ret = ldb_next_add_record(module, msg2);
132                 talloc_free(msg2);
133         } else {
134                 ret = ldb_next_add_record(module, msg);
135         }
136
137         return ret;
138 }
139
140 /* modify_record: change modifyTimestamp as well */
141 static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg)
142 {
143         struct ldb_message *msg2 = NULL;
144         struct tm *tm;
145         char *timestr;
146         time_t timeval;
147         int ret, i;
148
149         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n");
150
151         /* do not manipulate our control entries */
152         if (ldb_dn_is_special(msg->dn)) {
153                 return ldb_next_modify_record(module, msg);
154         }
155
156         timeval = time(NULL);
157         tm = gmtime(&timeval);
158         if (!tm) {
159                 return -1;
160         }
161
162         msg2 = talloc(module, struct ldb_message);
163         if (!msg2) {
164                 return -1;
165         }
166
167         /* formatted like: 20040408072012.0Z */
168         timestr = talloc_asprintf(msg2, 
169                                 "%04u%02u%02u%02u%02u%02u.0Z",
170                                 tm->tm_year+1900, tm->tm_mon+1,
171                                 tm->tm_mday, tm->tm_hour, tm->tm_min,
172                                 tm->tm_sec);
173         if (!timestr) {
174                 return -1;
175         }
176
177         msg2->dn = msg->dn;
178         msg2->num_elements = msg->num_elements;
179         msg2->private_data = msg->private_data;
180         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
181         for (i = 0; i < msg2->num_elements; i++) {
182                 msg2->elements[i] = msg->elements[i];
183         }
184
185         add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE);
186         add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE);
187
188         ret = ldb_next_modify_record(module, msg2);
189         talloc_free(msg2);
190
191         return ret;
192 }
193
194
195 static const struct ldb_module_ops timestamps_ops = {
196         .name              = "timestamps",
197         .search_bytree     = timestamps_search_bytree,
198         .add_record        = timestamps_add_record,
199         .modify_record     = timestamps_modify_record
200 };
201
202
203 /* the init function */
204 #ifdef HAVE_DLOPEN_DISABLED
205  struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
206 #else
207 struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[])
208 #endif
209 {
210         struct ldb_module *ctx;
211
212         ctx = talloc(ldb, struct ldb_module);
213         if (!ctx)
214                 return NULL;
215
216         ctx->private_data = NULL;
217         ctx->ldb = ldb;
218         ctx->prev = ctx->next = NULL;
219         ctx->ops = &timestamps_ops;
220
221         return ctx;
222 }