src/tree.c

00001 /* $Id: tree.c,v 1.28 2006/05/30 14:20:09 piotras Exp $
00002  *
00003  * midgard-lib: database access for Midgard clients
00004  *
00005  * Copyright (C) 1999 Jukka Zitting <jukka.zitting@iki.fi>
00006  * Copyright (C) 2000 The Midgard Project ry
00007  * Copyright (C) 2003 David Schmitter, Dataflow Solutions GmbH <schmitt@dataflow.ch>
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this library; see the file COPYING.  If not, write to
00021  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00022  * Boston, MA 02111-1307, USA.
00023  */
00024 
00025 #include <config.h>
00026 #include "midgard/midgard_legacy.h"
00027 #include "defaults.h"
00028 #if HAVE_CRYPT_H
00029 #include <crypt.h>
00030 #else
00031 #define _XOPEN_SOURCE
00032 #ifndef WIN32
00033 #include <unistd.h>
00034 #endif
00035 #endif
00036 #include <errno.h>
00037 #ifndef WIN32
00038 #include <unistd.h>
00039 #endif
00040 #include <time.h>
00041 
00042 static void mgd_copy_all_parameters(midgard * mgd, int id, const char * table,
00043                                                     int newoid)
00044 {
00045         midgard_res *res;
00046         res =
00047            mgd_sitegroup_select(mgd, "*", "record_extension",
00048                                                           "record_extension.tablename=$q "
00049                                                                           "AND record_extension.oid=$i",
00050                                                                 NULL, table, id);
00051         if (res) {
00052                 while (mgd_fetch(res)) {
00053                         mgd_copy_object ( mgd, res, "record_extension", "oid", newoid);
00054                 }
00055                 mgd_release(res);
00056         }
00057 }
00058 
00059 #if HAVE_MIDGARD_MULTILANG
00060 static int mgd_copy_all_content(midgard * mgd, int id, const char * table,
00061                                                     int newsid)
00062 {
00063         midgard_res *res;
00064         char * table_i = malloc(256 * sizeof(char));
00065         int retval = 0;
00066         assert (strlen(table) < 254);
00067         strcpy (table_i, table);
00068         strcat (table_i, "_i");
00069         
00070         res =
00071            mgd_ungrouped_select(mgd, "*", table_i,
00072                                                          "$s.sid=$d",
00073                                                                 NULL, table_i, id);
00074 
00075         if (res) {
00076                 while (mgd_fetch(res)) {
00077                   retval &= mgd_copy_object ( mgd, res, table_i, "sid", newsid);
00078                 }
00079                 mgd_release(res);
00080         }
00081         free(table_i);
00082         return retval;
00083 }
00084 
00085 
00086 #endif /* HAVE_MIDGARD_MULTILANG */
00087 /* DG: this function to copy blobs (to allow moving the blob from one type of object to another)
00088  * Can be optimized... */
00089 static int mgd_copy_object_blob(midgard * mgd, midgard_res * object, 
00090                                   int new_pid, const char *new_ptable)
00091 {
00092 #define MGD_BLOB_BUF_SIZE 4096
00093         FILE * fpo, * fpi;
00094         midgard_pool *pool;
00095         char *fields, *values;
00096         char new_location[MIDGARD_REPLIGARD_TAG_LENGTH + 5];
00097         static char dir[16] = "0123456789ABCDEF";
00098         char *new_path, *old_path;
00099         size_t sz;
00100         char * buf;
00101         const char *old_location = NULL;
00102         int i;
00103 
00104         if (!object)
00105                 return 0;
00106         pool = mgd_alloc_pool();
00107         if (!pool)
00108                 return 0;
00109 
00110         /* compute the new_location string */
00111         gchar *guid = midgard_guid_new(mgd);
00112         strcpy(new_location + 4, guid);
00113         g_free(guid);
00114 
00115         /* some basic hashing to aid in dirsize balancing. This probably
00116                 needs refinement since the rc5 checksum we use to generate the names
00117                 returns all readable chars which don't distribute well with the
00118                 simple method below
00119         */
00120         new_location[1] = new_location[3] = '/';
00121         new_location[0] = dir[ ((unsigned char)new_location[4]) / 16 ];
00122         new_location[2] = dir[ ((unsigned char)new_location[4]) % 16 ];
00123 
00124         new_path = mgd_format(mgd, pool, "$s/$s", 
00125                                         mgd_get_blobdir(mgd), new_location);
00126 
00127         /* 1. Create fields for query */
00128         fields = NULL;
00129         values = NULL;
00130         for (i = 0; i < mgd_cols(object); i++) {
00131                 if ((strcmp("id", mgd_colname(object, i)) != 0)
00132                     && (strcmp("sitegroup", mgd_colname(object, i)) != 0)
00133                    ) {
00134                         fields = fields ?
00135                            mgd_format(mgd, pool, "$s,$s", fields,
00136                                       mgd_colname(object, i)) : mgd_strdup(pool,
00137                                                                            mgd_colname (object, i));
00138                         /* Replace 'pid' field by new value */
00139                         if (!strcmp("pid", mgd_colname(object, i))) {
00140                                 values =
00141                                    values ? mgd_format(mgd, pool, "$s,$i",
00142                                                        values, new_pid) : mgd_format(mgd,
00143                                                                             pool, "$i", new_pid);
00144                         }
00145                         /* Replace 'ptable' field by new value */
00146                         else if (new_ptable && !strcmp("ptable", mgd_colname(object, i))) {
00147                                 values =
00148                                    values ? mgd_format(mgd, pool, "$s,$q",
00149                                                        values, new_ptable) : mgd_format(mgd,
00150                                                                             pool, "$q", new_ptable);
00151                         }
00152                         /* Replace 'location' field by new value */
00153                         else if (!strcmp("location", mgd_colname(object, i))) {
00154                                 old_location = mgd_sql2str(object, i);
00155                                 values =
00156                                    values ? mgd_format(mgd, pool, "$s,$q",
00157                                                        values, new_location) : mgd_format(mgd,
00158                                                                             pool, "$q", new_location);
00159                         }
00160                         else {
00161                                 values = values ?
00162                                    mgd_format(mgd, pool, "$s,$q", values,
00163                                               mgd_colvalue(object,
00164                                                            i)) :
00165                                    mgd_format(mgd, pool, "$q", mgd_colvalue(object, i));
00166                         }
00167                 }
00168         }
00169         /* 2. Create new object and update Repligard */
00170         i = mgd_create(mgd, "blobs", fields, "$s", values);
00171         if (i) {
00172 /* TODO: insert here the code to copy(blobdir+old_location, blobdir+new_location) */
00173                 if((buf = mgd_alloc(pool, MGD_BLOB_BUF_SIZE))) {
00174                         assert(old_location);
00175                         old_path = mgd_format(mgd, pool, "$s/$s", 
00176                                                         mgd_get_blobdir(mgd), old_location);
00177                         if ((fpo = fopen(new_path, "w")) == NULL) {
00178                                 mgd_free_pool(pool);
00179                                 return 0;
00180                         }
00181                         else if ((fpi = fopen(old_path, "r")) == NULL) {
00182                                 fclose(fpo);
00183                                 mgd_free_pool(pool);
00184                                 return 0;
00185                         }
00186                         while(!feof(fpi) && !ferror(fpi) && !ferror(fpo)) {
00187                                 if((sz = fread(buf, 1, MGD_BLOB_BUF_SIZE, fpi))) {
00188                                         fwrite(buf, 1, sz, fpo);
00189                                 }
00190                         }
00191                         if(ferror(fpi) || ferror(fpo)) {
00192                                 fclose(fpi); fclose(fpo);
00193                                 mgd_free_pool(pool);
00194 /* TODO: ROLLBACK: too bad we don't have transaction support :( */
00195                                 return 0;
00196                         }
00197                         fclose(fpi);
00198                         fclose(fpo);
00199                 }
00200                 CREATE_REPLIGARD(mgd, "blobs", i)
00201         }
00202         mgd_free_pool(pool);
00203         return i;
00204 }
00205 
00206 static void mgd_copy_all_attachments(midgard * mgd, int id, const char * table,
00207                                                     int newid, const char * newtable)
00208 {
00209         midgard_res *res;
00210         int i;
00211         res =
00212            mgd_sitegroup_select(mgd, "*", "blobs", "blobs.ptable=$q AND blobs.pid=$i",
00213                                                                 NULL, table, id);
00214         if (res) {
00215                 while (mgd_fetch(res)) {
00216         /* First copy the blob */
00217                         i=mgd_copy_object_blob(mgd, res, newid, newtable);
00218         /* Then copy any parameters linked to the blob */
00219                         if(i) mgd_copy_all_parameters ( mgd, 
00220                                                         strtol(mgd_column(res, "id"), NULL, 10),
00221                                                         "blobs", i);
00222                 }
00223                 mgd_release(res);
00224         }
00225         
00226 }
00227 
00228 int mgd_copy_object(midgard * mgd, midgard_res * object, const char *table,
00229                     const char *upfield, int new_up)
00230 {
00231         midgard_pool *pool;
00232         char *fields, *values, *stmp;
00233         int i;
00234 
00235         if (!object)
00236                 return 0;
00237         pool = mgd_alloc_pool();
00238         if (!pool)
00239                 return 0;
00240         /* 1. Create fields for query */
00241         fields = NULL;
00242         values = NULL;
00243         for (i = 0; i < mgd_cols(object); i++) {
00244                 if ((strcmp("id", mgd_colname(object, i)) != 0)
00245                     && (strcmp("sitegroup", mgd_colname(object, i)) != 0)
00246                    ) {
00247                         stmp = fields;
00248                         fields = fields ?
00249                                         mgd_format(mgd, pool, "$s,$s", fields,
00250                                       mgd_colname(object, i)) : mgd_strdup(pool,
00251                                                                            mgd_colname (object, i));
00252                         if (stmp)
00253                                 mgd_free_from_pool(pool, stmp);
00254                         stmp = values;
00255                         /* Replace 'up' field by new value */
00256                         if (!strcmp(upfield, mgd_colname(object, i))) {
00257                                 values =
00258                                    values ? mgd_format(mgd, pool, "$s,$i",
00259                                                        values,
00260                                                        new_up) : mgd_format(mgd,
00261                                                                             pool,
00262                                                                             "$i",
00263                                                                             new_up);
00264                         }
00265                         else {
00266                                 values = values ?
00267                                    mgd_format(mgd, pool, "$s,$q", values,
00268                                               mgd_colvalue(object,
00269                                                            i)) :
00270                                    mgd_format(mgd, pool, "$q", mgd_colvalue(object, i));
00271                         }
00272                         if (stmp)
00273                                 mgd_free_from_pool(pool, stmp);
00274                 }
00275         }
00276         /* 2. Create new object and update Repligard */
00277         i = mgd_create(mgd, table, fields, "$s", values);
00278         if (i) {
00279                 CREATE_REPLIGARD(mgd, table, i)
00280         }
00281         mgd_free_pool(pool);
00282         return i;
00283 }
00284 
00285 
00286 /* DG: this function to copy articles (they have 2 'up' fields)
00287  * Can be optimized... */
00288 int mgd_copy_object_article(midgard * mgd, midgard_res * object,
00289                     int new_topic, int new_up)
00290 {
00291         midgard_pool *pool;
00292         char *fields, *values, *stmp;
00293         int i, old_topic, force_name_change;
00294    time_t now = time(NULL);
00295 
00296         if (!object)
00297                 return 0;
00298         pool = mgd_alloc_pool();
00299         if (!pool)
00300                 return 0;
00301         /* 1. Create fields for query */
00302         fields = NULL;
00303         values = NULL;
00304         force_name_change = 0;
00305         for (i = 0; i < mgd_cols(object); i++) {
00306                 if ((strcmp("id", mgd_colname(object, i)) != 0)
00307                     && (strcmp("sitegroup", mgd_colname(object, i)) != 0)
00308                    ) {
00309                         stmp = fields;
00310                         fields = fields ?
00311                            mgd_format(mgd, pool, "$s,$s", fields,
00312                                       mgd_colname(object, i)) : mgd_strdup(pool,
00313                                                                            mgd_colname
00314                                                                            (object,
00315                                                                             i));
00316                         if (stmp)
00317                                 mgd_free_from_pool(pool, stmp);
00318                         stmp = values;
00319                         /* Replace 'topic' field by new value */
00320                         if ((!strcmp("topic", mgd_colname(object, i))) && (new_topic)) {
00321                                 /* Check target topic to be the same */
00322                                 old_topic = mgd_sql2id(object, i);
00323                                 if (old_topic == new_topic) {
00324                                     /* if true, do not forget to change article name later */
00325                                     force_name_change = 1;
00326                                 }
00327                                 values =
00328                                    values ? mgd_format(mgd, pool, "$s,$i",
00329                                                        values,
00330                                                        new_topic) : mgd_format(mgd,
00331                                                                             pool,
00332                                                                             "$i",
00333                                                                             new_topic);
00334                         }
00335                         /* Replace 'up' field by new value */
00336                         else if (!strcmp("up", mgd_colname(object, i))) {
00337                                 values =
00338                                    values ? mgd_format(mgd, pool, "$s,$i",
00339                                                        values,
00340                                                        new_up) : mgd_format(mgd,
00341                                                                             pool,
00342                                                                             "$i",
00343                                                                             new_up);
00344                         }
00345                         else if ((!strcmp("name", mgd_colname(object, i))) && (force_name_change)) {
00346                             /* Add current timestamp to the article name in order to prevent duplicated names */
00347                                 values =
00348                                    values ? mgd_format(mgd, pool, "$s,'$Q ($Q)'",
00349                                                         values,
00350                                                         mgd_colvalue(object, i), asctime(gmtime(&now))) : 
00351                                             mgd_format(mgd, pool, "'$Q ($Q)'", 
00352                                                         mgd_colvalue(object, i), asctime(gmtime(&now)));
00353                                 force_name_change = 0;
00354                             
00355                         }
00356                         else {
00357                                 values = values ?
00358                                    mgd_format(mgd, pool, "$s,$q", values,
00359                                               mgd_colvalue(object,
00360                                                            i)) :
00361                                    mgd_format(mgd, pool, "$q", mgd_colvalue(object, i));
00362                         }
00363                         if (stmp)
00364                                 mgd_free_from_pool(pool, stmp);
00365                 }
00366         }
00367         /* 2. Create new object and update Repligard */
00368         i = mgd_create(mgd, "article", fields, "$s", values);
00369         if (i) {
00370                 CREATE_REPLIGARD(mgd, "article", i)
00371         }
00372         mgd_free_pool(pool);
00373         return i;
00374 }
00375 
00376 static int article_copier(midgard * mgd, int id, int level, void *xprm)
00377 {
00378         struct mgd_article_tree {
00379                 int topic;
00380                 int *ups;
00381         } *xparam=xprm;
00382         midgard_res *res;
00383         int i;
00384         int *up = xparam->ups;
00385         res = mgd_sitegroup_record(mgd, "*", "article", id);
00386         if (!res)
00387                 return 1;
00388         if (mgd_fetch(res)) {
00389                 up[level + 1] =
00390                         i = mgd_copy_object_article(mgd, res, xparam->topic,
00391                                    level ? up[level] : 0);
00392                         mgd_copy_all_parameters ( mgd,
00393                                                         strtol(mgd_column(res, "id"), NULL, 10),
00394                                                         "article", i);
00395                         mgd_copy_all_attachments ( mgd,
00396                                                         strtol(mgd_column(res, "id"), NULL, 10),
00397                                                         "article", i, NULL);
00398 #if HAVE_MIDGARD_MULTILANG
00399                         mgd_copy_all_content ( mgd, strtol(mgd_column(res, "id"), NULL, 10), "article", i);
00400                 
00401 #endif /* HAVE_MIDGARD_MULTILANG */
00402         }
00403         mgd_release(res);
00404         return 1;
00405 }
00406 
00407 int mgd_copy_article(midgard * mgd, int root, int newtopic)
00408 {
00409         struct mgd_article_tree {
00410                 int topic;
00411                 int *ups;
00412         } xparam;
00413         int newroot;
00414         xparam.topic=newtopic;
00415         /* This is ugly but how we could find number of replies instead? */
00416         xparam.ups = mgd_tree(mgd, "article", "up", root, 0, NULL);
00417         mgd_walk_table_tree(mgd, "article", "up", root, 0, 1, (void *) &xparam,
00418                                                                         article_copier, NULL);
00419         newroot = xparam.ups[1];
00420         free(xparam.ups);
00421         return newroot;
00422 }
00423 
00424 int mgd_copy_page_element(midgard * mgd, int id, int newpage)
00425 {
00426         midgard_res *res;
00427         int i = 0;
00428         assert(mgd);
00429         res = mgd_sitegroup_record(mgd, "*", "pageelement", id);
00430         if (!res)
00431                 return 0;
00432         if (mgd_fetch(res))
00433                 i = mgd_copy_object(mgd, res, "pageelement", "page",
00434                                     newpage ? newpage :
00435                                     strtol(mgd_column(res, "page"), NULL, 10));
00436         mgd_release(res);
00437 #if HAVE_MIDGARD_MULTILANG
00438         mgd_copy_all_parameters (mgd, id, "pageelement", i);
00439         mgd_copy_all_attachments (mgd, id, "pageelement", i, NULL);
00440         mgd_copy_all_content(mgd, id, "pageelement", i);
00441 #endif /* HAVE_MIDGARD_MULTILANG */
00442         return i;
00443 }
00444 
00445 int mgd_copy_element(midgard * mgd, int id, int newstyle)
00446 {
00447         midgard_res *res;
00448         int i = 0;
00449         assert(mgd);
00450         res = mgd_sitegroup_record(mgd, "*", "element", id);
00451         if (!res)
00452                 return 0;
00453         if (mgd_fetch(res))
00454                 i = mgd_copy_object(mgd, res, "element", "style",
00455                                     newstyle ? newstyle :
00456                                     strtol(mgd_column(res, "style"), NULL, 10));
00457         mgd_release(res);
00458 #if HAVE_MIDGARD_MULTILANG
00459         mgd_copy_all_parameters (mgd, id, "element", i);
00460         mgd_copy_all_attachments (mgd, id, "element", i, NULL);
00461         mgd_copy_all_content(mgd, id, "element", i);            
00462 #endif /* HAVE_MIDGARD_MULTILANG */
00463         return i;
00464 }
00465 
00466 int mgd_copy_snippet(midgard * mgd, int id, int newsnippetdir)
00467 {
00468         midgard_res *res;
00469         int i = 0;
00470         assert(mgd);
00471         res = mgd_sitegroup_record(mgd, "*", "snippet", id);
00472         if (!res)
00473                 return 0;
00474         if (mgd_fetch(res))
00475                 i = mgd_copy_object(mgd, res, "snippet", "up",
00476                                     newsnippetdir ? newsnippetdir :
00477                                     strtol(mgd_column(res, "up"), NULL, 10));
00478         mgd_release(res);
00479 #if HAVE_MIDGARD_MULTILANG
00480         mgd_copy_all_parameters (mgd, id, "snippet", i);
00481         mgd_copy_all_attachments (mgd, id, "snippet", i, NULL);
00482         mgd_copy_all_content(mgd, id, "snippet", i);            
00483 #endif /* HAVE_MIDGARD_MULTILANG */
00484         return i;
00485 }
00486 
00487 static int topic_copier(midgard * mgd, int id, int level, void *xparam)
00488 {
00489         midgard_res *res, *art_res;
00490         int *up = xparam;
00491         int i;
00492         res = mgd_sitegroup_record(mgd, "*", "topic", id);
00493         if (!res)
00494                 return 1;
00495         if (mgd_fetch(res)) {
00496                 up[level + 1] =
00497                    mgd_copy_object(mgd, res, "topic", "up",
00498                                    level ? up[level] : 0);
00499                 mgd_copy_all_parameters ( mgd, id, "topic", up[level + 1]);
00500                 mgd_copy_all_attachments ( mgd, id, "topic", up[level + 1], NULL);
00501                 art_res =
00502                    mgd_sitegroup_select(mgd, "id", "article", "article.topic=$i "
00503                                                    "AND article.up=0", "article.created", id);
00504                 if (art_res) {
00505                         while (mgd_fetch(art_res)) {
00506                                 i = mgd_copy_article(mgd, mgd_sql2int(art_res,0), up[level + 1] );
00507                         }
00508                         mgd_release(art_res);
00509                 }
00510         }
00511         mgd_release(res);
00512         return 1;
00513 }
00514 
00515 int mgd_copy_topic(midgard * mgd, int root)
00516 {
00517         int *ups, newroot;
00518         /* This is ugly but how we could find number of sub-topics instead? */
00519         ups = mgd_tree(mgd, "topic", "up", root, 0, NULL);
00520         mgd_walk_table_tree(mgd, "topic", "up", root, 0, 1, (void *) ups,
00521                                                                         topic_copier, NULL);
00522         newroot = ups[1];
00523         free(ups);
00524         return newroot;
00525 }
00526 
00527 static int event_copier(midgard * mgd, int id, int level, void *xparam)
00528 {
00529         midgard_res *res, *emb_res;
00530         int *up = xparam;
00531         int i;
00532         res = mgd_sitegroup_record(mgd, "*", "event", id);
00533         if (!res)
00534                 return 1;
00535         if (mgd_fetch(res)) {
00536                 up[level + 1] =
00537                    mgd_copy_object(mgd, res, "event", "up",
00538                                    level ? up[level] : 0);
00539                 mgd_copy_all_parameters ( mgd, id, "event", up[level + 1]);
00540                 mgd_copy_all_attachments ( mgd, id, "event", up[level + 1], NULL);
00541                 emb_res =
00542                    mgd_sitegroup_select(mgd, "*", "eventmember", "eid=$i",
00543                                         NULL, id);
00544                 if (emb_res) {
00545                         while (mgd_fetch(emb_res)) {
00546                                 i = mgd_copy_object(mgd, emb_res, "eventmember",
00547                                                 "eid", up[level + 1]);
00548                                 mgd_copy_all_parameters ( mgd,
00549                                                                 strtol(mgd_column(emb_res, "id"), NULL, 10),
00550                                                                 "eventmember", i);
00551                                 mgd_copy_all_attachments ( mgd,
00552                                                                 strtol(mgd_column(emb_res, "id"), NULL, 10),
00553                                                                 "eventmember", i, NULL);
00554                         }
00555                         mgd_release(emb_res);
00556                 }
00557         }
00558         mgd_release(res);
00559         return 1;
00560 }
00561 
00562 int mgd_copy_event(midgard * mgd, int root)
00563 {
00564         int *ups, newroot;
00565         /* This is ugly but how we could find number of sub-topics instead? */
00566         ups = mgd_tree(mgd, "event", "up", root, 0, NULL);
00567         mgd_walk_table_tree(mgd, "event", "up", root, 0, 1, (void *) ups,
00568                                                                                 event_copier, NULL);
00569         newroot = ups[1];
00570         free(ups);
00571         return newroot;
00572 }
00573 
00574 static int page_copier(midgard * mgd, int id, int level, void *xparam)
00575 {
00576         midgard_res *res, *elem_res;
00577         int *up = xparam;
00578         int i;
00579         res = mgd_sitegroup_record(mgd, "*", "page", id);
00580         if (!res)
00581                 return 1;
00582         if (mgd_fetch(res)) {
00583                 up[level + 1] =
00584                    mgd_copy_object(mgd, res, "page", "up",
00585                                    level  ? up[level] : 0);
00586 #if HAVE_MIDGARD_MULTILANG
00587           mgd_copy_all_content ( mgd, id, "page", up[level + 1] );
00588 #endif /* HAVE_MIDGARD_MULTILANG */
00589                 mgd_copy_all_parameters ( mgd, id, "page", up[level + 1]);
00590                 mgd_copy_all_attachments ( mgd, id, "page", up[level + 1], NULL);
00591                 elem_res =
00592                    mgd_sitegroup_select(mgd, "*", "pageelement", "page=$i",
00593                                         NULL, id);
00594                 if (elem_res) {
00595                         while (mgd_fetch(elem_res)) {
00596 #if ! HAVE_MIDGARD_MULTILANG
00597                                 i = mgd_copy_object(mgd, elem_res, "pageelement",
00598                                                 "page", up[level + 1]);
00599                                 mgd_copy_all_parameters ( mgd,
00600                                                                 strtol(mgd_column(elem_res, "id"), NULL, 10),
00601                                                                 "pageelement", i);
00602                                 mgd_copy_all_attachments ( mgd,
00603                                                                 strtol(mgd_column(elem_res, "id"), NULL, 10),
00604                                                                 "pageelement", i, NULL);
00605 #else /* HAVE_MIDGARD_MULTILANG */
00606                                 i = mgd_copy_page_element(mgd, strtol(mgd_column(elem_res, "id"), NULL, 10), up[level + 1]);
00607 #endif /* HAVE_MIDGARD_MULTILANG */
00608                         }
00609                         mgd_release(elem_res);
00610                 }
00611         }
00612         mgd_release(res);
00613         return 1;
00614 }
00615 
00616 int mgd_copy_page(midgard * mgd, int root)
00617 {
00618         int *ups, newroot;
00619         /* This is ugly but how we could find number of sub-pages instead? */
00620         ups = mgd_tree(mgd, "page", "up", root, 0, NULL);
00621         mgd_walk_table_tree(mgd, "page", "up", root, 0, 1, (void *) ups,
00622                                                                                 page_copier, NULL);
00623         newroot = ups[1];
00624         free(ups);
00625         return newroot;
00626 }
00627 
00628 static int style_copier(midgard * mgd, int id, int level, void *xparam)
00629 {
00630         midgard_res *res, *elem_res;
00631         int *up = xparam;
00632         int i;
00633         res = mgd_sitegroup_record(mgd, "*", "style", id);
00634         if (!res)
00635                 return 1;
00636         if (mgd_fetch(res)) {
00637                 up[level + 1] =
00638                    mgd_copy_object(mgd, res, "style", "up",
00639                                    level ? up[level] : 0);
00640                 mgd_copy_all_parameters ( mgd, id, "style", up[level + 1]);
00641                 mgd_copy_all_attachments ( mgd, id, "style", up[level + 1], NULL);
00642                 elem_res =
00643                    mgd_sitegroup_select(mgd, "*", "element", "element.style=$i",
00644                                         NULL, id);
00645                 if (elem_res) {
00646                         while (mgd_fetch(elem_res)) {
00647 #if ! HAVE_MIDGARD_MULTILANG
00648                                 i = mgd_copy_object(mgd, elem_res, "element",
00649                                                 "style", up[level + 1]);
00650                                 mgd_copy_all_parameters ( mgd,
00651                                                                 strtol(mgd_column(elem_res, "id"), NULL, 10),
00652                                                                 "element", i);
00653                                 mgd_copy_all_attachments ( mgd,
00654                                                                 strtol(mgd_column(elem_res, "id"), NULL, 10),
00655                                                                 "element", i, NULL);
00656 #else /* HAVE_MIDGARD_MULTILANG */
00657                                 i = mgd_copy_element(mgd, strtol(mgd_column(elem_res, "id"), NULL, 10), up[level + 1]);
00658 #endif /* HAVE_MIDGARD_MULTILANG */
00659                         }
00660                         mgd_release(elem_res);
00661                 }
00662         }
00663         mgd_release(res);
00664         return 1;
00665 }
00666 
00667 int mgd_copy_style(midgard * mgd, int root)
00668 {
00669         int *ups, newroot;
00670         /* This is ugly but how we could find number of sub-topics instead? */
00671         ups = mgd_tree(mgd, "style", "up", root, 0, NULL);
00672         mgd_walk_table_tree(mgd, "style", "up", root, 0, 1, (void *) ups,
00673                                                                         style_copier, NULL);
00674         newroot = ups[1];
00675         free(ups);
00676         return newroot;
00677 }
00678 
00679 static int snippetdir_copier(midgard * mgd, int id, int level, void *xparam)
00680 {
00681         midgard_res *res, *snip_res;
00682         int *up = xparam;
00683         int i;
00684         res = mgd_sitegroup_record(mgd, "*", "snippetdir", id);
00685         if (!res)
00686                 return 1;
00687         if (mgd_fetch(res)) {
00688                 up[level + 1] =
00689                    mgd_copy_object(mgd, res, "snippetdir", "up",
00690                                    level ? up[level] : 0);
00691                 mgd_copy_all_parameters ( mgd, id, "snippetdir", up[level + 1]);
00692                 mgd_copy_all_attachments ( mgd, id, "snippetdir", up[level + 1], NULL);
00693                 snip_res =
00694                    mgd_sitegroup_select(mgd, "*", "snippet", "up=$i", NULL, id);
00695                 if (snip_res) {
00696                         while (mgd_fetch(snip_res)) {
00697                                 i = mgd_copy_object(mgd, snip_res, "snippet", "up",
00698                                                 up[level + 1]);
00699                                 mgd_copy_all_parameters ( mgd,
00700                                                                 strtol(mgd_column(snip_res, "id"), NULL, 10),
00701                                                                 "snippet", i);
00702                                 mgd_copy_all_attachments ( mgd,
00703                                                                 strtol(mgd_column(snip_res, "id"), NULL, 10),
00704                                                                 "snippet", i, NULL);
00705 #if HAVE_MIDGARD_MULTILANG
00706                                 mgd_copy_all_content ( mgd,
00707                                                                 strtol(mgd_column(snip_res, "id"), NULL, 10),
00708                                                                 "snippet", i);
00709 #endif /* HAVE_MIDGARD_MULTILANG */
00710                         }
00711                         mgd_release(snip_res);
00712                 }
00713         }
00714         return 1;
00715         mgd_release(res);
00716 }
00717 
00718 int mgd_copy_snippetdir(midgard * mgd, int root)
00719 {
00720         int *ups, newroot;
00721         /* This is ugly but how we could find number of sub-topics instead? */
00722         ups = mgd_tree(mgd, "snippetdir", "up", root, 0, NULL);
00723         mgd_walk_table_tree(mgd, "snippetdir", "up", root, 0, 1, (void *) ups,
00724                                                                                         snippetdir_copier, NULL);
00725         newroot = ups[1];
00726         free(ups);
00727         return newroot;
00728 }
00729 
00730 #if HAVE_MIDGARD_MULTILANG
00731 static int mgd_delete_all_content(midgard * mgd, int id, const char * table) { 
00732   midgard_res * res;
00733   
00734   
00735   char table_i[256];
00736   int retcode = 0;
00737   assert (strlen(table) < 254);
00738   strcpy (table_i, table);
00739   strcat (table_i, "_i");
00740         
00741 
00742   res =
00743     mgd_ungrouped_select(mgd, "id", table_i, "$s.sid=$i",
00744                          NULL, table_i, id);
00745   if (res) {
00746     while (mgd_fetch(res)) {
00747       retcode &= mgd_delete(mgd, table_i, mgd_sql2int(res, 0));
00748       DELETE_REPLIGARD(mgd, table_i, mgd_sql2int(res, 0));
00749     }
00750   }             
00751   return retcode;
00752 }  
00753 
00754 #endif /* HAVE_MIDGARD_MULTILANG */
00755 static int mgd_delete_all_parameters(midgard * mgd, int id, const char * table)
00756 {
00757         midgard_res *res;
00758         res = mgd_sitegroup_select(mgd, "id", "record_extension",
00759                                                 "record_extension.tablename=$q AND record_extension.oid=$i",
00760                                                 NULL, table, id);
00761         if (res) {
00762                 while (mgd_fetch(res)) {
00763                         if(!mgd_delete(mgd, "record_extension", mgd_sql2int(res, 0))) return 0;
00764                         DELETE_REPLIGARD(mgd, "record_extension",
00765                                              mgd_sql2int(res, 0));
00766                 }
00767                 mgd_release(res);
00768         }
00769         return 1;
00770 }
00771 
00772 int mgd_delete_all_attachments(midgard * mgd, int id, const char * table)
00773 {
00774         midgard_res *res;
00775         midgard_pool * pool;
00776         char * path;
00777         res =
00778            mgd_sitegroup_select(mgd, "id,location,sitegroup", "blobs",
00779                                      "blobs.ptable=$q AND blobs.pid=$i",
00780                                          NULL, table, id);
00781         if (res) {
00782                 pool = mgd_alloc_pool();
00783                 while (mgd_fetch(res)) {
00784         /* Now we delete the blob file */
00785                         path = mgd_format(mgd, pool, "$s/$s", mgd_get_blobdir(mgd),
00786                                                         mgd_colvalue(res,1));
00787                         if (unlink(path) == 0 || errno == ENOENT) {
00788         /* First delete any parameters linked to the blob */
00789 #if HAVE_MIDGARD_QUOTA
00790                                 mgd_touch_recorded_quota(mgd, "blobsdata", mgd_sql2int(res,2));
00791                                 mgd_touch_recorded_quota(mgd, "wholesg", mgd_sql2int(res,2));
00792 #endif /* HAVE_MIDGARD_QUOTA */
00793                                 if(!mgd_delete_all_parameters ( mgd, mgd_sql2int(res, 0), "blobs")) 
00794                                         return 0;
00795                                 if(!mgd_delete(mgd, "blobs", mgd_sql2int(res, 0))) return 0;
00796                                 DELETE_REPLIGARD(mgd, "blobs", mgd_sql2int(res, 0));
00797                         }
00798                 }
00799                 mgd_free_pool(pool);
00800                 mgd_release(res);
00801         }
00802         return 1;
00803 }
00804 
00805 static int article_deleter(midgard * mgd, int id, int level, void *xparam)
00806 {
00807         int *retcode=xparam;
00808         
00809         /* First we delete all the attachments linked to the article */
00810         *retcode &= mgd_delete_all_attachments(mgd, id, "article");
00811         
00812         /* Now we delete the parameters linked to the article */
00813         *retcode &= mgd_delete_all_parameters(mgd, id, "article");
00814         
00815 #if HAVE_MIDGARD_MULTILANG
00816         /* Now we delete the content linked to the article */
00817         
00818         *retcode &= mgd_delete_all_content(mgd, id, "article");
00819         
00820 #endif /* HAVE_MIDGARD_MULTILANG */
00821         /* And finally, delete the article */
00822         *retcode &= mgd_delete(mgd, "article", id);
00823         DELETE_REPLIGARD(mgd, "article", id);
00824         return 1;
00825 }
00826 
00827 static int topic_deleter(midgard * mgd, int id, int level, void *xparam)
00828 {
00829         midgard_res *res;
00830         int *retcode=xparam;
00831         
00832         /* First we delete all the attachments linked to the topic */
00833         *retcode &= mgd_delete_all_attachments(mgd, id, "topic");
00834         
00835         /* Now we delete the parameters linked to the topic */
00836         *retcode &= mgd_delete_all_parameters(mgd, id, "topic");
00837         
00838         res = mgd_sitegroup_select(mgd, "id", "article", "article.topic=$i",
00839                                    "article.created", id);
00840         if (res) {
00841                 while (mgd_fetch(res)) {
00842         /* First we delete all the attachments linked to the article */
00843                         *retcode &= mgd_delete_all_attachments(mgd, mgd_sql2int(res, 0), "article");
00844         /* Now we delete the parameters linked to the article */
00845                         *retcode &= mgd_delete_all_parameters(mgd, mgd_sql2int(res, 0), "article");
00846 #if HAVE_MIDGARD_MULTILANG
00847                         *retcode &= mgd_delete_all_content(mgd, mgd_sql2int(res, 0), "article");
00848 #endif /* HAVE_MIDGARD_MULTILANG */
00849         /* Now we can safely delete the article */
00850                         *retcode &= mgd_delete(mgd, "article", mgd_sql2int(res, 0));
00851                         DELETE_REPLIGARD(mgd, "article", mgd_sql2int(res, 0));
00852                 }
00853                 mgd_release(res);
00854         }
00855         /* And finally, delete the topic */
00856         *retcode &= mgd_delete(mgd, "topic", id);
00857         DELETE_REPLIGARD(mgd, "topic", id);
00858         return 1;
00859 }
00860 
00861 int mgd_delete_element(midgard * mgd, int id) {
00862   int retcode=1;
00863   /* First we delete all the attachments linked to the element */
00864   retcode &= mgd_delete_all_attachments(mgd, id, "element");
00865   
00866   /* Now we delete the parameters linked to the element */
00867   retcode &= mgd_delete_all_parameters(mgd, id, "element");
00868 #if HAVE_MIDGARD_MULTILANG
00869   retcode &= mgd_delete_all_content(mgd, id, "element");
00870 #endif
00871   retcode &= mgd_delete(mgd, "element", id);
00872   DELETE_REPLIGARD(mgd, "element", id);
00873 
00874   return retcode;
00875 }
00876 
00877 
00878 int mgd_delete_page_element(midgard * mgd, int id) {
00879   int retcode=1;
00880   /* First we delete all the attachments linked to the pageelement */
00881   retcode &= mgd_delete_all_attachments(mgd, id, "pageelement");
00882   
00883   /* Now we delete the parameters linked to the pageelement */
00884   retcode &= mgd_delete_all_parameters(mgd, id, "pageelement");
00885 #if HAVE_MIDGARD_MULTILANG
00886   retcode &= mgd_delete_all_content(mgd, id, "pageelement");
00887 #endif
00888   retcode &= mgd_delete(mgd, "pageelement", id);
00889   DELETE_REPLIGARD(mgd, "pageelement", id);
00890 
00891   return retcode;
00892 }
00893 
00894 int mgd_delete_article(midgard * mgd, int root)
00895 {
00896         int retcode=1;
00897         mgd_walk_table_tree(mgd, "article", "up", root, 0, 1, &retcode,
00898                                                                                 article_deleter, NULL);
00899         return retcode;
00900 }
00901 
00902 int mgd_delete_topic(midgard * mgd, int root)
00903 {
00904         int retcode=1;
00905         mgd_walk_table_tree(mgd, "topic", "up", root, 0, 1, &retcode,
00906                                                                                 topic_deleter, NULL);
00907         return retcode;
00908 }
00909 
00910 static int page_deleter(midgard * mgd, int id, int level, void *xparam)
00911 {
00912         midgard_res *res;
00913         int *retcode=xparam;
00914 
00915 #if HAVE_MIDGARD_PAGELINKS
00916         // DG: does repligard handle pagelinks ??
00917         // DELETE_REPLIGARD(mgd, "pagelink", mgd_exists_id(mgd, "up=$d", id));
00918         mgd_query(mgd, "DELETE FROM pagelink WHERE up=$d", id);
00919 #endif
00920         /* First we delete all the attachments linked to the page */
00921         *retcode &= mgd_delete_all_attachments(mgd, id, "page");
00922         
00923         /* Now we delete the parameters linked to the page */
00924         *retcode &= mgd_delete_all_parameters(mgd, id, "page");
00925         /* Deleting pageelements now */
00926         res =
00927            mgd_sitegroup_select(mgd, "id", "pageelement", "pageelement.page=$i",
00928                                 NULL, id);
00929         if (res) {
00930                 while (mgd_fetch(res)) {
00931         /* First we delete all the attachments linked to the pageelement */
00932                         *retcode &= mgd_delete_all_attachments(mgd, mgd_sql2int(res, 0), "pageelement");
00933         /* Now we delete the parameters linked to the pageelement */
00934                         *retcode &= mgd_delete_all_parameters(mgd, mgd_sql2int(res, 0), "pageelement");
00935         /* Now we can safely delete the pageelement */
00936                         *retcode &= mgd_delete(mgd, "pageelement", mgd_sql2int(res, 0));
00937                         DELETE_REPLIGARD(mgd, "pageelement", mgd_sql2int(res, 0));
00938 #if HAVE_MIDGARD_MULTILANG
00939                         *retcode &= mgd_delete_all_content(mgd, mgd_sql2int(res, 0), "pageelement");
00940 #endif /* HAVE_MIDGARD_MULTILANG */
00941                 }
00942                 mgd_release(res);
00943         }
00944 
00945 #if HAVE_MIDGARD_MULTILANG
00946         /* delete content */
00947         *retcode &= mgd_delete_all_content(mgd, id, "page");
00948                   
00949 #endif /* HAVE_MIDGARD_MULTILANG */
00950         /* And finally, delete the page */
00951         *retcode &= mgd_delete(mgd, "page", id);
00952         DELETE_REPLIGARD(mgd, "page", id);
00953         return 1;
00954 }
00955 
00956 int mgd_delete_page(midgard * mgd, int root)
00957 {
00958         int retcode=1;
00959         mgd_walk_table_tree(mgd, "page", "up", root, 0, 1, &retcode,
00960                                                                                 page_deleter, NULL);
00961         return retcode;
00962 }
00963 
00964 static int snippetdir_deleter(midgard * mgd, int id, int level, void *xparam)
00965 {
00966         midgard_res *res;
00967         int *retcode=xparam;
00968 
00969         /* First we delete all the attachments linked to the snippetdir */
00970         *retcode &= mgd_delete_all_attachments(mgd, id, "snippetdir");
00971         
00972         /* Now we delete the parameters linked to the snippetdir */
00973         *retcode &= mgd_delete_all_parameters(mgd, id, "snippetdir");
00974         /* Deleting snippets now */
00975         res = mgd_sitegroup_select(mgd, "id", "snippet", "snippet.up=$i",
00976                                    "snippet.name", id);
00977         if (res) {
00978                 while (mgd_fetch(res)) {
00979         /* First we delete all the attachments linked to the snippet */
00980                         *retcode &= mgd_delete_all_attachments(mgd, mgd_sql2int(res, 0), "snippet");
00981         /* Now we delete the parameters linked to the snippet */
00982                         *retcode &= mgd_delete_all_parameters(mgd, mgd_sql2int(res, 0), "snippet");
00983         /* Now we can safely delete the snippet */
00984                         *retcode &= mgd_delete(mgd, "snippet", mgd_sql2int(res, 0));
00985                         DELETE_REPLIGARD(mgd, "snippet",
00986                                              mgd_sql2int(res, 0));
00987                 }
00988                 mgd_release(res);
00989         }
00990         /* And finally, delete the snippetdir */
00991         *retcode &= mgd_delete(mgd, "snippetdir", id);
00992         DELETE_REPLIGARD(mgd, "snippetdir", id);
00993         return 1;
00994 }
00995 
00996 int mgd_delete_snippetdir(midgard * mgd, int root)
00997 {
00998         int retcode=1;
00999         mgd_walk_table_tree(mgd, "snippetdir", "up", root, 0, 1, &retcode,
01000                                                                                 snippetdir_deleter, NULL);
01001         return retcode;
01002 }
01003 
01004 static int event_deleter(midgard * mgd, int id, int level, void *xparam)
01005 {
01006         midgard_res *res;
01007         int *retcode=xparam;
01008 
01009         /* First we delete all the attachments linked to the event */
01010         *retcode &= mgd_delete_all_attachments(mgd, id, "event");
01011         
01012         /* Now we delete the parameters linked to the event */
01013         *retcode &= mgd_delete_all_parameters(mgd, id, "event");
01014         /* Deleting eventmembers now */
01015         res = mgd_sitegroup_select(mgd, "id", "eventmember", "eventmember.eid=$i",
01016                                    NULL, id);
01017         if (res) {
01018                 while (mgd_fetch(res)) {
01019         /* First we delete all the attachments linked to the eventmember */
01020                         *retcode &= mgd_delete_all_attachments(mgd, mgd_sql2int(res, 0), "eventmember");
01021         /* Now we delete the parameters linked to the eventmember */
01022                         *retcode &= mgd_delete_all_parameters(mgd, mgd_sql2int(res, 0), "eventmember");
01023         /* Now we can safely delete the eventmember */
01024                         *retcode &= mgd_delete(mgd, "eventmember", mgd_sql2int(res, 0));
01025                         DELETE_REPLIGARD(mgd, "eventmember",
01026                                              mgd_sql2int(res, 0));
01027                 }
01028                 mgd_release(res);
01029         }
01030         /* And finally, delete the event */
01031         *retcode &= mgd_delete(mgd, "event", id);
01032         DELETE_REPLIGARD(mgd, "event", id);
01033         return 1;
01034 }
01035 
01036 int mgd_delete_event(midgard * mgd, int root)
01037 {
01038         int retcode=1;
01039         mgd_walk_table_tree(mgd, "event", "up", root, 0, 1, &retcode,
01040                                                                                 event_deleter, NULL);
01041         return retcode;
01042 }
01043 
01044 static int style_deleter(midgard * mgd, int id, int level, void *xparam)
01045 {
01046         midgard_res *res;
01047         int *retcode=xparam;
01048 
01049         /* First we delete all the attachments linked to the style */
01050         *retcode &= mgd_delete_all_attachments(mgd, id, "style");
01051         
01052         /* Now we delete the parameters linked to the style */
01053         *retcode &= mgd_delete_all_parameters(mgd, id, "style");
01054         /* Deleting elements now */
01055         res = mgd_sitegroup_select(mgd, "id", "element", "element.style=$i",
01056                                    "element.id", id);
01057         if (res) {
01058                 while (mgd_fetch(res)) {
01059         /* First we delete all the attachments linked to the element */
01060                         *retcode &= mgd_delete_all_attachments(mgd, mgd_sql2int(res, 0), "element");
01061         /* Now we delete the parameters linked to the element */
01062                         *retcode &= mgd_delete_all_parameters(mgd, mgd_sql2int(res, 0), "element");
01063         /* Now we can safely delete the element */
01064                         *retcode &= mgd_delete(mgd, "element", mgd_sql2int(res, 0));
01065                         DELETE_REPLIGARD(mgd, "element", mgd_sql2int(res, 0));
01066                 }
01067                 mgd_release(res);
01068         }
01069         /* And finally, delete the style */
01070         *retcode &= mgd_delete(mgd, "style", id);
01071         DELETE_REPLIGARD(mgd, "style", id);
01072         return 1;
01073 }
01074 
01075 int mgd_delete_style(midgard * mgd, int root)
01076 {
01077         int retcode=1;
01078         mgd_walk_table_tree(mgd, "style", "up", root, 0, 1, &retcode,
01079                                                                                 style_deleter, NULL);
01080         return retcode;
01081 }
01082 
01083 int mgd_move_object(midgard * mgd, const char *table, const char *upfield,
01084                     int id, int newup)
01085 {
01086         return mgd_update(mgd, table, id, "$s=$i", upfield, newup);
01087 }
01088 
01089 /* mgd_parse_path
01090     Scans records in a tables 'table' and 'uptable' and returns IDs of
01091     an object queried in path and its uplink.
01092     upfield     -       name of field in 'table' points to uplink
01093     namefiled   -       name of field in 'table' contains 'name' of an object
01094                         ('article' contains two names - 'name' and 'title',
01095                         and we can search by both)
01096     If id == NULL then will assume that only 'uptable' table should be scanned
01097     and path contains only info about structure ('directories'). 
01098     E.g. if path = '/topic1/topic2/topic3/article'
01099     returns id = ID of 'article' under 'topic3' and
01100             up = ID of 'topic3'
01101     if path = '/topic1/topic2/topic3' and id = NULL
01102     return up = ID of 'topic3'
01103     
01104     0 if query was successful, 1 in other case
01105     
01106     Could be used for quering any tables that have 'id', 'up', and 'name' fields.
01107 */
01108 char *mgd_strtok(char *str, char c)
01109 {
01110         static char *ptr=NULL;
01111         char *p;
01112         if(str) ptr=str;
01113         if(*ptr==c) ptr++; 
01114         p=ptr;
01115         if(!(ptr=strchr(p,c))) return NULL;
01116         *ptr='\0'; ptr++;
01117         return p;
01118 }
01119 
01120 int mgd_parse_path(midgard * mgd, const char *path, const char *uptable,
01121                    const char *table, const char *upfield,
01122                    const char *namefield, int *id, int *up)
01123 {
01124         char *tok, *filename, *part;
01125         midgard_res *res;
01126         midgard_pool *pool;
01127         int upval;
01128         part = NULL;
01129         pool = mgd_alloc_pool();
01130         if (id) {
01131                 part = strrchr(path, '/');
01132                 if (part) {
01133                         part++;
01134                         filename = mgd_strndup(pool, path, part - path);
01135                 }
01136                 else {
01137                         /* '/' not found - path is not absolute */
01138                         if (pool)
01139                                 mgd_free_pool(pool);
01140                         return 1;
01141                 }
01142         }
01143         else {
01144                 filename = mgd_strdup(pool, path);
01145         }
01146         upval = 0;
01147 
01148         /* Traverse the path structure */
01149         for (tok = mgd_strtok(filename, '/'); tok; tok = mgd_strtok(NULL, '/')) {
01150                 /* Find the correct uplink */
01151                 res = mgd_sitegroup_select
01152                    (mgd, "id", uptable, "up=$d AND name=$q", NULL, upval, tok);
01153                 if (!res || !mgd_fetch(res)) {
01154                         if (res)
01155                                 mgd_release(res);
01156                         upval = -1;
01157                         break;
01158                 }
01159                 upval = atoi(mgd_colvalue(res, 0));
01160                 mgd_release(res);
01161         }
01162 
01163         if (pool)
01164                 mgd_free_pool(pool);
01165 
01166         if (upval == -1) {
01167                 /* some path component not found */
01168                 g_free(filename);
01169                 return 1;
01170         }
01171 
01172         (*up) = upval;
01173 
01174         if (id) {
01175 
01176                 (*id) =
01177                    mgd_exists_id(mgd, table, "$s=$d AND $s=$q", upfield, upval,
01178                               namefield, part);
01179         }
01180 
01181         g_free(filename);
01182         return 0;
01183 }
01184 
01185 int mgd_parse_path_with_hook(midgard * mgd, const char *path,
01186                              const char *uptable, const char *table,
01187                              const char *upfield, const char *namefield,
01188                              int *id, int *up, midgard_pathfunc hook)
01189 {
01190         char *tok, *filename, *part;
01191         midgard_res *res;
01192         midgard_pool *pool;
01193         int upval, idval;
01194         part = NULL;
01195         pool = mgd_alloc_pool();
01196         if (id) {
01197                 part = strrchr(path, '/');
01198                 if (part) {
01199                         part++;
01200                         filename = mgd_strndup(pool, path, part - path);
01201                 }
01202                 else {
01203                         /* '/' not found - path is not absolute */
01204                         if (pool)
01205                                 mgd_free_pool(pool);
01206                         return 1;
01207                 }
01208         }
01209         else {
01210                 filename = mgd_strdup(pool, path);
01211         }
01212 
01213         upval = 0;
01214 
01215         /* Traverse the path structure */
01216         for (tok = mgd_strtok(filename, '/'); tok; tok = mgd_strtok(NULL, '/')) {
01217                 /* Find the correct uplink */
01218                 res = mgd_sitegroup_select
01219                    (mgd, "id", uptable, "up=$d AND name=$q", NULL, upval, tok);
01220                 if (!res || !mgd_fetch(res)) {
01221                         if (res)
01222                                 mgd_release(res);
01223                         idval =
01224                            hook(mgd, uptable, tok, upval, 0,
01225                                 MIDGARD_PATH_ELEMENT_NOTEXISTS);
01226                         if (idval)
01227                                 goto query;
01228                         upval = -1;
01229                         break;
01230                 }
01231                 idval = atoi(mgd_colvalue(res, 0));
01232                 mgd_release(res);
01233                 hook(mgd, uptable, tok, upval, idval,
01234                      MIDGARD_PATH_ELEMENT_EXISTS);
01235               query:
01236                 upval = idval;
01237         }
01238 
01239         if (pool)
01240                 mgd_free_pool(pool);
01241 
01242         if (upval == -1) {
01243                 /* some path component not found */
01244                 return 1;
01245         }
01246 
01247         (*up) = upval;
01248 
01249         if (id) {
01250 
01251                 (*id) =
01252                    mgd_exists_id(mgd, table, "$s=$d AND $s=$q", upfield, upval,
01253                               namefield, part);
01254                 if ((*id) == 0) {
01255                         (*id) = hook(mgd, table, part, upval, 0, MIDGARD_PATH_OBJECT_NOTEXISTS);
01256                 }
01257                 else {
01258                         hook(mgd, table, part, upval, 0,
01259                              MIDGARD_PATH_OBJECT_EXISTS);
01260                 }
01261         }
01262 
01263         return 0;
01264 }
01265 
01266 int mgd_has_dependants(midgard * mgd, int id, char * table)
01267 {
01268     if(mgd_exists_id(mgd,"record_extension","oid=$d AND tablename=$q", id, table))
01269             return 1;
01270     if(mgd_exists_id(mgd,"blobs","pid=$d AND ptable=$q", id, table))
01271             return 1;
01272     return 0;
01273 }
01274 

Generated on Thu Feb 22 06:15:18 2007 for midgard-core by  doxygen 1.4.6