2 /* -}{----------------------------------------------------------------------- */
7 #include <notification.h>
9 /* -}{---- ------------------------------------------------------------------ */
11 EXPORT void n_register_driver(char* name,
12 n_handles_object handles_object,
13 n_view_event view_event,
14 n_cast_event cast_event,
15 n_sync_object sync_object )
19 EXPORT n_object* n_object_new(char* s)
24 EXPORT void n_commit(n_object* o)
28 EXPORT n_object* n_view(n_object* o, char* uid)
33 EXPORT void n_open(n_object* o, char* uid, char* options)
37 EXPORT char* n_to_string(n_object* o)
42 EXPORT char* n_uid(n_object* o)
47 EXPORT int n_uid_is(n_object* o, char* uid)
52 EXPORT char* n_header(n_object* o, char* name)
57 EXPORT k_hashtable* n_headers(n_object* o)
62 EXPORT k_hashtable* n_content(n_object* o)
67 EXPORT void n_dispatch(n_event* event)
69 /* one callback per view or cast */
70 /* must delete the event */
73 /* -}{---- ------------------------------------------------------------------ */
75 #define TMPBUFSIZE 4096
76 static char tmpbuf[TMPBUFSIZE];
77 static char* hostname;
78 static k_hashtable* resources;
80 /* -}{---- ------------------------------------------------------------------ */
82 typedef struct ni_driver{
84 ni_handles_resource handles_resource;
85 ni_sync_resource sync_resource;
88 /* -}{---- From headers.c --------------------------------------------------- */
90 extern void init_headers(void);
91 extern void drop_entity_headers(k_hashtable* ent_head);
92 extern void fill_headers(k_hashtable* ent_head,
102 /* -}{---- ------------------------------------------------------------------ */
104 static void incoming_request(ni_event* evq);
105 static ni_resource* ensure_res(char* pub);
106 static void ensure_sub_entry(k_hashtable* ent_head, k_hashtable* sub);
107 static void ensure_pub_entry(k_hashtable* ent_head, k_hashtable* sub);
108 static k_hashtable* get_this(k_hashtable*, char*, k_hashtable*);
109 static k_hashtable* get_using(k_hashtable* curr, char* tag, char* val);
110 static void post_to_driver(char* pub, ni_event* evq);
111 static void incoming_resource(ni_event* evt);
112 static void test_pub_tos(ni_resource* res, ni_event* evt, int entityok);
113 static int satisfiable(k_hashtable*, ni_resource*, ni_event*, int);
114 static void update_pubcache(int, k_hashtable**, k_hashtable*, k_hashtable*);
115 static int sub_less(k_hashtable* sub1, k_hashtable* sub2);
116 static void fix_via_subs(k_hashtable* evteh, k_hashtable* reseh);
117 static int sub_ok(k_hashtable* sub);
118 static int range_ok(char* range, char* conrange);
119 static void merge_non_entity_headers(k_hashtable* reseh, k_hashtable* evteh);
120 static void merge_entity_range(ni_resource* res, ni_event* evt);
121 static void respond( k_hashtable* sub, ni_resource* res, ni_event* evt);
122 static void respond_ok(k_hashtable* sub, ni_event* evv);
123 static void respond_nf(k_hashtable* sub, ni_event* evv);
124 static void* entity_to_octets(k_hashtable* ent_head, void* entity);
125 static char* handled_by(char* pub);
126 static void call_sync_resource(ni_resource* res);
127 static ni_driver* ni_driver_new(char* name,
128 ni_handles_resource handles_resource,
129 ni_sync_resource sync_resource);
131 /* -}{---- ------------------------------------------------------------------ */
133 EXPORT int on_module_loaded(void)
135 resources=k_hashtable_new("Resources", 0);
139 k_log_out("ON initialised");
143 EXPORT void on_module_tick(void)
147 EXPORT int on_module_event(void* data)
151 if(!k_hashtable_get(evt->ent_head, "Status:")){
153 incoming_request(evt);
156 incoming_resource(evt);
161 /* -}{---- ------------------------------------------------------------------ */
163 void incoming_request(ni_event* evq)
166 if(L) ni_event_show(evq, "ON got request event");
168 k_hashtable* sub=evq->ent_head;
169 char* uri =k_hashtable_get(sub, "URI:");
170 char* pub =k_hashtable_get(sub, "Sub-To:"); if(!pub) return;
171 int styor=k_hashtable_isi(sub, "Sub-Type:", "Original");
172 char* via =k_hashtable_get(sub, "Via:");
173 char* from =k_hashtable_get(sub, "From:");
174 if(L) k_log_out("------------------ %s", pub);
176 int nocache=k_hashtable_isi(sub, "Cache-Control:", "no-cache");
178 k_hashtable_remove( sub, "Cache-Control:");
179 k_hashtable_set( sub, "If-Modified-Since:", "0");
183 ni_resource* ses=k_hashtable_get(resources, uri);
184 if(ses) ensure_sub_entry(ses->ent_head, sub);
185 if(ses) if(L) ni_resource_show(ses, "Subscribing Resource:");
187 post_to_driver(pub, evq);
192 ni_resource* res=ensure_res(pub);
193 if(L) ni_resource_show(res, "Publishing Resource:");
195 k_hashtable* pubcache=0;
196 int sat=satisfiable(sub, res, 0, 0);
197 update_pubcache(sat, &pubcache, res->ent_head, sub);
199 if(L) k_log_out("Memory cache hit for %s", pub);
200 respond(k_hashtable_dup(sub), res, 0);
201 ni_event_delete(evq);
204 ensure_pub_entry(res->ent_head, sub);
205 if(L) ni_resource_show(res, "Pending Resource:");
207 evq->ent_head=pubcache;
208 post_to_driver(pub, evq);
209 k_hashtable_delete(sub);
212 if(L) k_log_out("In-progress Pub-Cache sufficient");
213 ni_event_delete(evq);
218 ni_resource* ensure_res(char* pub)
220 ni_resource* res=k_hashtable_get(resources, pub);
222 res=ni_resource_new(pub, k_hashtable_new("resHeaders", 1), 0);
223 k_hashtable_set(resources, pub, res);
228 void ensure_sub_entry(k_hashtable* ent_head, k_hashtable* sub)
231 k_hashtable* sup=get_this(ent_head, tag, sub);
233 k_hashtable* sup=k_hashtable_dup(sub);
234 char* uri=k_hashtable_extract(sup, "Sub-To:");
235 k_hashtable_put( sup, "URI:", uri);
236 k_hashtable_remove( sup, "Sub-Type:");
237 k_hashtable_sub(ent_head, tag, sup);
240 k_hashtable_remove(sup, "Range:");
241 k_hashtable_remove(sup, "Content-Range:");
242 k_hashtable_remove(sup, "Status:");
243 k_hashtable_remove(sup, "Status-Cache:");
244 char* mth=k_strdup(k_hashtable_get(sub, "Method:"));
245 char* via=k_strdup(k_hashtable_get(sub, "Via:"));
246 char* ims=k_strdup(k_hashtable_get(sub, "If-Modified-Since:"));
247 char* rng=k_strdup(k_hashtable_get(sub, "Range:"));
248 if(mth) k_hashtable_put(sup, "Method:", mth);
249 if(via) k_hashtable_put(sup, "Via:", via);
250 if(ims) k_hashtable_put(sup, "If-Modified-Since:", ims);
251 if(rng) k_hashtable_put(sup, "Range:", rng);
255 void ensure_pub_entry(k_hashtable* ent_head, k_hashtable* sub)
258 k_hashtable* sup=get_this(ent_head, tag, sub);
260 k_hashtable* sup=k_hashtable_dup(sub);
261 k_hashtable_remove(sup, "Sub-To:");
262 k_hashtable_remove(sup, "Sub-Type:");
263 k_hashtable_sub(ent_head, tag, sup);
266 k_hashtable_remove(sup, "Method:");
267 k_hashtable_remove(sup, "If-Modified-Since:");
268 k_hashtable_remove(sup, "Cache-Control:");
269 k_hashtable_remove(sup, "Update:");
270 char* mth=k_strdup(k_hashtable_get(sub, "Method:"));
271 char* ims=k_strdup(k_hashtable_get(sub, "If-Modified-Since:"));
272 char* ccn=k_strdup(k_hashtable_get(sub, "Cache-Control:"));
273 char* upd=k_strdup(k_hashtable_get(sub, "Update:"));
274 if(mth) k_hashtable_put(sup, "Method:", mth);
275 if(ims) k_hashtable_put(sup, "If-Modified-Since:", ims);
276 if(ccn) k_hashtable_put(sup, "Cache-Control:", ccn);
277 if(upd) k_hashtable_put(sup, "Update:", upd);
281 k_hashtable* get_this(k_hashtable* ent_head, char* pubsub, k_hashtable* try)
283 k_hashtable* curr=k_hashtable_get(ent_head, pubsub);
290 val=k_hashtable_get(try, tag);
291 if(val) return get_using(curr, tag, val);
294 val=k_hashtable_get(try, tag);
295 if(val) return get_using(curr, tag, val);
300 k_hashtable* get_using(k_hashtable* curr, char* tag, char* val)
303 for(c=curr; c; c=c->next) if(k_hashtable_is(c, tag, val)) return c;
307 /* -}{---- ------------------------------------------------------------------ */
309 void incoming_resource(ni_event* evt)
312 if(L) ni_event_show(evt, "ON got resource incoming event");
314 ni_resource* res=k_hashtable_get(resources, evt->uri);
315 int fullconst=res && k_hashtable_is(res->ent_head, "Status:", "200") &&
316 k_hashtable_is(res->ent_head, "CUX:", "C");
319 k_log_err("Resource is complete and Constant");
320 ni_event_delete(evt);
323 if(!res) res=ensure_res(evt->uri);
325 k_hashtable* reseh=res->ent_head;
326 k_hashtable* evteh=evt->ent_head;
327 int okfull =k_hashtable_is(evteh, "Status:", "200");
328 int partial =k_hashtable_is(evteh, "Status:", "206");
329 int headonly=k_hashtable_is(evteh, "Status:", "260");/*
330 int updated =k_hashtable_is(evteh, "Status:", "266");*/
331 int notmod =k_hashtable_is(evteh, "Status:", "304");
332 int notfound=k_hashtable_is(evteh, "Status:", "404");
334 int entityok= (okfull || partial || notmod);
335 int entityev=!(headonly || notmod || notfound);
336 int entityin=!!evt->entity;
337 int entityon=!!res->entity;
341 if(okfull || !entityon){
342 k_hashtable_merge(reseh, evteh);
343 if(okfull) k_hashtable_remove(reseh, "Content-Range:");
346 merge_non_entity_headers(reseh, evteh);
349 fix_via_subs(evteh, reseh);
352 if(okfull || (partial && !entityon)){
353 if(res->entity!=evt->entity){
354 if(!k_hashtable_is(reseh, "CUX:", "C")){
357 res->entity=evt->entity;
361 if(partial && entityon){
362 merge_entity_range(res, evt);
366 if(L) ni_resource_show(res, "updated resource - sync and try pubs:");
368 call_sync_resource(res);
370 test_pub_tos(res, evt, entityok);
373 ni_event_delete(evt);
375 if(L) ni_resource_show(res, "resource after ON:");
378 void fix_via_subs(k_hashtable* evteh, k_hashtable* reseh)
380 char* from=k_hashtable_get(evteh, "From:");
382 k_hashtable* subs=k_hashtable_get(reseh, "Sub-To:");
384 for(sub=subs; sub; sub=sub->next){
385 if(!k_hashtable_is(sub, "Via:", from)) continue;
386 int st=k_hashtable_get_int(evteh, "Status:");
387 char* cr=k_hashtable_get_dup(evteh, "Content-Range:");
388 if(st!=304) k_hashtable_put_int(sub, "Status:", st);
389 if(st==200) k_hashtable_remove( sub, "Content-Range:");
391 if(cr) k_hashtable_put(sub, "Content-Range:", cr);
392 if(sub_ok(sub)) k_hashtable_set(sub, "Status-Cache:", "OK");
396 void test_pub_tos(ni_resource* res, ni_event* evt, int entityok)
398 k_hashtable* keeps=0;
399 k_hashtable* sub=k_hashtable_extract(res->ent_head, "Pub-To:");
401 k_hashtable* subnext=sub->next;
404 int sat=satisfiable(sub, res, evt, entityok);
405 update_pubcache(sat, 0, res->ent_head, sub);
407 respond(k_hashtable_dup(sub), res, evt);
408 if(!k_hashtable_get(sub, "Update:")) keep=0;
415 k_hashtable_delete(sub);
421 k_hashtable* subnext=sub->next;
422 k_hashtable_sub(res->ent_head, "Pub-To:", sub);
427 int satisfiable(k_hashtable* sub,
433 int get =k_hashtable_is( sub, "Method:", "GET");
434 int head =k_hashtable_is( sub, "Method:", "HEAD");
435 int dosub=k_hashtable_is( sub, "Method:", "SUB");
436 int unsub=k_hashtable_is( sub, "Method:", "UNSUB");
437 int full=!k_hashtable_isi(sub, "Cache-Control:", "no-full");
438 int updt =k_hashtable_isi(sub, "Update:", "changes");
439 char* ims =k_hashtable_get(sub, "If-Modified-Since:");
440 char* range=k_hashtable_get(sub, "Range:");
442 int getsub =get || dosub;
443 int getrange=getsub && range;
445 k_hashtable* reseh=res->ent_head;
446 int gotall= k_hashtable_is( reseh, "Status:", "200");
447 int gotrange= k_hashtable_is( reseh, "Status:", "206");
448 int gothead= k_hashtable_is( reseh, "Status:", "260");
449 int gotupdated=evt &&
450 k_hashtable_is(evt->ent_head, "Status:", "266");
451 int notfound= k_hashtable_is( reseh, "Status:", "404");
452 int constant= k_hashtable_is( reseh, "CUX:", "C" );
453 char* conrange= k_hashtable_get(reseh, "Content-Range:");
456 if(notfound) return 1;
458 int gotany=(gothead || gotrange || gotall);
459 int snapok=(constant || !ims || entityok);
463 ((getsub && gotall && snapok) ||
464 (getrange && gotrange && range_ok(range, conrange) && snapok) ||
468 ((dosub && gotupdated)));
470 if(L) k_log_out("satisfiable %d", sat);
474 void update_pubcache(int sat,
475 k_hashtable** pubcachep,
479 if(!sat){ if(pubcachep){
480 k_hashtable* pubcache;
481 pubcache=k_hashtable_get(reseh, "Pub-Cache:");
482 if(!pubcache || sub_less(pubcache, sub)){
484 pubcache=k_hashtable_dup(sub);
485 k_hashtable_sub(reseh, "Pub-Cache:", pubcache);
488 k_hashtable_merge(pubcache, sub);
490 k_hashtable_remove(pubcache, "URI:");
491 k_hashtable_remove(pubcache, "Sub-Type:");
492 *pubcachep=k_hashtable_dup(pubcache);
493 k_hashtable_set(*pubcachep, "Sub-Type:", "Cache");
496 else{ if(!pubcachep){
497 k_hashtable* pubcache;
498 pubcache=k_hashtable_get(reseh, "Pub-Cache:");
499 if(!sub_less(sub, pubcache)){
500 k_hashtable_remove(pubcache, "Method:");
501 k_hashtable_remove(pubcache, "If-Modified-Since:");
506 int sub_ok(k_hashtable* sub)
508 char* gotresp =k_hashtable_get(sub, "Status:");
509 if(!gotresp) return 0;
510 int notfound=k_hashtable_is( sub, "Status:", "404");
511 if(notfound) return 0;
512 int gotall =k_hashtable_is( sub, "Status:", "200");
513 int gotrange=k_hashtable_is( sub, "Status:", "206");
514 int gothead= k_hashtable_is( sub, "Status:", "260");
515 int doget =k_hashtable_is( sub, "Method:", "GET");
516 int dohead =k_hashtable_is( sub, "Method:", "HEAD");
517 int dosub =k_hashtable_is( sub, "Method:", "SUB");
518 char* range =k_hashtable_get(sub, "Range:");
519 char* conrange=k_hashtable_get(sub, "Content-Range:");
521 int dogetsub=doget || dosub;
522 int dogetrange=dogetsub && range;
523 int gotany =(gothead || gotrange || gotall);
525 return (dogetsub && gotall ) ||
526 (dogetrange && gotrange && range_ok(range, conrange)) ||
530 int sub_less(k_hashtable* sub1, k_hashtable* sub2)
533 if(L) k_log_out("sub_less sub1:");
534 if(L) k_hashtable_show_chars(sub1);
535 if(L) k_log_out("sub_less sub2:");
536 if(L) k_hashtable_show_chars(sub2);
537 char* mth1 =k_hashtable_get(sub1, "Method:");
538 int head1=k_hashtable_is( sub1, "Method:", "HEAD");
539 int get2 =k_hashtable_is( sub2, "Method:", "GET");
540 char* ims1 =k_hashtable_get(sub1, "If-Modified-Since:");
541 char* ims2 =k_hashtable_get(sub2, "If-Modified-Since:");
542 int full=!k_hashtable_isi(sub2, "Cache-Control:", "no-full");
543 return full && ((!mth1) || (head1 && get2) || (!ims1 && ims2));
546 int range_ok(char* range, char* conrange)
548 k_log_out("range_ok not implemented: %s vs %s", range, conrange);
552 void merge_non_entity_headers(k_hashtable* reseh, k_hashtable* evteh)
556 void merge_entity_range(ni_resource* res, ni_event* evt)
558 k_log_out("merge_entity_range not implemented yet");
561 /* -}{---- ------------------------------------------------------------------ */
563 void respond(k_hashtable* sub, ni_resource* res, ni_event* evt)
565 int updated=evt && k_hashtable_is(evt->ent_head, "Status:", "266");
566 ni_event* evv=updated? ni_event_dup(evt):
569 if(L) ni_event_show(evv, "respond");
571 k_hashtable_remove(evv->ent_head, "Permit:");
572 k_hashtable_remove(evv->ent_head, "Sub-To:");
573 k_hashtable_remove(evv->ent_head, "Pub-To:");
574 k_hashtable_remove(evv->ent_head, "Pub-Cache:");
575 k_hashtable_sub( evv->ent_head, "Pub-To:", sub);
578 nf=k_hashtable_is( evv->ent_head, "Status:", "404");
579 if(!nf) respond_ok(sub, evv);
580 else respond_nf(sub, evv);
583 void respond_ok(k_hashtable* sub, ni_event* evv)
589 k_hashtable* ent_head=evv->ent_head;
591 time_t modifitime=k_hashtable_get_int(ent_head, "Last-Modified-Epoch:");
592 char* modistring=k_hashtable_get( ent_head, "Last-Modified:");
594 modifitime=k_time_from_rfc(modistring);
596 char* imss=k_hashtable_get(sub, "If-Modified-Since:");
597 time_t imst=k_time_from_rfc(imss);
599 if(modifitime== -1 || imst== -1 || modifitime > imst){
600 if(k_hashtable_is(sub, "Method:", "HEAD")){
603 if(!k_hashtable_is(ent_head, "CUX:", "C")){
604 evv->entity=entity_to_octets(ent_head, evv->entity);
610 statustext="Not Modified";
614 drop_entity_headers(ent_head);
617 fill_headers(ent_head, status, statustext, 0,
618 modistring? -1: modifitime,
619 datalength, 0, 0, nocache);
621 char* pub =k_hashtable_get(sub, "URI:");
623 if(L) ni_event_show(evv, "respond_ok");
624 post_to_driver(pub, evv);
627 void respond_nf(k_hashtable* sub, ni_event* evv)
629 fill_headers(evv->ent_head, "404", "File Not Found", 0, -1, 0, 0, 0, 1);
630 char* pub =k_hashtable_get(sub, "URI:");
631 post_to_driver(pub, evv);
634 void post_to_driver(char* pub, ni_event* evq)
636 char* driver=handled_by(pub);
637 if(0) k_log_out("Passing %s on to %s", pub, driver);
638 if(0) ni_event_show(evq, "Post to Driver:");
639 k_event_post(driver, evq);
642 void* entity_to_octets(k_hashtable* ent_head, void* entity)
644 if(!entity) return 0;
645 size_t size=k_hashtable_get_int(ent_head, "Content-Length:");
646 return k_memdup(entity, size);
649 /* -}{---- ------------------------------------------------------------------ */
651 EXPORT char* ni_hostname()
653 return hostname? hostname: "not set";
656 EXPORT void ni_hostname_set(char* name)
659 hostname=k_strdup(name);
662 /* -}{---- ------------------------------------------------------------------ */
664 static ni_driver* opdriver;
665 static ni_driver* moddriver;
667 char* handled_by(char* pub)
669 if(moddriver->handles_resource(pub)) return moddriver->name;
673 void call_sync_resource(ni_resource* res)
675 if(moddriver->handles_resource(res->uri)) moddriver->sync_resource(res);
676 else opdriver->sync_resource(res);
679 ni_driver* ni_driver_new(char* name,
680 ni_handles_resource handles_resource,
681 ni_sync_resource sync_resource)
683 ni_driver* driver=k_malloc(sizeof(ni_driver));
685 driver->handles_resource=handles_resource;
686 driver->sync_resource =sync_resource;
690 EXPORT void ni_register_driver(char* name,
691 ni_handles_resource handles_resource,
692 ni_sync_resource sync_resource)
694 ni_driver* d=ni_driver_new(name, handles_resource, sync_resource);
695 if(!strcmp(name, "op")) opdriver=d;
699 /* -}{---- ------------------------------------------------------------------ */
701 EXPORT ni_resource* ni_resource_new(char* uri,
702 k_hashtable* ent_head,
705 char* urih=k_hashtable_get(ent_head, "URI:");
708 if(uri) k_hashtable_put_dup(ent_head, "URI:", uri);
710 ni_resource* res=k_malloc(sizeof(ni_resource));
711 res->uri =(uri? k_strdup(uri): 0);
712 res->ent_head=ent_head;
717 EXPORT ni_resource* ni_resource_dup(ni_resource* res)
719 ni_resource* rep=k_malloc(sizeof(ni_resource));
720 rep->uri =k_strdup( res->uri);
721 rep->ent_head=k_hashtable_dup(res->ent_head);
722 rep->entity = res->entity;
726 EXPORT void ni_resource_delete(ni_resource* res)
729 if(res->entity && res->ent_head){
730 int constant=k_hashtable_is(res->ent_head, "CUX:", "C");
731 if(!constant) k_free(res->entity);
733 k_hashtable_delete(res->ent_head);
738 static char* excto[]={ "Permit:", "Sub-To:", "Pub-To:", 0 };
739 static char* perto[]={ "Permit:", 0 };
740 static char* subto[]={ "Sub-To:", 0 };
741 static char* pubto[]={ "Pub-To:", 0 };
743 EXPORT void ni_resource_show(ni_resource* res, char* text)
746 k_log_out("\n---%s--------\n------------\n\n----------",
753 l+=k_hashtable_snprintf_x(res->ent_head, b+l, s-l, excto);
754 l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, perto);
755 l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, subto);
756 l+=k_hashtable_snprintf_i(res->ent_head, b+l, s-l, pubto);
757 k_log_out("\n---%s----%s--\n%s----------\n%p\n----------",
758 text, res->uri, tmpbuf, res->entity);
762 /* -}{---- ------------------------------------------------------------------ */
764 EXPORT ni_resource* ni_resource_get(char* uri)
766 return k_hashtable_get(resources, uri);
769 /* -}{---- ------------------------------------------------------------------ */
771 EXPORT ni_event* ni_res_to_evt(ni_resource* res)
773 ni_event* evp=k_malloc(sizeof(ni_event));
774 evp->uri =k_strdup( res->uri);
775 evp->evt_head=k_hashtable_new("vHeaders/ni_res_to_evt", 1);
776 evp->ent_head=k_hashtable_dup(res->ent_head);
777 evp->entity = res->entity;
781 /* -}{---- ------------------------------------------------------------------ */
783 EXPORT ni_event* ni_event_new(char* uri,
784 k_hashtable* evt_head,
785 k_hashtable* ent_head,
788 char* urih=k_hashtable_get(ent_head, "URI:");
791 if(uri) k_hashtable_put_dup(ent_head, "URI:", uri);
793 ni_event* evt=k_malloc(sizeof(ni_event));
794 evt->uri =(uri? k_strdup(uri): 0);
795 evt->evt_head=evt_head;
796 evt->ent_head=ent_head;
801 EXPORT ni_event* ni_event_dup(ni_event* evt)
803 ni_event* evp=k_malloc(sizeof(ni_event));
804 evp->uri =k_strdup( evt->uri);
805 evp->evt_head=k_hashtable_dup(evt->evt_head);
806 evp->ent_head=k_hashtable_dup(evt->ent_head);
807 evp->entity = evt->entity;
811 EXPORT void ni_event_delete(ni_event* evt)
814 if(evt->entity && evt->ent_head){
815 int constant=k_hashtable_is(evt->ent_head, "CUX:", "C");
816 if(!constant) k_free(evt->entity);
818 k_hashtable_delete(evt->evt_head);
819 k_hashtable_delete(evt->ent_head);
824 EXPORT void ni_event_show(ni_event* evt, char* text)
827 k_log_out("\n---%s--------\n------------\n\n----------",
833 int n=k_hashtable_snprintf(evt->evt_head, buf, siz)+1;
834 ; k_hashtable_snprintf(evt->ent_head, buf+n, siz-n);
835 k_log_out("\n---%s----%s--\n"
839 text, evt->uri, buf, buf+n, evt->entity);
843 /* -}{----------------------------------------------------------------------- */