root/trunk/midgard/apis/php5/midgard.c

Revision 18417, 28.2 kB (checked in by piotras, 1 month ago)

Enable replicator class

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* $Id$
2 Copyright (C) 2000 The Midgard Project ry
3 Copyright (C) 2005, 2006, 2007, 2008 Piotr Pokora, <piotrek.pokora@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Lesser General Public License as published
7 by the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <sys/file.h>
21 #include "php_midgard.h"
22 #include "php_midgard_compat.h"
23 #include <midgard/midgard_http_host.h>
24
25 #include "mgd_preparser.h"
26 #include "mgd_preparse.h"
27 #include "php_midgard_gobject.h"
28
29 #include <zend_exceptions.h>
30 #include <zend_extensions.h>
31 #include <zend_ini.h>
32
33 #include <locale.h>
34 #include <SAPI.h>
35
36 #ifdef G_LOG_DOMAIN
37 #undef G_LOG_DOMAIN
38 #define G_LOG_DOMAIN "midgard-core"
39 #endif
40
41 /* True global resources - no need for thread safety here */
42 static MidgardSchema *midgard_global_schema = NULL;
43 static zend_class_entry *midgard_metadata_class;
44 static zend_class_entry *ce_midgard_error_exception;
45 static MidgardConnection *inherited_cnc;
46 static void _make_midgard_global(); 
47 guint global_loghandler = 0;
48 zend_object_handlers php_midgard_gobject_handlers;
49 /* End of true globals */
50
51 static void php_midgard_register_as_zend_extension();
52
53 MGD_FUNCTION(ret_type, is_guid, (type_param));
54
55 /* Undocumented */
56 MGD_FUNCTION(ret_type, cache_invalidate, (type_param));
57 MGD_FUNCTION(ret_type, set_errno, (type_param));
58
59 /* Every user visible function must have an entry in midgard_functions[].
60 */
61 function_entry midgard2_functions[] = {
62 MGD_FE(errno, NULL)
63 MGD_FE(errstr, NULL)
64 MGD_FE(version, NULL)
65 MGD_FE(snippet, NULL)
66 MGD_FE(preparse, NULL)
67 MGD_FE(format, NULL)
68 MGD_FE(template, NULL)
69 MGD_FE(is_element_loaded, NULL)
70 MGD_FE(is_guid, NULL)
71 /* Undocumented */
72     {NULL, NULL, NULL}  /* Must be the last line in midgard2_functions[] */
73 };
74
75 gboolean php_midgard_error_throw_exception(MidgardConnection *mgd)
76 {
77         if(mgd->errnum != MGD_ERR_OK) {
78                 zend_throw_exception_ex(ce_midgard_error_exception,
79                                 0 TSRMLS_CC, mgd->errstr);
80                 return TRUE;
81         }       
82        
83         return FALSE;
84 }
85
86 /* TODO , Check how msg memory (re)allocation works if msg is passed
87  * to php_error already */
88 void php_midgard_log_errors(const gchar *domain, GLogLevelFlags level,
89                 const gchar *msg, gpointer userdata)
90 {
91         MidgardConnection *mgd = (MidgardConnection*) userdata;
92         gchar *level_ad = NULL;
93         guint mlevel = midgard_connection_get_loglevel(mgd);
94
95         g_assert(msg != NULL);
96
97         switch (level) {
98                 case G_LOG_FLAG_RECURSION:
99                         level_ad =  "RECURSION";
100                         break;
101                        
102                 case G_LOG_FLAG_FATAL:
103                         level_ad = "FATAL! ";
104                         break;
105                        
106                 case G_LOG_LEVEL_ERROR:
107                         level_ad =  "ERROR";
108                         php_error(E_ERROR,
109                                         "(pid:%ld): %s",
110                                         (unsigned long)getpid(), msg);
111                         return;
112                         break;
113                        
114                 case G_LOG_LEVEL_CRITICAL:
115                         level_ad = "CRITICAL ";
116                         php_error(E_WARNING,
117                                         "(pid:%ld): %s",
118                                         (unsigned long)getpid(), msg);
119                         return;
120                         break;
121                        
122                 case G_LOG_LEVEL_WARNING:
123                         level_ad =  "WARNING"
124                         php_error(E_WARNING,
125                                         "(pid:%ld): %s",
126                                         (unsigned long)getpid(), msg);                                 
127                         return;
128                         break;
129                        
130                 case G_LOG_LEVEL_MESSAGE:
131                         level_ad = "MESSAGE";
132                         break;
133                
134                 case G_LOG_LEVEL_INFO:
135                         level_ad = "info";     
136                         break;
137                        
138                 case G_LOG_LEVEL_DEBUG:
139                         level_ad = "DEBUG";     
140                         break;
141                        
142                 default:
143                         level_ad =  "Unknown level";
144                         break;
145         }       
146
147         if (mlevel >= level) {
148        
149                 midgard_error_default_log(
150                                 domain, level, msg, MIDGARD_CONNECTION(mgd_handle()));
151         }
152 }
153
154 ZEND_DECLARE_MODULE_GLOBALS(midgard2)
155
156 zend_module_entry midgard2_module_entry = {
157         STANDARD_MODULE_HEADER,
158         "midgard2",
159         midgard2_functions,
160         PHP_MINIT(midgard2),
161         PHP_MSHUTDOWN(midgard2),
162         PHP_RINIT(midgard2),   
163         PHP_RSHUTDOWN(midgard2),
164         PHP_MINFO(midgard2),
165         MIDGARD_LIB_VERSION,          /* extension version number (string) */
166         STANDARD_MODULE_PROPERTIES
167 };
168
169 //#ifdef COMPILE_DL_MIDGARD2
170 ZEND_GET_MODULE(midgard2)
171 //#endif
172
173 ZEND_INI_BEGIN()
174 ZEND_INI_ENTRY("midgard.configuration", "", ZEND_INI_SYSTEM, NULL)
175 ZEND_INI_ENTRY("midgard.http", "Off", ZEND_INI_SYSTEM, NULL)
176 ZEND_INI_ENTRY("midgard.engine", "On", ZEND_INI_ALL, NULL)
177 ZEND_INI_ENTRY("midgard.quota", "Off", ZEND_INI_ALL, NULL)
178 ZEND_INI_ENTRY("midgard.memory_debug", "Off", ZEND_INI_ALL, NULL)
179 ZEND_INI_END()
180
181 static void php_midgard2_init_globals(zend_midgard2_globals *midgard2_globals)
182 {
183         midgard2_globals->mgd = NULL;
184 }
185
186 static gboolean php_midgard_ini_enabled(const gchar *ini_entry)
187 {
188         g_assert(ini_entry != NULL);
189
190         gchar *entry = zend_ini_string((gchar *)ini_entry, strlen(ini_entry)+1, 0);
191         gchar *lentry = g_ascii_strdown(entry, strlen(entry));
192
193         gboolean enabled = FALSE;
194
195         /* Kind of weird, zend_ini_entry returns 'Off' but might returns '1' when set to 'On' */
196         if(g_str_equal(lentry, "on")
197                         || *lentry == '1')
198                 enabled = TRUE;
199
200         g_free(lentry);
201
202         return enabled;
203 }
204
205 static gboolean php_midgard_memory_debug()
206 {
207         return php_midgard_ini_enabled("midgard.memory_debug");
208 }
209
210 static gboolean php_midgard_engine_is_enabled()
211 {
212         gchar *engine = zend_ini_string("midgard.engine", sizeof("midgard.engine"), 0);
213         gchar *lengine = g_ascii_strdown(engine, strlen(engine));
214
215         gboolean enabled = FALSE;
216        
217         if(g_str_equal(lengine, "on"))
218                 enabled = TRUE;
219
220         g_free(lengine);
221
222         return enabled;
223 }
224
225 static gboolean php_midgard_is_http_env()
226 {
227         gchar *http = zend_ini_string("midgard.http", sizeof("midgard.http"), 0);
228         gchar *lhttp = g_ascii_strdown(http, strlen(http));
229
230         gboolean enabled = FALSE;
231        
232         if(g_str_equal(lhttp, "on"))
233                 enabled = TRUE;
234
235         g_free(lhttp);
236
237         return enabled;
238 }
239
240 static const gchar *php_midgard_get_configuration()
241 {
242         gchar *config = zend_ini_string("midgard.configuration", sizeof("midgard.configuration"), 0);
243         return (const gchar *) config;
244 }
245
246 static GHashTable *all_configs = NULL;
247
248 static gboolean php_midgard_initialize_configs()
249 {
250         if(all_configs != NULL)
251                 return TRUE;
252
253         all_configs = midgard_connection_open_all(FALSE);
254
255         if(all_configs != NULL)
256                 return TRUE;
257
258         return FALSE;
259 }
260
261 PHP_MINIT_FUNCTION(midgard2)
262 {
263         zend_extension *ze = zend_get_extension("midgard");
264         if(ze != NULL) {
265                 php_error(E_ERROR, "Module midgard (1.x) already loaded");
266                 return FAILURE;
267         }
268
269         ze = zend_get_extension(MIDGARD_PACKAGE_NAME);
270         if(ze != NULL) {
271                 php_error(E_NOTICE, "Module midgard2 already loaded. It's recommended to load it via php.ini");
272                 return SUCCESS;
273         }
274
275         /*
276         zend_module_entry *module;
277         int rv = zend_hash_find(&module_registry, "midgard2", strlen("midgard2")+1, (void**)&module);
278         if(rv == SUCCESS)
279                 return SUCCESS;
280         */
281
282         global_loghandler =
283                 g_log_set_handler("midgard-core", G_LOG_LEVEL_MASK,
284                                 midgard_error_default_log, NULL);
285                
286         //g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
287         //g_log_set_fatal_mask("GLib-GObject", G_LOG_LEVEL_CRITICAL);
288
289         ZEND_INIT_MODULE_GLOBALS(midgard2, php_midgard2_init_globals, NULL);
290
291         zend_register_auto_global("_MIDGARD", sizeof("_MIDGARD")-1, NULL TSRMLS_CC);
292         zend_register_auto_global("_MIDCOM", sizeof("_MIDCOM")-1, NULL  TSRMLS_CC);
293         zend_register_auto_global("_MIDGARD_CONNECTION", sizeof("_MIDGARD_CONNECTION")-1, NULL  TSRMLS_CC);
294
295         midgard_init();
296
297         /* register Gtype types from schemas */
298         if(!g_type_from_name("midgard_article")
299                         && midgard_global_schema == NULL) {
300
301                 midgard_global_schema = g_object_new(MIDGARD_TYPE_SCHEMA, NULL);
302                 midgard_schema_init((MidgardSchema *) midgard_global_schema);
303                 midgard_schema_read_dir((MidgardSchema *) midgard_global_schema, MIDGARD_LSCHEMA_DIR);
304         }
305
306         /* Initialize handlers */
307         memcpy(&php_midgard_gobject_handlers,
308                         zend_get_std_object_handlers(), sizeof(zend_object_handlers));
309         /* Custom handlers hooks */
310         php_midgard_gobject_handlers.clone_obj = NULL;
311         php_midgard_gobject_handlers.read_property = php_midgard_gobject_read_property;
312         php_midgard_gobject_handlers.write_property = php_midgard_gobject_write_property;
313         php_midgard_gobject_handlers.get_properties = php_midgard_zendobject_get_properties;
314         php_midgard_gobject_handlers.has_property = php_midgard_gobject_has_property;
315
316         /* Register midgard_exception class */
317         zend_class_entry ce;
318         INIT_CLASS_ENTRY(ce, "midgard_error_exception", NULL);
319         ce_midgard_error_exception = zend_register_internal_class_ex(&ce,
320                         zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
321
322         php_midgard_reflection_property_init(module_number);
323         php_midgard_query_builder_init(module_number);
324         php_midgard_config_init(module_number);
325         php_midgard_user_init(module_number);
326         php_midgard_blob_init(module_number);
327         php_midgard_sitegroup_init(module_number);
328         php_midgard_object_class_init(module_number);
329         php_midgard_request_config_init(module_number);
330         php_midgard_collector_init(module_number);
331         php_midgard_connection_init(module_number);
332         php_midgard_object_init(module_number);
333         php_midgard_dbus_init(module_number);
334         php_midgard_replicator_init(module_number);
335
336         /* Register midgard_metadata class */
337         static zend_class_entry midgard_metadata_class_entry;
338         INIT_CLASS_ENTRY(midgard_metadata_class_entry, "midgard_metadata", NULL);
339         midgard_metadata_class = zend_register_internal_class(&midgard_metadata_class_entry TSRMLS_CC);
340        
341         /* Register properties' midgard types */
342         REGISTER_LONG_CONSTANT("MGD_TYPE_NONE", MGD_TYPE_NONE, CONST_CS | CONST_PERSISTENT);
343         REGISTER_LONG_CONSTANT("MGD_TYPE_STRING", MGD_TYPE_STRING, CONST_CS | CONST_PERSISTENT);
344         REGISTER_LONG_CONSTANT("MGD_TYPE_INT", MGD_TYPE_INT, CONST_CS | CONST_PERSISTENT);
345         REGISTER_LONG_CONSTANT("MGD_TYPE_UINT", MGD_TYPE_UINT, CONST_CS | CONST_PERSISTENT);
346         REGISTER_LONG_CONSTANT("MGD_TYPE_FLOAT", MGD_TYPE_FLOAT, CONST_CS | CONST_PERSISTENT);
347         REGISTER_LONG_CONSTANT("MGD_TYPE_BOOLEAN", MGD_TYPE_BOOLEAN, CONST_CS | CONST_PERSISTENT);
348         REGISTER_LONG_CONSTANT("MGD_TYPE_TIMESTAMP", MGD_TYPE_TIMESTAMP, CONST_CS | CONST_PERSISTENT);
349         REGISTER_LONG_CONSTANT("MGD_TYPE_LONGTEXT", MGD_TYPE_LONGTEXT, CONST_CS | CONST_PERSISTENT);
350         REGISTER_LONG_CONSTANT("MGD_TYPE_GUID", MGD_TYPE_GUID, CONST_CS | CONST_PERSISTENT);
351        
352         /* Register errcode constants */
353         REGISTER_LONG_CONSTANT("MGD_ERR_OK", MGD_ERR_OK, CONST_CS | CONST_PERSISTENT);
354         REGISTER_LONG_CONSTANT("MGD_ERR_ERROR", MGD_ERR_ERROR, CONST_CS | CONST_PERSISTENT);
355         REGISTER_LONG_CONSTANT("MGD_ERR_ACCESS_DENIED", MGD_ERR_ACCESS_DENIED, CONST_CS | CONST_PERSISTENT);
356         REGISTER_LONG_CONSTANT("MGD_ERR_SITEGROUP_VIOLATION", MGD_ERR_SITEGROUP_VIOLATION, CONST_CS | CONST_PERSISTENT);
357         REGISTER_LONG_CONSTANT("MGD_ERR_NOT_OBJECT", MGD_ERR_NOT_OBJECT, CONST_CS | CONST_PERSISTENT);
358         REGISTER_LONG_CONSTANT("MGD_ERR_INVALID_NAME", MGD_ERR_INVALID_NAME, CONST_CS | CONST_PERSISTENT);
359         REGISTER_LONG_CONSTANT("MGD_ERR_DUPLICATE", MGD_ERR_DUPLICATE, CONST_CS | CONST_PERSISTENT);
360         REGISTER_LONG_CONSTANT("MGD_ERR_HAS_DEPENDANTS", MGD_ERR_HAS_DEPENDANTS, CONST_CS | CONST_PERSISTENT);
361         REGISTER_LONG_CONSTANT("MGD_ERR_RANGE", MGD_ERR_RANGE, CONST_CS | CONST_PERSISTENT);
362         REGISTER_LONG_CONSTANT("MGD_ERR_NOT_CONNECTED", MGD_ERR_NOT_CONNECTED, CONST_CS | CONST_PERSISTENT);
363         REGISTER_LONG_CONSTANT("MGD_ERR_SG_NOTFOUND", MGD_ERR_SG_NOTFOUND, CONST_CS | CONST_PERSISTENT);
364         REGISTER_LONG_CONSTANT("MGD_ERR_INVALID_OBJECT", MGD_ERR_INVALID_OBJECT, CONST_CS | CONST_PERSISTENT);
365         REGISTER_LONG_CONSTANT("MGD_ERR_QUOTA", MGD_ERR_QUOTA, CONST_CS | CONST_PERSISTENT);
366         REGISTER_LONG_CONSTANT("MGD_ERR_INTERNAL", MGD_ERR_INTERNAL, CONST_CS | CONST_PERSISTENT);
367         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_NAME_EXISTS", MGD_ERR_OBJECT_NAME_EXISTS, CONST_CS | CONST_PERSISTENT);
368         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_NO_STORAGE", MGD_ERR_OBJECT_NO_STORAGE, CONST_CS | CONST_PERSISTENT);
369         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_PARENT", MGD_ERR_OBJECT_NO_PARENT, CONST_CS | CONST_PERSISTENT);
370         REGISTER_LONG_CONSTANT("MGD_ERR_INVALID_PROPERTY_VALUE", MGD_ERR_INVALID_PROPERTY_VALUE, CONST_CS | CONST_PERSISTENT);
371         REGISTER_LONG_CONSTANT("MGD_ERR_INVALID_PROPERTY", MGD_ERR_INVALID_PROPERTY, CONST_CS | CONST_PERSISTENT);
372         REGISTER_LONG_CONSTANT("MGD_ERR_USER_DATA", MGD_ERR_USER_DATA, CONST_CS | CONST_PERSISTENT);
373         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_DELETED", MGD_ERR_OBJECT_DELETED, CONST_CS | CONST_PERSISTENT);
374         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_PURGED", MGD_ERR_OBJECT_PURGED, CONST_CS | CONST_PERSISTENT);
375         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_EXPORTED", MGD_ERR_OBJECT_EXPORTED, CONST_CS | CONST_PERSISTENT);
376         REGISTER_LONG_CONSTANT("MGD_ERR_OBJECT_IMPORTED", MGD_ERR_OBJECT_IMPORTED, CONST_CS | CONST_PERSISTENT);
377         REGISTER_LONG_CONSTANT("MGD_ERR_MISSED_DEPENDENCE", MGD_ERR_MISSED_DEPENDENCE, CONST_CS | CONST_PERSISTENT);
378        
379         REGISTER_INI_ENTRIES();
380
381         /* midgard.http is on so we make all available connections */
382         if (php_midgard_is_http_env()) {
383        
384                 g_debug("Found server context. Initialize all configurations");
385                 if(!php_midgard_initialize_configs())
386                         return FAILURE;
387         }
388
389         /* Register midgard as Zend extension */
390         php_midgard_register_as_zend_extension();
391
392         return SUCCESS;
393 }
394
395 static void __free_connections(gpointer key, gpointer val, gpointer ud)
396 {
397         MidgardConnection *cnc = MIDGARD_CONNECTION(val);
398         g_object_unref(cnc);
399 }
400
401 PHP_MSHUTDOWN_FUNCTION(midgard2)
402 {       
403         //g_warning("MIDGARD MODULE SHUTDOWN - FIXME");
404         return SUCCESS;
405
406         UNREGISTER_INI_ENTRIES();
407
408         /* Free schema */
409         if(midgard_global_schema != NULL)
410                 g_object_unref(midgard_global_schema);
411
412         /* Free connections */
413         if(all_configs != NULL) {
414                
415                 g_hash_table_foreach(all_configs, __free_connections, NULL);
416                
417         } else {
418                
419                 MidgardConnection *mgd = mgd_handle();
420                 if(mgd != NULL)
421                         g_object_unref(mgd);
422         }
423
424         return SUCCESS;
425 }
426
427 static const gchar *php_midgard_get_request_uri()
428 {
429         /* FIXME */
430         /* In theory we should get request_uri string from SG(request_info).request_uri,
431          * but it holds SCRIPT_NAME name when RINIT is invoked.
432          * Hash lookup is acceptable, but it would be better to get uri directly.*/
433
434         zval **data;
435        
436         if(zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]),
437                                 "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &data) == FAILURE)
438                 return NULL;
439
440         return (const gchar *)Z_STRVAL_PP(data);
441 }
442
443 static const gchar *php_midgard_get_request_host()
444 {
445         zval **data;
446
447         if(zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]),
448                                 "HTTP_HOST", sizeof("HTTP_HOST"), (void **) &data) == FAILURE)
449                 return NULL;
450
451         return (const gchar *)Z_STRVAL_PP(data);
452 }
453
454 static MidgardHttpHost *global_http_host = NULL;
455
456 static void php_midgard_initialize_http_request()
457 {       
458         const gchar *uri = php_midgard_get_request_uri();
459
460         if(uri == NULL){
461                 g_warning("NULL uri in server context");
462                 return;
463         }
464
465         const gchar *hoststr = php_midgard_get_request_host();
466
467         if(hoststr == NULL) {
468                 g_warning("NULL hostname in server context");
469                 return;
470         }
471
472         gchar **hostsd = g_strsplit(hoststr, ":", -1);
473
474         MidgardHttpHost *http_host =
475                 midgard_http_host_new(mgd_handle(), hostsd[0], atoi(hostsd[1]), uri);
476
477         g_strfreev(hostsd);
478
479         if(http_host == NULL)
480                 return;
481
482         global_http_host = http_host;
483
484         MidgardRequestConfig *rcfg = midgard_http_host_get_request_config(http_host);
485         if(!midgard_connection_set_request_config(mgd_handle(), rcfg))
486                 g_warning("Couldn't set request configuration for current connection");
487
488         return;
489 }
490
491 PHP_RINIT_FUNCTION(midgard2)
492 {       
493         inherited_cnc = NULL;
494
495         if(!php_midgard_engine_is_enabled())
496                 return SUCCESS;
497
498         if (SG(server_context)) {       
499
500                 const gchar *config = php_midgard_get_configuration();
501                 MidgardConnection *cnc =
502                         (MidgardConnection *) g_hash_table_lookup(all_configs, config);
503        
504                 /* Try to connect */
505                 if(cnc == NULL) {
506                        
507                         g_warning("Can not find connection handler for '%s' configuration", config);
508                         return FAILURE;
509                 }
510
511                 g_debug("Found connection handler for '%s'", config);   
512                 MGDG(mgd) = midgard_connection_copy(cnc);
513                 inherited_cnc = cnc;
514         }
515
516         if(MGDG(mgd) != NULL) {
517
518                 guint loghandler =
519                         g_log_set_handler(G_LOG_DOMAIN,
520                                         G_LOG_LEVEL_MASK,
521                                         php_midgard_log_errors,
522                                         (gpointer)mgd_handle());
523                 midgard_connection_set_loghandler(mgd_handle(), loghandler);
524
525                 inherited_cnc = mgd_handle();
526
527                 /* Initialize _MIDGARD_CONNECTION singleton */
528                 zval *_mcg = NULL;
529                 MAKE_STD_ZVAL(_mcg);
530                 php_midgard_gobject_init(_mcg, "midgard_connection",
531                                 G_OBJECT(mgd_handle()), FALSE);
532                 /* PHP object constructor hack.
533                  * I have no idea how to "trigger" php constructor here */
534                 /* TODO, check object_init_ex and similiar */
535                 zend_hash_add(&EG(symbol_table), "_MIDGARD_CONNECTION",
536                                 sizeof("_MIDGARD_CONNECTION"),
537                                 &_mcg, sizeof(zval **), NULL);
538
539         }
540
541         if (SG(server_context)) {
542                 php_midgard_initialize_http_request();
543         }
544
545         _make_midgard_global();
546
547          /* Initialize closure hash */
548         php_midgard_gobject_closure_hash_new();
549
550         return SUCCESS;
551 }
552
553 PHP_RSHUTDOWN_FUNCTION(midgard2)
554 {       
555         MidgardConnection *mgd = mgd_handle();
556        
557         g_debug("RSHUTDOWN");
558
559         if(mgd != NULL){
560
561        
562                 /* FIXME , replace with MidgardConnection API */
563                 if(mgd->person){
564                         g_object_unref(G_OBJECT(mgd->person));
565                         /* Set NULL explicitly. It work very fine with php-cli
566                          * however NULL must be set for Apache "sub"requests */
567                         mgd->person = NULL;
568                 }
569
570                 mgd->rcfg = NULL; /* REMOVE ME */
571         }
572
573         if(inherited_cnc != NULL) {
574                
575                 /* Remove G_LOG_DOMAIN loghandler!
576                  * Apache module or any other application might need to assign
577                  * own loghandler for midgard-core domain between RSHUTDOWN and RINIT */
578
579                 g_log_remove_handler(G_LOG_DOMAIN,
580                                 midgard_connection_get_loghandler(inherited_cnc));
581
582                 g_object_unref(inherited_cnc);
583                 inherited_cnc = NULL;
584         }
585
586         if(global_http_host != NULL)
587                 g_object_unref(global_http_host);
588
589         /* Free all closures
590          * We can not keep them persistant as all data changes per request. */
591         php_midgard_gobject_closure_hash_free();
592
593         /*
594         zend_extension *ze = zend_get_extension(MIDGARD_PACKAGE_NAME);
595         if(ze) {
596                 g_warning("Found midgard extension with handle %d", (int)ze->handle);
597                 ze->handle = 0;
598         }*/
599        
600         /* It's not safe, but allow valgrind to print function names.
601          * It simply forces Zend to not unload midgard module */
602         zend_module_entry *module;
603         int rv = zend_hash_find(&module_registry, "midgard2", strlen("midgard2")+1, (void**)&module);
604
605         if(rv == SUCCESS) {
606                 if(php_midgard_memory_debug()) {
607                         mgd_info("DISABLE MODULE HANDLE");
608                         module->handle = 0;
609                 }
610         }
611
612         g_debug("MIDGARD RSHUTDOWN SUCCESS");
613         return SUCCESS;
614 }
615
616 PHP_MINFO_FUNCTION(midgard2)
617 {
618     int i = 0;
619     php_info_print_table_start();
620     php_info_print_table_header(2, "Midgard2 Support", "enabled");
621     php_info_print_table_row(2, "Midgard2 version", midgard_version());
622    
623     while (midgard2_module_entry.functions[i].fname) {
624         php_info_print_table_row(2, "", midgard2_module_entry.functions[i].fname);
625         i++;
626     }
627     php_info_print_table_end();
628
629     i = 0;
630     php_info_print_table_start();
631     php_info_print_table_header(2, "MgdSchema technology support", "enabled");
632     php_info_print_table_row(2, "Midgard2 version", midgard_version());
633
634     /*
635     while (__midgard_php_type_functions[i].fname) {
636         php_info_print_table_row(2, "", __midgard_php_type_functions[i].fname);
637         i++;
638     }
639     */
640     php_info_print_table_end();
641        
642     php_info_print_box_start(0);
643     PUTS("<h3><a href=\"http://www.midgard-project.org/\">");
644     PUTS("The Midgard Project</a></h3>\n");
645
646     php_printf("This program makes use of the Midgard Content Management engine:<br />");
647     php_printf("&copy; 1998-2001 The Midgard Project Ry - 2000-2001 Aurora Linux<br />\n");
648     php_printf("&copy; 2002-2008 The Midgard Community<br />\n");
649     php_info_print_box_end();
650
651     /* Remove comments if you have entries in php.ini
652     DISPLAY_INI_ENTRIES();
653     */
654 }
655
656 MGD_FUNCTION(ret_type, config_init, (type_param))
657 {
658         gchar *conf;
659         gint conf_length;
660         MidgardConnection *mgd;
661         RETVAL_FALSE;
662
663         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
664                                 &conf, &conf_length) == FAILURE)
665                 return;
666
667         /* Check if connection is established */
668         if(mgd_handle() != NULL) {
669                
670                 php_error(E_NOTICE,
671                                 "mgd_config_init is deprecated. Use midgard_connection class");
672                 RETURN_TRUE;
673         }
674        
675         /* TODO , open connection here if really needed for some backward compatibility */     
676 }
677
678 /* Fetch static globals. Unfortunately these need to be here since the
679    module globals are declared static by the Zend macros
680 */
681 MidgardConnection *mgd_handle()
682 {
683         TSRMLS_FETCH();
684         return MGDG(mgd);
685 }
686
687 void mgd_handle_set(MidgardConnection *mgd)
688 {
689         g_assert(mgd != NULL);
690
691         TSRMLS_FETCH();
692         MGDG(mgd) = mgd;
693 }
694
695 void mgd_set_errno(MgdErrorGeneric mgd_errno)
696 {
697         TSRMLS_FETCH();
698         MIDGARD_ERRNO_SET(mgd_handle(), mgd_errno); 
699 }
700
701 void mgd_reset_errno(void)
702 {
703         TSRMLS_FETCH();
704         MIDGARD_ERRNO_SET(mgd_handle(), MGD_ERR_OK);
705 }
706
707 int mgd_get_errno()
708 {
709         TSRMLS_FETCH();
710         return mgd_handle()->errnum;
711 }
712
713 MGD_FUNCTION(ret_type, get_midgard, (type param))
714 {
715         /* TODO, rewrite me */
716         /* Get data from $MIDGARD */
717 }
718
719 MGD_FUNCTION(ret_type, set_default_lang, (type_param))
720 {
721         CHECK_MGD;
722         RETVAL_FALSE;
723         guint lang;
724
725         if (zend_parse_parameters(1 TSRMLS_CC, "l", &lang)
726                         == FAILURE) {
727                 WRONG_PARAM_COUNT;
728         }
729
730         /* mgd_set_default_lang(mgd_handle(), lang); */
731         RETVAL_TRUE;
732 }
733
734 MGD_FUNCTION(ret_type, get_default_lang, (type_param))
735 {
736         CHECK_MGD;
737         RETVAL_FALSE;
738
739         if(ZEND_NUM_ARGS() > 0)
740                 WRONG_PARAM_COUNT;
741
742         RETVAL_TRUE;
743         /*RETURN_LONG(mgd_get_default_lang(mgd_handle()));*/
744 }
745
746 static void _make_midgard_global()
747 {       
748         int i; 
749         zval *types, *confv, *mgd_php_globals, *schema_array;
750         MidgardConnection *mgd = mgd_handle();
751         MidgardRequestConfig *rcfg = NULL;
752         GValueArray *array = NULL;
753
754         if(mgd != NULL)
755                 rcfg = mgd->rcfg;
756
757         TSRMLS_FETCH();
758        
759         /* Initialize _MIDGARD array keys */
760         MAKE_STD_ZVAL(mgd_php_globals);
761         array_init(mgd_php_globals);
762
763         /* Initialize schema classes array */
764         MAKE_STD_ZVAL(schema_array);
765         array_init(schema_array);
766        
767         MAKE_STD_ZVAL(types);
768         array_init(types);
769        
770         guint n_types;
771         GType *all_types = g_type_children(MIDGARD_TYPE_OBJECT, &n_types);
772        
773         for (i = 0; i < n_types; i++) {
774        
775                 add_assoc_string(types,
776                                 (gchar *)g_type_name(all_types[i]), "", 1);
777         }
778
779         i = 0;
780
781         add_assoc_zval(schema_array, "types", types);
782         g_free(all_types);
783
784         add_assoc_zval(mgd_php_globals, "schema", schema_array);
785
786         zval *mro = NULL;
787         MAKE_STD_ZVAL(mro);     
788
789         /* This can be cli ? */
790         if(rcfg == NULL) {
791
792                 //MidgardRequest *request = midgard_request_new();
793                 //php_midgard_gobject_init(mro, "midgard_request", G_OBJECT(request), TRUE);
794                 //add_assoc_zval(mgd_php_globals, "midgard_request", mro);
795         }
796
797         /* Data from MidgardRequest */
798         if(rcfg != NULL) {
799
800                 /* MIDGARD_REQUEST */
801                 php_midgard_gobject_init(mro, "midgard_request_config", G_OBJECT(rcfg), TRUE);
802                 //add_assoc_zval(mgd_php_globals, "midgard_request", mro);
803                 
804                 /* ARGC */
805                 add_assoc_long(mgd_php_globals, "argc", rcfg->argc);
806
807                 /* ARGV */
808                 zval *argv;
809                 MAKE_STD_ZVAL(argv);
810                 array_init(argv);
811
812                 if(rcfg->argv != NULL) {
813                        
814                         array = (GValueArray *) rcfg->argv;
815                        
816                         for (i = 0; i < array->n_values; i++) {
817                                
818                                 GValue *strval = g_value_array_get_nth(array, i);
819                                 const gchar *argvstr =
820                                         g_value_get_string((const GValue *)strval);
821                                 add_index_string(argv, i, (gchar *)argvstr, 1);
822                         }
823
824                         array = NULL;
825                 }
826                 add_assoc_zval(mgd_php_globals, "argv", argv);
827
828                 /* URI */
829                 add_assoc_string(mgd_php_globals, "uri", rcfg->uri, 1);
830
831                 /* SELF */
832                 add_assoc_string(mgd_php_globals, "self", rcfg->uri, 1);
833
834                 /* LANG */
835                 add_assoc_long(mgd_php_globals, "lang",
836                                 midgard_connection_get_lang_id(mgd, NULL));
837
838                 /* SITEGROUP */
839                 add_assoc_long(mgd_php_globals, "sitegroup",
840                                 midgard_connection_get_sitegroup_id(mgd));
841
842                 guint id = 0;
843                 /* PAGE ID */
844                 if(rcfg->page) 
845                         g_object_get(G_OBJECT(rcfg->page), "id", &id, NULL);
846                        
847                 add_assoc_long(mgd_php_globals, "page", id);
848                
849
850                 /* HOST ID */
851                 id = 0;
852                 if(rcfg->host) {
853                         g_object_get(G_OBJECT(rcfg->host), "id", &id, NULL);
854                         /* FIXME , Initialize midgard_host for PHP */
855                 }
856        
857                 add_assoc_long(mgd_php_globals, "host", id);
858
859                 /* AUTH */
860                 add_assoc_bool(mgd_php_globals, "auth", rcfg->auth_required);
861
862                 /* STYLE */
863                 id = 0;
864                 if(rcfg->style)
865                         g_object_get(G_OBJECT(rcfg->style), "id", &id, NULL);
866                 add_assoc_long(mgd_php_globals, "style", id);
867                
868         }
869
870         /* configure prefix */
871         MAKE_STD_ZVAL(confv);
872         array_init(confv);
873         add_assoc_string(confv, "prefix", MIDGARD_LIB_PREFIX, 1);
874         add_assoc_zval(mgd_php_globals, "config", confv);
875
876         zend_hash_update(&EG(symbol_table), "_MIDGARD",
877                         sizeof("_MIDGARD"), &mgd_php_globals,
878                         sizeof(zval *), NULL);
879 }
880
881
882 /* Piotras: zend_parse_parameters_ex with first 'quiet' parameter
883  * is used to return false without any warning being set on PHP level.
884  * This is midcom related.
885  * I define quiet parameter as 2 , in any other case it's not quiet.
886  * I have no idea if it's hack like, but it works as expected */
887 MGD_FUNCTION(ret_type, is_guid, (type param))
888 {
889         gchar *guid;
890         guint guidl;
891         CHECK_MGD;