@@ -107,7 +107,7 @@ HttpBodyFactory::fabricate_with_old_api(const char *type, HttpTransact::State *c
107107 Log::error (" BODY_FACTORY: suppressing '%s' response for url '%s'" , type, url);
108108 }
109109 unlock ();
110- return ( nullptr ) ;
110+ return nullptr ;
111111 }
112112 // ////////////////////////////////////////////////////////////////////////////////
113113 // if language-targeting activated, get client Accept-Language & Accept-Charset //
@@ -400,7 +400,7 @@ HttpBodyFactory::fabricate(StrList *acpt_language_list, StrList *acpt_charset_li
400400 char *buffer;
401401 const char *pType = context->txn_conf ->body_factory_template_base ;
402402 const char *set;
403- HttpBodyTemplate *t;
403+ HttpBodyTemplate *t = NULL ;
404404 HttpBodySet *body_set;
405405 char template_base[PATH_NAME_MAX];
406406
@@ -416,12 +416,12 @@ HttpBodyFactory::fabricate(StrList *acpt_language_list, StrList *acpt_charset_li
416416 // if error body suppressed, return NULL
417417 if (is_response_suppressed (context)) {
418418 Debug (" body_factory" , " error suppression enabled, returning NULL template" );
419- return ( nullptr ) ;
419+ return nullptr ;
420420 }
421421 // if custom error pages are disabled, return NULL
422422 if (!enable_customizations) {
423423 Debug (" body_factory" , " customization disabled, returning NULL template" );
424- return ( nullptr ) ;
424+ return nullptr ;
425425 }
426426
427427 // what set should we use (language target if enable_customizations == 2)
@@ -437,25 +437,30 @@ HttpBodyFactory::fabricate(StrList *acpt_language_list, StrList *acpt_charset_li
437437 }
438438 if (pType != nullptr && 0 != *pType && 0 != strncmp (pType, " NONE" , 4 )) {
439439 sprintf (template_base, " %s_%s" , pType, type);
440- } else {
441- sprintf (template_base, " %s" , type);
440+ t = find_template (set, template_base, &body_set);
441+ // Check for default alternate.
442+ if (t == nullptr ) {
443+ sprintf (template_base, " %s_default" , pType);
444+ t = find_template (set, template_base, &body_set);
445+ }
442446 }
443- // see if we have a custom error page template
444- t = find_template (set, template_base, &body_set);
447+
448+ // Check for base customizations if specializations didn't work.
445449 if (t == nullptr ) {
446450 t = find_template (set, type, &body_set); // this executes if the template_base is wrong and doesn't exist
447451 }
452+
448453 if (t == nullptr ) {
449454 Debug (" body_factory" , " can't find template, returning NULL template" );
450- return ( nullptr ) ;
455+ return nullptr ;
451456 }
452457
453458 *content_language_return = body_set->content_language ;
454459 *content_charset_return = body_set->content_charset ;
455460
456461 // build the custom error page
457462 buffer = t->build_instantiated_buffer (context, buffer_length_return);
458- return ( buffer) ;
463+ return buffer;
459464}
460465
461466// LOCKING: must be called with lock taken
@@ -692,8 +697,9 @@ HttpBodyFactory::load_body_set_from_directory(char *set_name, char *tmpl_dir)
692697 DIR *dir;
693698 int status;
694699 struct stat stat_buf;
695- char path[MAXPATHLEN + 1 ];
696700 struct dirent *dirEntry;
701+ char path[MAXPATHLEN + 1 ];
702+ static const char BASED_DEFAULT[] = " _default" ;
697703
698704 // //////////////////////////////////////////////
699705 // ensure we can open tmpl_dir as a directory //
@@ -702,7 +708,7 @@ HttpBodyFactory::load_body_set_from_directory(char *set_name, char *tmpl_dir)
702708 Debug (" body_factory" , " load_body_set_from_directory(%s)" , tmpl_dir);
703709 dir = opendir (tmpl_dir);
704710 if (dir == nullptr ) {
705- return ( nullptr ) ;
711+ return nullptr ;
706712 }
707713
708714 // ///////////////////////////////////////////
@@ -713,7 +719,7 @@ HttpBodyFactory::load_body_set_from_directory(char *set_name, char *tmpl_dir)
713719 status = stat (path, &stat_buf);
714720 if ((status < 0 ) || !S_ISREG (stat_buf.st_mode )) {
715721 closedir (dir);
716- return ( nullptr ) ;
722+ return nullptr ;
717723 }
718724 Debug (" body_factory" , " found '%s'" , path);
719725
@@ -729,14 +735,19 @@ HttpBodyFactory::load_body_set_from_directory(char *set_name, char *tmpl_dir)
729735
730736 while ((dirEntry = readdir (dir))) {
731737 HttpBodyTemplate *tmpl;
738+ size_t d_len = strlen (dirEntry->d_name );
732739
733740 // /////////////////////////////////////////////////////////////
734- // all template files have name of the form <type>#<subtype> //
741+ // all template files must have a file name of the form //
742+ // - <type>#<subtype> //
743+ // - <base>_<type>#<subtype> //
744+ // - <base>_default [based default] //
745+ // - default [global default] //
735746 // /////////////////////////////////////////////////////////////
736747
737- if ((strchr (dirEntry->d_name , ' #' ) == nullptr ) && (strcmp (dirEntry->d_name , " default" ) != 0 )) {
748+ if (!(nullptr != strchr (dirEntry->d_name , ' #' ) || (0 == strcmp (dirEntry->d_name , " default" )) ||
749+ (d_len >= sizeof (BASED_DEFAULT) && 0 == strcmp (dirEntry->d_name + d_len - (sizeof (BASED_DEFAULT) - 1 ), BASED_DEFAULT))))
738750 continue ;
739- }
740751
741752 snprintf (path, sizeof (path), " %s/%s" , tmpl_dir, dirEntry->d_name );
742753 status = stat (path, &stat_buf);
0 commit comments