[subversion:17] Working lazy-creation hooks for index.html and feed.atom.

  • From: TimBray@kenai.com
  • To: commits@mod-atom.kenai.com
  • Subject: [subversion:17] Working lazy-creation hooks for index.html and feed.atom.
  • Date: Wed, 5 Nov 2008 20:27:16 +0000 (GMT)

Repository: subversion
Revision:   17
Author:     tim.bray@sun.com
Date:       2008-11-05 20:27:10 UTC

Log Message:
-----------
Working lazy-creation hooks for index.html and feed.atom.  Step 1,
modularize out the refresh_collection code.

Modified Paths:
--------------
    src/mod_atom.hsrc/mod_atom.c

Diffs:
-----
Index: src/mod_atom.c
===================================================================
--- src/mod_atom.c      (revision 16)
+++ src/mod_atom.c      (revision 17)
@@ -144,9 +144,11 @@
 
 /* A bunch of regexes for sorting incoming URIs into buckets
  */
-typedef struct pub_patterns_t {
+typedef struct pub_patterns_t
+{
     ap_regex_t * entry;
     ap_regex_t * collection;
+    ap_regex_t * feed;
     ap_regex_t * media_object;
     ap_regex_t * entries_space;
     ap_regex_t * extras_space;
@@ -156,12 +158,14 @@
 /* A publication can be regular, or a meta-pub, or a sub-pub created
  *  by posting to a meta-pub
  */
-typedef enum pub_type_t {
+typedef enum pub_type_t
+{
     REGULAR_PUB, META_PUB, SUB_PUB
 } pub_type_t;
 
 /* a publication, corresponding to an AtomPub directive in config */
-typedef struct pub_t {
+typedef struct pub_t
+{
     char * path; /* the path used by the world to refer to this pub */
     char * dir; /* the directory where the pub's data is rooted */
     char * title; /* the pub's human-readable title */
@@ -174,7 +178,8 @@
 } pub_t;
 
 /* fake low-rent continuation in run_fp_template */
-typedef enum template_state_t {
+typedef enum template_state_t
+{
     Writing,
     Bypassing,
     Done
@@ -186,13 +191,14 @@
  *  However, it does have the benefit of reducing almost all calls to
just
  *  a couple of arguments, making things easier to read.
  */
-typedef struct entry_t {
+typedef struct entry_t
+{
     apr_xml_doc * xml; /* DOM of the entry */
-    char * path;       /* the part after ...(atom|pub) & with no
extension */
-    pub_t * pub;       /* the publication */
-    char * coll_base;  /* dir for this entry's collection & feed */
-    char * id;         /* unique id */
-    int size;          /* in bytes, for media objects only */
+    char * path; /* the part after ...(atom|pub) & with no extension
*/
+    pub_t * pub; /* the publication */
+    char * coll_base; /* dir for this entry's collection & feed */
+    char * id; /* unique id */
+    int size; /* in bytes, for media objects only */
     text_construct_type_t type_of_content;
 } entry_t;
 
@@ -241,6 +247,8 @@
 static int put(request_rec * r, pub_t * pub);
 static int put_entry(request_rec * r, pub_t * pub, entry_t * e);
 static int put_media(request_rec * r, pub_t * pub, entry_t * e);
+static char * refresh_collection(char * coll_base, pub_t * pub,
+                                 apr_pool_t * pool, apr_finfo_t *
coll_finfo);
 static int replace_media(request_rec * r, entry_t * e);
 static char * rm_rf(apr_pool_t * pool, char * dir);
 static int save_new_entry(request_rec * r, entry_t * e);
@@ -301,7 +309,8 @@
                          "Can't initialize publication '%s' at URI
'%s': '%s'",
                          pub->title, pub->path, problem);
             continue;
-        } else {
+        }
+        else {
             ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
                          "Publication '%s' at '%s' successfully
loaded!",
                          pub->title, pub->path);
@@ -341,7 +350,7 @@
     publist = (pub_t *) pubs_from_config->elts;
     for (i = 0; i < pubs_from_config->nelts - 1; i++)
         if (is_prefix(path, publist[i].path) ||
-                is_prefix(publist[i].path, path)) {
+            is_prefix(publist[i].path, path)) {
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,
                          "One publication prefixes another: '%s' and
'%s'",
                          path, publist[i].path);
@@ -396,11 +405,10 @@
  */
 static int map_to_storage(request_rec * r) {
     pub_t * pub = find_pub(r);
-    apr_finfo_t * finfo;
+    apr_finfo_t finfo;
     apr_status_t status;
     char * s;
     char * post_atom;
-    int basics =  APR_FINFO_MTIME | APR_FINFO_INODE | APR_FINFO_SIZE;
 
     if (pub == NULL)
         return DECLINED;
@@ -409,16 +417,15 @@
     s = is_prefix(r->uri, pub->path) + 1;
     if ((post_atom = is_prefix(s, ATOM_DIR)))
         s = atom_join(r->pool, pub->dir, PUB_DIR, post_atom, NULL);
-    else 
+    else
         s = atom_join(r->pool, pub->dir, s, NULL);
     r->canonical_filename = r->filename = s; /* why 'canonical' too?
*/
 
     /* it seems we have to fill in r->finfo too */
-    finfo = (apr_finfo_t *) apr_palloc(r->pool, sizeof (apr_finfo_t));
-    finfo->name = r->filename;
-    status = apr_stat(finfo, r->filename, basics, r->pool);
-    r->finfo = *finfo;
+    finfo.name = r->filename;
+    status = apr_stat(&finfo, r->filename, BASICS, r->pool);
 
+    /* assuming the target filename exists */
     if (status == APR_SUCCESS) {
 
         /* if we're getting a collection, check the timestamp file to
see
@@ -426,45 +433,22 @@
          */
         if ((r->method_number == M_GET) &&
                 MATCHES(pub->patterns->collection, r->uri)) {
-           apr_finfo_t ts_info;
             char * coll_base = dir_of(r->pool, r->filename);
-           char * ts_name;
-           apr_status_t ts_status;
-           int rebuild = 1;
+            char * prob = refresh_collection(coll_base, pub, r->pool,
&finfo);
 
-           ts_name = atom_join(r->pool, coll_base, TIMESTAMP_FILE,
NULL);
-           ts_status = apr_stat(&ts_info, ts_name, basics, r->pool);
+            if (prob)
+                return server_error(r, APR_SUCCESS, "In GET
collection, %s",
+                                    prob);
 
-            /* note, rebuild even if the timestamp date and the
collection
-             *  date are the same.  Stupid unix 1-second mtime
granularity...
-             */
-           if (ts_status == APR_SUCCESS && ts_info.mtime <
finfo->mtime)
-               rebuild = 0;
-           
-           if (rebuild) {
-               char * problem;
-               problem = write_collection(r->pool, pub, coll_base,
-                                          DEFAULT_ENTRIES_IN_FEED);
-               if (problem)
-                   return server_error(r, APR_SUCCESS,
-                                       "Can't refresh collection '%s':
%s",
-                                       r->filename, problem);
-
-                /* of course, now the finfo is different */
-                apr_stat(finfo, r->filename, basics, r->pool);
-                r->finfo = *finfo;
-           }
-       }
+        }
+        r->finfo = finfo;
         return OK;
     }
-       
-    /* It has to exist... */
-    if (status == APR_SUCCESS)
-        return OK;
 
-    /* ...  unless this is a PUT into the extras space */
+    /* Initial stat failed. This may not be a problem.
+     * It has to exist... unless this is a PUT into the extras space
*/
     if ((r->method_number == M_PUT) &&
-            MATCHES(pub->patterns->extras_space, r->uri))
+        MATCHES(pub->patterns->extras_space, r->uri))
         return OK;
 
     return HTTP_NOT_FOUND;
@@ -491,15 +475,15 @@
      */
     if (!is_atom_path) {
 
-       if (r->method_number == M_POST || r->method_number == M_PUT ||
-           r->method_number == M_DELETE)
-           return HTTP_FORBIDDEN;
+        if (r->method_number == M_POST || r->method_number == M_PUT ||
+            r->method_number == M_DELETE)
+            return HTTP_FORBIDDEN;
 
-       if (MATCHES(pub->patterns->entry, r->uri))
-           return HTTP_FORBIDDEN;
+        if (MATCHES(pub->patterns->entry, r->uri))
+            return HTTP_FORBIDDEN;
 
-       if (MATCHES(pub->patterns->collection, r->uri))
-           return HTTP_FORBIDDEN;
+        if (MATCHES(pub->patterns->collection, r->uri))
+            return HTTP_FORBIDDEN;
     }
     return DECLINED;
 }
@@ -537,7 +521,7 @@
     if (MATCHES(pub->patterns->media_object, r->uri)) {
 
         char * mt_name =
-                apr_psprintf(r->pool, "%s.%s", r->filename,
MEDIA_TYPE_SUFFIX);
+            apr_psprintf(r->pool, "%s.%s", r->filename,
MEDIA_TYPE_SUFFIX);
         char * problem;
         char * media_type;
 
@@ -569,7 +553,7 @@
         return DECLINED;
 
     if (r->method_number == M_GET)
-       return get(r, pub);
+        return get(r, pub);
 
 
     switch (r->method_number) {
@@ -602,12 +586,14 @@
             start = find_num(&a);
             if (start == -1)
                 return HTTP_NOT_FOUND;
-        } else if (strncmp(a, "count=", 6) == 0) {
+        }
+        else if (strncmp(a, "count=", 6) == 0) {
             a += 6;
             count = find_num(&a);
             if (count == -1)
                 return HTTP_NOT_FOUND;
-        } else
+        }
+        else
             return HTTP_NOT_FOUND;
 
         if (*a == '&')
@@ -657,12 +643,14 @@
         return HTTP_UNSUPPORTED_MEDIA_TYPE;
     if (MATCHES(pub->patterns->entries_space, r->uri)) {
         if (strcmp(media_type, "application/atom+xml;type=entry") != 0
&&
-                strcmp(media_type, "application/atom+xml") != 0)
+            strcmp(media_type, "application/atom+xml") != 0)
             return HTTP_UNSUPPORTED_MEDIA_TYPE;
         return post_entry(r, &entry);
-    } else if (MATCHES(pub->patterns->media_space, r->uri)) {
+    }
+    else if (MATCHES(pub->patterns->media_space, r->uri)) {
         return post_media(r, entry.pub);
-    } else
+    }
+    else
         return server_error(r, APR_SUCCESS,
                             "Weird media type '%s' on POST '%s'",
                             media_type, r->uri);
@@ -745,8 +733,8 @@
         /* sanity-check media-type */
         media_type = (char *) apr_table_get(r->headers_in,
"Content-Type");
         if ((media_type == NULL) ||
-                (strcmp(media_type, "application/atom+xml;type=entry")
!= 0 &&
-                    strcmp(media_type, "application/atom+xml") != 0))
+            (strcmp(media_type, "application/atom+xml;type=entry") !=
0 &&
+            strcmp(media_type, "application/atom+xml") != 0))
             return HTTP_UNSUPPORTED_MEDIA_TYPE;
 
         is_entry = 1;
@@ -755,9 +743,11 @@
         if ((status = ap_xml_parse_input(r, &(entry.xml))) != OK)
             return server_error(r, status, "Can't parse XML PUT
body");
 
-    } else if (MATCHES(pub->patterns->media_object, r->uri)) {
+    }
+    else if (MATCHES(pub->patterns->media_object, r->uri)) {
         is_entry = 0;
-    } else {
+    }
+    else {
         apr_table_set(r->headers_out, "Allow", "GET, HEAD");
         return HTTP_METHOD_NOT_ALLOWED;
     }
@@ -797,7 +787,7 @@
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "ETag mismatch on PUT (%s vs %s), rejected",
                      if_match, etag);
-       unlock_file(mutex);
+        unlock_file(mutex);
         return HTTP_PRECONDITION_FAILED;
     }
 
@@ -827,7 +817,7 @@
         char * linkname;
         char * filename = entry_filename(r->pool, &entry);
 
-       dir = atom_join(r->pool, entry.coll_base, 
+        dir = atom_join(r->pool, entry.coll_base,
                         yyyymmdd_at(apr_time_now(), r->pool), NULL);
         if ((problem = atom_dir(dir, r->pool)))
             return server_error(r, APR_SUCCESS,
@@ -847,7 +837,7 @@
 
     /* update the public-facing html & feed & front-page if required
*/
     if ((entry.type_of_content != MEDIA_TYPE) &&
-            MATCHES(pub->patterns->entries_space, r->uri))
+        MATCHES(pub->patterns->entries_space, r->uri))
         write_html_entry(r, &entry);
 
     return status;
@@ -875,12 +865,13 @@
                 return server_error(r, APR_SUCCESS,
                                     "failed to delete directory '%s'",
                                     r->filename);
-        } else {
-           if ((status = apr_file_remove(r->filename, r->pool)) !=
APR_SUCCESS)
-               return server_error(r, status,
-                                   "failed to delete file '%s'",
r->filename);
-       }
-       return HTTP_NO_CONTENT;
+        }
+        else {
+            if ((status = apr_file_remove(r->filename, r->pool)) !=
APR_SUCCESS)
+                return server_error(r, status,
+                                    "failed to delete file '%s'",
r->filename);
+        }
+        return HTTP_NO_CONTENT;
     }
 
     /* can't delete media resources directly */
@@ -915,24 +906,25 @@
             return server_error(r, status,
                                 "Can't remove media resource at '%s'",
bits);
 
-    } else {
+    }
+    else {
         /* not a media-link entry.  Thus there may be an HTML or text
file 
-        *  to lose; but there may not be, if the content@type was none
of
-        *  'html', 'xhtml', or 'text'.
-        * We could parse the entry and look at the content type
+         *  to lose; but there may not be, if the content@type was
none of
+         *  'html', 'xhtml', or 'text'.
+         * We could parse the entry and look at the content type
          *  to figure out the exact name, but why not just try
deleting any
-        *  of them.
+         *  of them.
          */
-       char * extensions[] = { ".html", ".text", ".html", NULL };
-       int i;
-       char * base =  apr_pstrdup(r->pool, r->filename);
-       *(rindex(base, '.')) = 0;
+        char * extensions[] = {".html", ".text", ".html", NULL};
+        int i;
+        char * base = apr_pstrdup(r->pool, r->filename);
+        *(rindex(base, '.')) = 0;
 
-       for (i = 0; extensions[i] && !html_removed; i++) {
-           char * target = apr_pstrcat(r->pool, base, extensions[i],
NULL);
-           status = apr_file_remove(target, r->pool);
-           html_removed = html_removed || (status == APR_SUCCESS);
-       }
+        for (i = 0; extensions[i] && !html_removed; i++) {
+            char * target = apr_pstrcat(r->pool, base, extensions[i],
NULL);
+            status = apr_file_remove(target, r->pool);
+            html_removed = html_removed || (status == APR_SUCCESS);
+        }
     }
 
     /* delete on a META will delete a whole publication.  I hope they
@@ -954,21 +946,21 @@
         namespaces = (char * *) entry->namespaces->elts;
         for (child = entry->root->first_child; child; child =
child->next) {
             if (strcmp(namespaces[child->ns], ATOM_NS) == 0 &&
-                    strcmp(child->name, "link") == 0) {
+                strcmp(child->name, "link") == 0) {
                 apr_xml_attr * a;
-               char * href = NULL;
-               char * rel = "";
+                char * href = NULL;
+                char * rel = "";
 
                 for (a = child->attr; a; a = a->next) {
                     if (a->ns == APR_XML_NS_NONE) {
-                       if (strcmp(a->name, "rel") == 0)
-                           rel = (char *) a->value;
-                       else if (strcmp(a->name, "href") == 0)
-                           href = (char *) a->value;
-                   }
+                        if (strcmp(a->name, "rel") == 0)
+                            rel = (char *) a->value;
+                        else if (strcmp(a->name, "href") == 0)
+                            href = (char *) a->value;
+                    }
                 }
-               if (strcmp(rel, "publication") == 0)
-                   sub_pub = href;
+                if (strcmp(rel, "publication") == 0)
+                    sub_pub = href;
             }
         }
 
@@ -1018,6 +1010,43 @@
 
 /********************* Utilities ***********************/
 
+/* Check (by looking at a timestamp) whether a collection file needs
to be
+ *  updated, and update it if necessary.  Fill in the finfo_t for the
+ *  collection.
+ */
+static char * refresh_collection(char * coll_base, pub_t * pub,
+                                 apr_pool_t * pool, apr_finfo_t *
coll_finfo) {
+    apr_finfo_t ts_finfo;
+    apr_status_t ts_status, coll_status;
+    char * ts_fn = atom_join(pool, coll_base, TIMESTAMP_FILE, NULL);
+    char * coll_fn = atom_join(pool, coll_base, COLLECTION_FILE,
NULL);
+    int refresh = 1;
+    char * problem = NULL;
+
+    coll_status = apr_stat(coll_finfo, coll_fn, BASICS, pool);
+    ts_status = apr_stat(&ts_finfo, ts_fn, BASICS, pool);
+
+    /* note, rebuild even if the timestamp date and the collection
+     *  date are the same.  Stupid unix 1-second mtime granularity...
+     */
+    if (coll_status == APR_SUCCESS && ts_status == APR_SUCCESS &&
+        ts_finfo.mtime < coll_finfo->mtime)
+        refresh = 0;
+
+    if (refresh) {
+        problem = write_collection(pool, pub, coll_base,
+                                   DEFAULT_ENTRIES_IN_FEED);
+        if (problem == NULL) {
+            coll_status = apr_stat(coll_finfo, coll_fn, BASICS, pool);
+            if (coll_status != APR_SUCCESS)
+                problem = apr_psprintf(pool,
+                                       "Can't stat refreshed
collection '%s",
+                                       coll_fn);
+        }
+    }
+    return problem;
+}
+
 /* write a timestamp indicating that a collection needs to be updated
  */
 static void timestamp(char * dir, apr_pool_t * pool) {
@@ -1036,30 +1065,31 @@
     apr_status_t status;
 
     status = apr_file_open(&fp, mutex_name, APR_FOPEN_WRITE |
APR_FOPEN_CREATE,
-                          PERMS, p);
+                           PERMS, p);
     if (status == APR_SUCCESS) {
-       status = apr_file_lock(fp, APR_FLOCK_EXCLUSIVE);
-       if (status != APR_SUCCESS) 
-           apr_file_close(fp);
+        status = apr_file_lock(fp, APR_FLOCK_EXCLUSIVE);
+        if (status != APR_SUCCESS)
+            apr_file_close(fp);
     }
 
     if (status == APR_SUCCESS)
-       *mutex_p = fp;
+        *mutex_p = fp;
     return status;
 }
+
 static void unlock_file(void * mutex) {
     apr_file_t * fp = (apr_file_t *) mutex;
     if (apr_file_unlock(fp) != APR_SUCCESS)
-       fprintf(stderr, "UNLOCK FAILED\n");
+        fprintf(stderr, "UNLOCK FAILED\n");
     if (apr_file_close(fp) != APR_SUCCESS)
-       fprintf(stderr, "CLOSE FAILED\n");
+        fprintf(stderr, "CLOSE FAILED\n");
 }
 
 /* apr equivalent of random() */
 static long arandom() {
     long ret;
-    long mask = 1 << ((sizeof(long) * 8) - 1);
-    apr_generate_random_bytes((unsigned char *) &ret, sizeof(long));
+    long mask = 1 << ((sizeof (long) * 8) - 1);
+    apr_generate_random_bytes((unsigned char *) & ret, sizeof (long));
     return ret & ~mask;
 }
 
@@ -1124,7 +1154,8 @@
             if (apr_file_remove(fname, pool) != APR_SUCCESS)
                 return apr_psprintf(pool, "Can't remove file '%s' in
rm_rf",
                                     fname);
-        } else if (finfo.filetype == APR_DIR) {
+        }
+        else if (finfo.filetype == APR_DIR) {
             if (strcmp(finfo.name, ".") == 0 || strcmp(finfo.name,
"..") == 0)
                 continue;
 
@@ -1198,7 +1229,7 @@
     char * msg;
 
     if (status != APR_SUCCESS) {
-       char * em = error_message(r->pool, status);
+        char * em = error_message(r->pool, status);
 
         fmt = apr_pstrcat(r->pool, fmt, ": ", NULL);
         fmt = apr_pstrcat(r->pool, fmt, em, NULL);
@@ -1226,7 +1257,7 @@
     };
 
     if (e->ns == APR_XML_NS_NONE ||
-            strcmp((char *) namespaces[e->ns], ATOM_NS) != 0)
+        strcmp((char *) namespaces[e->ns], ATOM_NS) != 0)
         return 0;
 
     for (i = 0; text_constructs[i]; i++)
@@ -1247,7 +1278,8 @@
     if (*a == 0 || *a == '&') {
         *a_p = a;
         return sofar;
-    } else
+    }
+    else
         return -1;
 }
 
@@ -1353,8 +1385,8 @@
     entry_names = (char * *) apr_pcalloc(pool, count * sizeof (char
*));
 
     for (problem = atom_iter_next(iter, &entry_name), i =
entries_in_feed = 0;
-            entry_name && (!problem) && (entries_in_feed < (start +
count));
-            problem = atom_iter_next(iter, &entry_name),
entries_in_feed++) {
+        entry_name && (!problem) && (entries_in_feed < (start +
count));
+        problem = atom_iter_next(iter, &entry_name),
entries_in_feed++) {
         if (entries_in_feed >= start)
             entry_names[i++] = entry_name;
     }
@@ -1377,16 +1409,16 @@
         char * entry_body;
 
         if ((problem = atom_snarf(entry_names[i], &entry_body, pool)))
{
-           /* in the situation where a file is found by the iterator
but
-            *  doesn't seem to be here, this seems to be just
filesystem
-            *  churn, we have to survive it
-            */
-           if (entry_body == SNARF_NOT_FOUND)
-               continue;
-           else
-               return apr_psprintf(pool, "Can't read entry '%s': %s",
-                                   entry_names[i], problem);
-       }
+            /* in the situation where a file is found by the iterator
but
+             *  doesn't seem to be here, this seems to be just
filesystem
+             *  churn, we have to survive it
+             */
+            if (entry_body == SNARF_NOT_FOUND)
+                continue;
+            else
+                return apr_psprintf(pool, "Can't read entry '%s': %s",
+                                    entry_names[i], problem);
+        }
 
         if (atom_genx_send(writer, entry_body) != GENX_SUCCESS)
             return "Can't write to collection";
@@ -1415,28 +1447,28 @@
 
     status = apr_file_open(&fp, tempname, APR_FOPEN_WRITE |
APR_FOPEN_CREATE,
                            PERMS, pool);
-    if (status != APR_SUCCESS) 
+    if (status != APR_SUCCESS)
         return apr_psprintf(pool, "Can't open collection tempfile
'%s': %s",
                             tempname, error_message(pool, status));
 
     writer = atom_genx_file_writer(pool, fp, &problem);
-    if (!writer) 
+    if (!writer)
         return apr_psprintf(pool, "Can't start XML writer: '%s'",
problem);
 
     ret = NULL;
     problem = generate_collection(dirname, pool, pub, writer, 0,
size);
     if (problem)
         ret = apr_psprintf(pool, "Can't generate collection in '%s':
%s",
-                          dirname, problem);
+                           dirname, problem);
     apr_file_flush(fp);
     apr_file_close(fp);
 
     if (ret == NULL) {
-       status = apr_file_rename(tempname, filename, pool);
-       if (status != APR_SUCCESS) 
+        status = apr_file_rename(tempname, filename, pool);
+        if (status != APR_SUCCESS)
             ret = apr_psprintf(pool, "Can't rename '%s' to '%s': %s",
                                tempname, filename,
-                              error_message(pool, status));
+                               error_message(pool, status));
     }
     return ret;
 }
@@ -1609,13 +1641,13 @@
     if (r->parsed_uri.port_str != NULL)
         return atom_join(r->pool,
                          apr_psprintf(r->pool, "%s://%s:%s",
ap_http_scheme(r),
-                                     r->hostname,
+                                      r->hostname,
                                       r->parsed_uri.port_str),
                          relative, NULL);
     else
         return atom_join(r->pool,
                          apr_psprintf(r->pool, "%s://%s",
ap_http_scheme(r),
-                                     r->hostname),
+                                      r->hostname),
                          relative, NULL);
 }
 
@@ -1754,17 +1786,17 @@
                         apr_xml_elem * entry, apr_xml_doc * doc,
                         genxWriter gw) {
     apr_xml_elem * title = NULL, * summary = NULL, * content = NULL,
-       * author = NULL;
+        * author = NULL;
     char * link = NULL;
     char * wanted[] = {
-       "title", "summary", "content", "author", NULL
+        "title", "summary", "content", "author", NULL
     };
     apr_xml_elem * * children[] = {
-       &title, &summary, &content, &author
+        &title, &summary, &content, &author
     };
 
     if (is_draft(r->pool, doc))
-       return;
+        return;
 
     atom_xml_children(doc, entry, ATOM_NS, wanted, children);
     link = atom_xml_link_href(doc, entry, "alternate");
@@ -1779,7 +1811,8 @@
         genxAddAttributeLiteral(gw, NULL, (utf8) "href", (utf8) link);
         atom_filter_text_construct(r->pool, doc, title, gw, 1);
         genxEndElement(gw);
-    } else
+    }
+    else
         atom_filter_text_construct(r->pool, doc, title, gw, 1);
     genxEndElement(gw); /* <div class="atom-entry-title> */
     genxAddCharacter(gw, '\n');
@@ -1798,12 +1831,12 @@
 
     if (author) {
         apr_xml_elem * name = atom_xml_child(doc, author, ATOM_NS,
"name");
-       
+
         if (name) {
             genxStartElementLiteral(gw, NULL, (utf8) "div");
             genxAddAttributeLiteral(gw, NULL, (utf8) "class",
                                     (utf8) "atom-entry-author");
-           genxAddText(gw, (utf8) element_text(name, r->pool));
+            genxAddText(gw, (utf8) element_text(name, r->pool));
             genxEndElement(gw); /* <div clss='atom-entry-author"> */
             genxAddCharacter(gw, '\n');
         }
@@ -1907,7 +1940,7 @@
                     if (strcmp(a->name, "label") == 0)
                         label = (utf8) a->value;
                     else if (strcmp(a->name, "term") == 0 &&
-                            label == NULL)
+                        label == NULL)
                         label = (utf8) a->value;
                 }
             }
@@ -1924,9 +1957,11 @@
         }
         genxEndElement(gw); /* </ul> */
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "content") == 0) {
+    }
+    else if (strcmp(elem->name, "content") == 0) {
         htmlify_text_construct(entry, "content", atom_ns, fields, gw,
r->pool);
-    } else if (strcmp(elem->name, "contributors") == 0) {
+    }
+    else if (strcmp(elem->name, "contributors") == 0) {
         /* put contributors in a comma-separated list, hyperlinked
names */
         apr_xml_elem * * contribs = (apr_xml_elem * *) fields->elts;
         count = find_entry_fields("contributor", atom_ns, entry,
fields);
@@ -1943,7 +1978,8 @@
         }
         genxEndElement(gw); /* </div> */
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "entry-author") == 0) {
+    }
+    else if (strcmp(elem->name, "entry-author") == 0) {
         apr_xml_elem * author;
         count = find_entry_fields("author", atom_ns, entry, fields);
         if (count != 1)
@@ -1955,7 +1991,8 @@
         htmlify_person(author, gw, atom_ns, r->pool);
         genxEndElement(gw); /* </author> */
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "entry-script") == 0) {
+    }
+    else if (strcmp(elem->name, "entry-script") == 0) {
         genxStartElementLiteral(gw, NULL, (constUtf8) "script");
         genxAddAttributeLiteral(gw, NULL, (utf8) "type", (utf8)
"text/javascript");
         genxAddAttributeLiteral(gw, NULL, (utf8) "src",
@@ -1964,7 +2001,8 @@
                                                  ENTRY_JS, NULL));
         genxEndElement(gw);
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "entry-stylesheet") == 0) {
+    }
+    else if (strcmp(elem->name, "entry-stylesheet") == 0) {
         genxStartElementLiteral(gw, NULL, (constUtf8) "link");
         genxAddAttributeLiteral(gw, NULL, (utf8) "rel", (utf8)
"stylesheet");
         genxAddAttributeLiteral(gw, NULL, (utf8) "href",
@@ -1973,23 +2011,34 @@
                                                  ENTRY_CSS, NULL));
         genxEndElement(gw);
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "front-author") == 0) {
-    } else if (strcmp(elem->name, "front-links") == 0) {
-    } else if (strcmp(elem->name, "front-script") == 0) {
-    } else if (strcmp(elem->name, "front-stylesheet") == 0) {
-    } else if (strcmp(elem->name, "generator") == 0) {
+    }
+    else if (strcmp(elem->name, "front-author") == 0) {
+    }
+    else if (strcmp(elem->name, "front-links") == 0) {
+    }
+    else if (strcmp(elem->name, "front-script") == 0) {
+    }
+    else if (strcmp(elem->name, "front-stylesheet") == 0) {
+    }
+    else if (strcmp(elem->name, "generator") == 0) {
         genxComment(gw, (utf8) GENERATOR);
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "logo") == 0) {
-    } else if (strcmp(elem->name, "pub-title") == 0) {
+    }
+    else if (strcmp(elem->name, "logo") == 0) {
+    }
+    else if (strcmp(elem->name, "pub-title") == 0) {
         genxAddText(gw, (utf8) get_title(entry->pub, r->pool));
-    } else if (strcmp(elem->name, "published") == 0) {
+    }
+    else if (strcmp(elem->name, "published") == 0) {
         htmlify_date(entry, "published", atom_ns, gw, fields,
r->pool);
-    } else if (strcmp(elem->name, "rights") == 0) {
+    }
+    else if (strcmp(elem->name, "rights") == 0) {
         htmlify_text_construct(entry, "rights", atom_ns, fields, gw,
r->pool);
-    } else if (strcmp(elem->name, "title") == 0) {
+    }
+    else if (strcmp(elem->name, "title") == 0) {
         htmlify_text_construct(entry, "title", atom_ns, fields, gw,
r->pool);
-    } else if (strcmp(elem->name, "updated") == 0) {
+    }
+    else if (strcmp(elem->name, "updated") == 0) {
         htmlify_date(entry, "updated", atom_ns, gw, fields, r->pool);
     }
 }
@@ -2068,7 +2117,8 @@
                                                  FEED_FILE, NULL));
         genxEndElement(gw);
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "front-script") == 0) {
+    }
+    else if (strcmp(elem->name, "front-script") == 0) {
         genxStartElementLiteral(gw, NULL, (utf8) "script");
         genxAddAttributeLiteral(gw, NULL, (utf8) "type", (utf8)
"text/javascript");
         genxAddAttributeLiteral(gw, NULL, (utf8) "src",
@@ -2078,7 +2128,8 @@
                                                  FRONT_PAGE_JS,
NULL));
         genxEndElement(gw);
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "front-stylesheet") == 0) {
+    }
+    else if (strcmp(elem->name, "front-stylesheet") == 0) {
         genxStartElementLiteral(gw, NULL, (constUtf8) "link");
         genxAddAttributeLiteral(gw, NULL, (utf8) "rel", (utf8)
"stylesheet");
         genxAddAttributeLiteral(gw, NULL, (utf8) "href",
@@ -2087,21 +2138,25 @@
                                                  FRONT_PAGE_CSS,
NULL));
         genxEndElement(gw);
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "generator") == 0) {
+    }
+    else if (strcmp(elem->name, "generator") == 0) {
         genxComment(gw, (utf8)
                     "Brought to you by the awesome power of XML, "
                     "the Atom Publishing Protocol, the Apache Web
server, "
                     "and mod_atom.");
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "pub-author") == 0) {
+    }
+    else if (strcmp(elem->name, "pub-author") == 0) {
         genxStartElementLiteral(gw, NULL, (utf8) "div");
         genxAddAttributeLiteral(gw, NULL, (utf8) "class", (utf8)
"atom-author");
         genxAddText(gw, (utf8) get_author(pub, r->pool));
         genxEndElement(gw); /* </author> */
         genxAddCharacter(gw, '\n');
-    } else if (strcmp(elem->name, "pub-title") == 0) {
+    }
+    else if (strcmp(elem->name, "pub-title") == 0) {
         genxAddText(gw, (utf8) get_title(pub, r->pool));
-    } else if (strcmp(elem->name, "updated") == 0) {
+    }
+    else if (strcmp(elem->name, "updated") == 0) {
         genxStartElementLiteral(gw, NULL, (utf8) "div");
         genxAddAttributeLiteral(gw, NULL, (utf8) "class",
                                 (utf8) "atom-date-updated");
@@ -2159,7 +2214,7 @@
     apr_xml_doc * template;
 
     if (!is_html_enabled(r->pool, pub))
-       return;
+        return;
 
     html_tmp = apr_psprintf(r->pool, "%s/%s%ld-%ld", coll_base,
                             TEMP_PREFIX, arandom(), arandom());
@@ -2178,14 +2233,14 @@
 
     /* open tempfiles which will become index.html and feed */
     status = apr_file_open(&html_fp, html_tmp,
-                          APR_FOPEN_WRITE | APR_FOPEN_CREATE, PERMS,
r->pool);
+                           APR_FOPEN_WRITE | APR_FOPEN_CREATE, PERMS,
r->pool);
     if (status != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "Can't create tempfile for front page '%s'",
html_tmp);
         return;
     }
     status = apr_file_open(&feed_fp, feed_tmp,
-                          APR_FOPEN_WRITE | APR_FOPEN_CREATE, PERMS,
r->pool);
+                           APR_FOPEN_WRITE | APR_FOPEN_CREATE, PERMS,
r->pool);
     if (status != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "Can't create tempfile for public feed '%s'",
feed_tmp);
@@ -2260,22 +2315,22 @@
     /* OK, now we'll run through the entries from the feed */
     namespaces = (char * *) coll->namespaces->elts;
     for (count = 0, entry = coll->root->first_child;
-            entry && (count < DEFAULT_ENTRIES_IN_FEED);
-            entry = entry->next) {
+        entry && (count < DEFAULT_ENTRIES_IN_FEED);
+        entry = entry->next) {
         text_construct_type_t type = TEXT_TYPE;
-       apr_xml_elem * content;
+        apr_xml_elem * content;
 
         /* skip non-entries */
         if (entry->ns == APR_XML_NS_NONE ||
-                strcmp(namespaces[entry->ns], ATOM_NS) != 0 ||
-                strcmp(entry->name, "entry") != 0)
+            strcmp(namespaces[entry->ns], ATOM_NS) != 0 ||
+            strcmp(entry->name, "entry") != 0)
             continue;
 
         /* for each atom:entry in the feed */
         /* if the type on its content is other than MEDIA_TYPE, we'll
keep it */
-       content = atom_xml_child(coll, entry, ATOM_NS, "content");
-       if (content)
-           type = atom_text_construct_type(content);
+        content = atom_xml_child(coll, entry, ATOM_NS, "content");
+        if (content)
+            type = atom_text_construct_type(content);
 
         if (type == MEDIA_TYPE)
             continue;
@@ -2315,9 +2370,9 @@
     char * draft_val = "no";
 
     if ((control = atom_xml_child(doc, doc->root, APP_NS, "control")))
{
-       apr_xml_elem * draft;
-       if ((draft = atom_xml_child(doc, control, APP_NS, "draft")))
-           draft_val = element_text(draft, pool);
+        apr_xml_elem * draft;
+        if ((draft = atom_xml_child(doc, control, APP_NS, "draft")))
+            draft_val = element_text(draft, pool);
     }
 
     return !strcmp(draft_val, "yes");
@@ -2351,9 +2406,9 @@
      * 2. the file x/options/html does not exist
      */
     if (is_draft(r->pool, e->xml))
-       return;
+        return;
     if (!is_html_enabled(r->pool, e->pub))
-       return;
+        return;
 
     filename = atom_join(r->pool, e->pub->dir, PUB_DIR, e->path,
NULL);
     filename = apr_pstrcat(r->pool, filename, extension, NULL);
@@ -2371,45 +2426,46 @@
 
     /* type could be HTML, XHTML, or TEXT.  If TEXT, just dump the
sucker */
     if (e->type_of_content == TEXT_TYPE) {
-       apr_xml_elem * content;
-       char * problem;
+        apr_xml_elem * content;
+        char * problem;
 
-       content = atom_xml_child(e->xml, e->xml->root, ATOM_NS,
"content");
-       if ((problem = to_file(tempname, element_text(content,
r->pool),
-                              r->pool)))
-           ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
-                        "Can't write text file '%s': %s", tempname,
problem);
-    } else {
+        content = atom_xml_child(e->xml, e->xml->root, ATOM_NS,
"content");
+        if ((problem = to_file(tempname, element_text(content,
r->pool),
+                               r->pool)))
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                         "Can't write text file '%s': %s", tempname,
problem);
+    }
+    else {
 
-       /* HTML */
-       status = apr_file_open(&fp, tempname,
-                              APR_FOPEN_WRITE | APR_FOPEN_CREATE,
PERMS,
-                              r->pool);
-       if (status != APR_SUCCESS) {
-           ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
-                        "Can't create HTML file '%s'", tempname);
-           return;
-       }
-       writer = atom_genx_file_writer(r->pool, fp, &problem);
-       if (!writer) {
-           ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
-                        "Can't make XML writer for '%s': %s",
-                        tempname, problem);
-           return;
-       }
+        /* HTML */
+        status = apr_file_open(&fp, tempname,
+                               APR_FOPEN_WRITE | APR_FOPEN_CREATE,
PERMS,
+                               r->pool);
+        if (status != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                         "Can't create HTML file '%s'", tempname);
+            return;
+        }
+        writer = atom_genx_file_writer(r->pool, fp, &problem);
+        if (!writer) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                         "Can't make XML writer for '%s': %s",
+                         tempname, problem);
+            return;
+        }
 
-       gw = atom_genx_get_writer(writer);
+        gw = atom_genx_get_writer(writer);
 
-       template_fn = atom_join(r->pool, e->pub->dir, PUB_DIR,
EXTRAS_DIR,
-                               TEMPLATES_DIR, ENTRY_TEMPLATE, NULL);
-       if (xnarf(template_fn, &template, r->pool) != APR_SUCCESS) {
-           ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
-                        "Can't parse entry template '%s'",
template_fn);
-           return;
-       }
-       run_e_template(gw, template, r, e);
-       apr_file_flush(fp);
-       apr_file_close(fp);
+        template_fn = atom_join(r->pool, e->pub->dir, PUB_DIR,
EXTRAS_DIR,
+                                TEMPLATES_DIR, ENTRY_TEMPLATE, NULL);
+        if (xnarf(template_fn, &template, r->pool) != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                         "Can't parse entry template '%s'",
template_fn);
+            return;
+        }
+        run_e_template(gw, template, r, e);
+        apr_file_flush(fp);
+        apr_file_close(fp);
     }
 
     /* rename tempfile to final target */
@@ -2417,7 +2473,7 @@
     if (status != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "Can't rename '%s' to '%s': %s", tempname,
filename,
-                    error_message(r->pool, status));
+                     error_message(r->pool, status));
     }
 
     update_public_site(r, e->pub, e->coll_base);
@@ -2496,7 +2552,7 @@
                                           int ns_ind, char * type,
                                           char * content) {
     apr_xml_elem * e =
-            (apr_xml_elem *) apr_pcalloc(r->pool, sizeof
(apr_xml_elem));
+        (apr_xml_elem *) apr_pcalloc(r->pool, sizeof (apr_xml_elem));
 
     e->ns = ns_ind;
     e->name = type;
@@ -2575,11 +2631,11 @@
     int i;
     int atom_ns = -1, app_ns = -1, xhtml_ns = -1;
     apr_xml_elem * updated = NULL, * author = NULL,
-            * id = NULL, * edited = NULL, * alt_link = NULL, *
edit_link = NULL;
+        * id = NULL, * edited = NULL, * alt_link = NULL, * edit_link =
NULL;
     apr_xml_elem * root = e->xml->root;
     char * mtime;
[trimmed for length]


[subversion:17] Working lazy-creation hooks for index.html and feed.atom.

TimBray 11/05/2008
  • Mysql
  • Glassfish
  • Jruby
  • Rails
  • Nblogo
Terms of Use; Privacy Policy;
© 2010, Oracle Corporation and/or its affiliates
(revision 20120127.ac94057)
 
 
Close
loading
Please Confirm
Close