summaryrefslogtreecommitdiff
path: root/catalog.cfg
blob: 6dc75bce0e608a0cb58f186f54573d0313646bca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
#==========================================================================#

# catalog.cfg

#==========================================================================#

## We want to hide the .gdbm, .autonumber, .numeric, .sql, .db files
## Needs to go before VariableDatabase
DatabaseDefault HIDE_AUTO_FILES 1

# Read in some initial default variables from a directory. These are
# larger ones -- they could conceivably be maintained in the
# VariableDatabase but might be easier to maintain in a file, especially
# for development.
#
# Notable settings: COMMON_MENU, COPYRIGHT
#
DirConfig Variable variables

# Read in large variables or dynamic variables from a series
# of files in a directory
VariableDatabase variable

# Read in site-specific variables from a database (if any).
# Used to create a information for a temporarily transferred
# catalog, i.e. for development.
#
# Ignored if file doesn't exist.
VariableDatabase site

# Warn if any important modules or usertags are missing.

Require module Digest::MD5    "Need %s %s for better cache keys."
Require module Digest::Bcrypt "Required if you are going to use bcrypt passwords for UserDB."
Require module Crypt::Random  "Required if you are going to use bcrypt passwords for UserDB."
Require module Safe::Hole     "Need %s %s for embedded perl object access."

# Encoding
Variable MV_UTF8 1
Variable MV_HTTP_CHARSET UTF-8

#==========================================================================#

# Can send various files outside the catalog directory, for disk partition
# reasons, for example.

ParseVariables  Yes

ifdef LOGDIR
ErrorFile       __LOGDIR__/error.log
AsciiTrack      __LOGDIR__/tracking.asc
#TrackFile       __LOGDIR__/usertrack
ErrorDestination  "Run jobs group=%s pid=%s"       __LOGDIR__/jobs_run.log
ErrorDestination  "Finished jobs group=%s pid=%s"  __LOGDIR__/jobs_run.log
endif

ifndef LOGDIR
AsciiTrack      logs/tracking.asc
#TrackFile       logs/usertrack
endif

ifdef CACHEDIR
SessionDatabase __CACHEDIR__/session
ScratchDir      __CACHEDIR__/tmp
endif

ifndef CACHEDIR
SessionDatabase session
ScratchDir      tmp
endif

ifdef RUNDIR
RunDir  __RUNDIR__
endif

#==========================================================================#

# Database setup

ParseVariables  Yes

ifndef INDEV
DatabaseDefault LOG_ERROR_SESSION 0
endif

## Quote all identifiers to avoid name clash issues and SQL injection attacks
DatabaseDefault QUOTE_IDENTIFIERS 1

ifdef MYSQL
DatabaseDefault NO_ASCII_INDEX 1
include dbconf/mysql/mysql.cfg
endif

ifdef PGSQL
DatabaseDefault NO_ASCII_INDEX 1
include dbconf/pgsql/pgsql.cfg
endif

ifdef SQLITE
DatabaseDefault NO_ASCII_INDEX 1
include dbconf/sqlite/sqlite.cfg
endif

# Default DBM if nothing else defined
ifndef SOME_DATABASE
Require We_need_a_database  "%s, must have either MySQL or Postgres"
endif

### Uncomment these for DBI sessions
# SessionType DBI
# SessionDB   sessions
# Database sessions sessions.txt __SQLDSN__
# NoImport sessions

### You can change the length of the session ID. Must be integer between
### 8 and 32.
# Limit  session_id_length  8

#==========================================================================#

# The URLs which are written to refer back to our catalog.

<ParseVariables Yes>

VendURL    http://__SERVER_NAME____CGI_URL__
SecureURL  __SECURE_SERVER____CGI_URL__

ifndef SECURE_ENABLE
SecureURL  http://__SERVER_NAME____CGI_URL__
endif

# Set the image path for relative images
ImageDir          __IMAGE_DIR__/

</ParseVariables>

#==========================================================================#

# Here we set up the catalog theme.

<ParseVariables Yes>

##
## Here we pick up the region variables like LEFTONLY_TOP and LEFTONLY_BOTTOM.
##
## Commenting; new variables TOP and BOTTOM will be defined in variable directory.
## No longer going to need multiple leftright_top, leftonly_top, etc; will be
## defined in "display_class" in each page.

#DirConfig Variable templates/regions

# TRAFFIC is defined system-wide in interchange.cfg. When in low-traffic
# mode, variables are dynamic -- i.e. when you change the region file
# the page changes. Otherwise a reconfig must be done to change the
# variable.
#
# Careful, this can change the way *other* variables are interpreted.
ifdef @TRAFFIC =~ /low/i
Pragma dynamic_variables
Pragma dynamic_variables_file_only
endif

# Provide some links for the admin to edit pages if we have the UI in
ifdef @UI
Autoload admin_links
endif

#==========================================================================#

# Internationalization
LocaleDatabase  locale

# Default locale
ifdef DEFAULT_LOCALE
DefaultLocale  __DEFAULT_LOCALE__
endif

ifdef DEFAULT_LOCALE
# Database definitions for localized databases
include dbconf/locales/{__LOCALES__}.cfg
endif

Locale en_US  <<EOL
{
    "Username already exists (indirect).",
    "Sorry, that email is already associated with an account.",
}
EOL

Locale id_ID currency_symbol Rp
Locale id_ID p_cs_precedes 1
Locale id_ID mon_thousands_sep .
Locale id_ID mon_decimal_point ""
Locale id_ID frac_digits 0

#==========================================================================#

# Various catalog settings.

ScratchDefault  mv_add_dot_html   0
ScratchDefault  mv_no_session_id  1
ScratchDefault  mv_no_count       1
Pragma url_no_session_id

ifdef DEFAULT_COUNTRY
ValuesDefault country __DEFAULT_COUNTRY__
ValuesDefault b_country __DEFAULT_COUNTRY__
endif

DirectoryIndex  index.html
SpecialPage  catalog      index
SpecialPage  violation    ../special_pages/violation
SpecialPage  put_handler  admin_publish
SpecialPage  report       ../etc/report
SpecialPage  receipt      ../etc/receipt

# Allow others in our group to read/write files by default
ReadPermission  group
WritePermission group

# Don't send X-Track HTTP response header
UserTrack no

# If a specific user session accesses this catalog more than this many
# times with no pauses of 30 seconds or more, the LockoutCommand (if set)
# is executed. Set this to 0 if you're getting links to 127.0.0.1
# during your testing.
RobotLimit  100

# We also count the number of accesses from the same IP address. More than
# RobotLimit accesses within a one hour period will cause a Forbidden result.
# Uncomment the following line to change the 1 hour period to 30 minutes.
# Limit  ip_session_expire  30

# The default lockout time is one day.  Uncomment the following line to change
# it to just under an hour.
# Limit  robot_expire  0.04

# Strip whitespace from top of pages so you don't have to scroll down
# before the HTML starts when doing 'view source' in a browser.
Pragma  strip_white

# Don't allow <!--[itl tag]-->
Pragma  no_html_comment_embed

## DATA INSERTION PRAGMAS for form database inserts or updates

## Restricts inserts to insert-only, but allows the fall-through
## behavior from update to insert. No existing data will be clobbered.
# Pragma dml=preserve

## Pragma 'dml=strict' forces update or insert to only perform the
## requested action.
# Pragma dml=strict

## Pragma 'dml=upsert' (the default) preserves Interchange's original
## method of doing an update if the record exists, otherwise doing an
## insert. This can clobber an existing key.
# Pragma dml=upsert

## END DATA INSERTION PRAGMAS

#==========================================================================#

# User session related settings.

# Whether to encrypt passwords in UserDB
UserDB    default    crypt         1
UserDB    default    bcrypt        1

# These 2 lines are needed for query/pw_reset
UserDB    default    promote       1
UserDB    default    from_plain    1

# The pepper should be unique for your site, but note that if you change this,
# it will make previously-crypted passwords inaccessible --
# so set this before you start adding users, or don't set at all.
UserDB    default    bcrypt_pepper  __BCRYPT_PEPPER__

# Set to 1 to make the username and password case-insensitive
UserDB    default    ignore_case   0

# Change a field to something that doesn't conflict in MySQL
UserDB    default    time_field    mod_time

# Don't want people setting their credit limit or dealer status directly
UserDB    default    scratch       "dealer price_level credit_limit usernick"
UserDB    default    expire_field  expiration

# Update the database with the date when creating a user
UserDB    default    created_date_iso   created

# Update the database with the date when updating a user via set_values
UserDB    default    updated_date_iso   updated

# Set some other things you want to retain but which don't deserve their
# own field -- stored in serial field preferences
UserDB    default    extra_fields  <<EOU
"
	mv_same_billing
	mv_credit_card_exp_type
	mv_credit_card_exp_month
	mv_credit_card_exp_year
	fax_order
	phone_cell
	account_id
	po_number
"
EOU

# Log user login/logout etc in separate logfile
UserDB    default    logfile       logs/userdb.log

# This makes the login username the user's email address
UserDB    default    indirect_login  usernick
UserDB    default    assign_username 1

# for indirect login to work with admin
UserDB    autocreate   crypt        0
UserDB    autocreate   time_field   mod_time
UserDB    autocreate   scratch      "dealer price_level credit_limit"

# This makes the password be inserted in an insert-only table.
#
# UserDB      default     enclair_db  enclair
#
# You can set the following, which have the defaults shown in the
# setting. You can also insert %M, which is the MD5 of the password, or
# %D which is a datetime localtime value in the form YYYYmmddHHMMSS.
#UserDB   default  enclair_key_field   username
#UserDB   default  enclair_field       password
#UserDB   default  enclair_query_template "INSERT INTO %t (%U,%P) values (%u,%p)"

# minimal login stuff for affiliate
UserDB    affiliate  user_field    affiliate
UserDB    affiliate  database      affiliate
UserDB    affiliate  time_field    none
UserDB    affiliate  crypt         0

# Set this to Yes if you want auto-login capability for users.
# You must be careful about malicious JavaScripts in your embedded code.
## this is not secure at all, since it saves user's password.
## can use alternate cookie to just save username.
CookieLogin  No

# Limit the time your customers can retain a session
SessionExpire   4 hours

# Limit the time your customers can CookieLogin
SaveExpire   30 days

#==========================================================================#

# Cart, order, and route settings.

ParseVariables  Yes

MailOrderTo     __ORDERS_TO__

AlwaysSecure   <<EOD
	*
EOD

AlwaysSecureGlob   <<EOD
	admin*,
	cert*,
	ui*,
EOD

## Set this if you have a different secure server
#AlwaysSecure   order ord/basket process

ifndef COMMON_ORDER_PROFILE
Variable COMMON_ORDER_PROFILE <<EOV
	[calc]
		if ($CGI->{state_cs_in} && !$CGI->{state}){
			$CGI->{state} = $CGI->{state_cs_in};
		}
		return;
	[/calc]
	mv_same_billing=always_pass
	fname=required
	lname=required
	address1=required
	address2=always_pass
	city=required
	country=required
	state=multistate
	zip=multizip
	phone_day=phone
	[if !session logged_in]email=email_only[/if]
EOV
endif

## Payment-related stuff

EncryptKey  __PGP_KEY__

## These routes are not order routes, but payment routes
Route  authorizenet  id           "__MV_PAYMENT_ID__"
Route  authorizenet  secret       "__MV_PAYMENT_SECRET__"
Route  authorizenet  host         "__MV_PAYMENT_HOST__"
Route  authorizenet  referer      "__MV_PAYMENT_REFERER__"

Route  itransact     id           "__MV_PAYMENT_ID__"

Route  netbilling    id           "__MV_PAYMENT_ID__"
Route  netbilling    secret       "__MV_PAYMENT_SECRET__"

Route  signio        id           "__MV_PAYMENT_ID__"
Route  signio        secret       "__MV_PAYMENT_SECRET__"
Route  signio        partner      "__MV_PAYMENT_PARTNER__"
Route  signio        vendor       "__MV_PAYMENT_VENDOR__"
Route  signio        host         "__MV_PAYMENT_HOST__"

Route  skipjack      id           "__MV_PAYMENT_ID__"
Route  skipjack      partner      "__MV_PAYMENT_PARTNER__"

Route  linkpoint     id           "__MV_PAYMENT_ID__"
Route  linkpoint     host         "__MV_PAYMENT_HOST__"
Route  linkpoint     keyfile      "__MV_PAYMENT_SECRET__"

# This prevents a user from setting this value, you may want to unset
# this if you have user-selectable handling charges like insurance
FormIgnore   mv_handling
#
#

# Along these lines further, for better integrity and less chance of a
# user screwing up your order routes:
# Note that __ORDER_ROUTES__ is empty by default, default Route "default"
# is used with cascades
FormIgnore      mv_order_route

## This route places the order entry in the database. If you don't
## have an inventory table (or a userdb table for that matter) make
## sure you remove it from the list of "transactions" tables.

Route log  <<EOF
	empty        1
	encrypt      0
	increment    0
	report       etc/log_transaction
	supplant     0
	track        logs/log
EOF

ifdef TRANSACTION_TABLES
Route log       transactions '__TRANSACTION_TABLES__'
endif

## This route copies the user if they requested that. We don't
## care (much) if it fails, so error_ok is set and failure will
## not cause the order to fail
Route copy_user  <<EOF
	empty        1
	error_ok     1
	encrypt      0
	increment    0
	report       etc/mail_receipt
	supplant     0
	track        logs/log
EOF

ParseVariables Yes
## This route emails the order to you unless email is set to "",
## and failsafe-logs the order report a couple of places
Route main  <<EOF
	attach            0
	credit_card       1
	default           1
	email             '__ORDERS_TO__'
	encrypt           0
	errors_to         '__ORDERS_TO__'
	pgp_cc_key        "__PGP_KEY__"
	pgp_key           "__PGP_KEY__"
	receipt           etc/receipt.html
	report            etc/report
	supplant          1
	individual_track  orders
	track             logs/tracking.asc
EOF

## This route emails the order to you unless email is set to "",
## and failsafe-logs the order report a couple of places
Route main_entry  <<EOF
	attach            0
	credit_card       1
	email             '__ORDERS_TO__'
	encrypt           0
	errors_to         '__ORDERS_TO__'
	pgp_cc_key        "__PGP_KEY__"
	pgp_key           "__PGP_KEY__"
	report            etc/report
	supplant          1
	individual_track  orders
	track             logs/tracking.asc
EOF


# Order desk route run if entered from admin
# always
Route   entry   master          1
Route   entry   cascade         "log main_entry copy_user"
Route   entry   empty           1
Route   entry   supplant        1
Route   entry   no_receipt      1
Route   entry   counter_tid     logs/tid.counter
Route   entry   write_tables    "inventory userdb transactions orderline"
Route   entry   transactions    '__TRANSACTION_TABLES__'
Route   entry   email           '__ORDERS_TO__'

# Default route is run if no routes set, this should be last Route
# always
Route   default   master          1
Route   default   cascade         "log main copy_user"
Route   default   empty           1
Route   default   supplant        1
Route   default   counter_tid     logs/tid.counter
Route   default   write_tables    "inventory userdb transactions orderline"
Route   default   transactions    '__TRANSACTION_TABLES__'
Route   default   email           '__ORDERS_TO__'

## Uncomment this if you want Routes read dynamically from DB
#Route   default   dynamic_routes  1
## Uncomment this if you want ITL allowed in routes
#Route   default   expandable      1


## Sest
SalesTax        __TAXFIELD__
TaxShipping     __TAXSHIPPING__

OrderCounter    etc/order.number
OrderLineLimit  200
Profiles        include/profiles/*.*

## Sets the default as to whether items are aggregated or ordered
## on separate lines. Can be overridden with mv_separate_items=0 in
## URL or form.
SeparateItems   No

#==========================================================================#

ifdef UI_TRAFFIC_STATS
TrackFile __UI_TRAFFIC_STATS__
endif

# Deal with customer click history. For example, after adding an item to
# the cart, the user can return to a specific search results page.
History 10

# Allow delivery of soft goods (downloadable files).
ActionMap  deliver   <<EOR
sub {
	$Scratch->{deliverable} = $CGI->{mv_arg};
	$CGI->{mv_nextpage} = 'deliver';
	if(! $Session->{username} and $CGI->{mv_username}) {
		$Tag->userdb('login');
	}
	return 1;
}
EOR

# Pricing setup
#
# If the user is logged in and is marked as a "dealer" (1 in the dealer
# field in the userdb database) then they are given quantity discounts
# based on price groups. (All products are in price group 1 as
# distributed.) If the quantity is 1, then pricing comes from the
# "wholesale" field in the products database.

AutoModifier pricing:price_group

#
# If the user is not a dealer (or not logged in) then pricing just comes
# from "price". Any quantity discounts will be set in the qN fields in the
# database, and are separate from dealer quantity discounts.
#

Profile dealer <<EOR
{
	CommonAdjust => <<EOF,

		pricing:w5,w10:,
		;:wholesale,
		;:wholesale:mv_sku,
		;$,
		==:options
EOF
	NonTaxableField => 'nontaxable',
}
EOR

Profile distributor <<EOR
{
	CommonAdjust => <<EOF,

		pricing:w5,w10:,
		;:wholesale,
		;:wholesale:mv_sku,
		;$,
		==:options,
		-10%
EOF
	NonTaxableField => 'nontaxable',
}
EOR

## This should match the default direct setting below this paragraph
Profile default CommonAdjust   "pricing:q5,q10 ;:sale_price, ;:price, ;$, :related, ==:options"
Profile default NonTaxableField
Profile default PriceField 0

CommonAdjust   pricing:q5,q10 ;:sale_price, ;:price, ;$, :related, ==:options
PriceField     0

## This sets the type of options pertaining to the product
OptionsEnable option_type

## Finally, set which tables products can be ordered from
ProductFiles   products variants

#==========================================================================#

## Tag which provides a CSS button-looking link
UserTag b-link Order href form
UserTag b-link HasEndTag
UserTag b-link addAttr
UserTag b-link Routine <<EOR
sub {
	my ($page, $form, $opt, $anchor) = @_;
	# use vars qw/$Tag $Scratch/;
	if($Scratch->{no_javascript}) {
		$opt->{extra} ||= 'style="font-size: smaller"';
		return $Tag->page($opt) . $anchor . '</a>';
	}
	my $class = $opt->{class} || 'btn';
	my $url = $Tag->area($opt);
	my $string = $Tag->filter('encode_entities', $anchor);
	my @properties;
	push @properties, "type=button";
	push @properties, qq{value="$string"};
	push @properties, qq{class="$class"};
	for(qw/style id name/) {
		next unless $opt->{$_};
		push @properties, qq{$_="$opt->{$_}"};
	}
	push @properties, qq{onClick="window.location='$url'"};
	push @properties, qq{onMouseOver="saveblink=window.status;window.status='$url'"};
	push @properties, qq{onMouseOut="window.status=saveblink"};
	if($opt->{title}) {
		$opt->{title} = $Tag->filter('encode_entities', $opt->{title});
	}
	else {
		$opt->{title} = $string;
	}
	push @properties, qq{title="$opt->{title}"};
	push @properties, $opt->{extra} if $opt->{extra};

	return qq{<input } . join(" ", @properties) . '>';
}
EOR

### Shipping setup. See Interchange docs -- you will want to change
### the origin postal code and default destination postal codes, for sure.
Shipping   Postal     default_geo   45056
Shipping   QueryUPS   default_geo   45056
Shipping   default    dir           products/ship

Database   2ndDayAir        ship/2ndDayAir.csv         CSV
Database   2ndDayAirAM      ship/2ndDayAirAM.csv       CSV
Database   3DaySelect       ship/3DaySelect.csv        CSV
Database   Expedited        ship/Expedited.csv         CSV
Database   Express          ship/Express.csv           CSV
Database   Ground           ship/Ground.csv            CSV
Database   NextDayAir       ship/NextDayAir.csv        CSV
Database   NextDayAirSaver  ship/NextDayAirSaver.csv   CSV
Database   Xarea            ship/Xarea.csv             CSV
Database   Zone             ship/Zone.csv              CSV
Database   usps             ship/usps.txt              TAB
Database   Book             ship/Book.txt              TAB
Database   Priority         ship/Priority.txt          TAB
Database   air_pp           ship/air_pp.txt            TAB
Database   surf_pp          ship/surf_pp.txt           TAB
Database   ups_cache        ship/ups_cache.txt         __SQLDSN__
Database   ups_cache        AUTO_SEQUENCE  ups_cache_seq
Database   ups_cache        DEFAULT_TYPE varchar(12)
Database   ups_cache        INDEX  weight origin zip shipmode country

## Uncomment
MaxQuantityField  inventory:quantity

## Builds a series of hidden variables given an IC-style form
## specification, i.e.
##
## [hiddens]
##    mv_action=refresh
##    mv_nextpage=foo
## [/hiddens]
##
UserTag hiddens Interpolate 1
UserTag hiddens HasEndTag
UserTag hiddens Routine <<EOR
sub {
	my $block = shift;
	my @lines = grep /\S/, split /\n/, $block;

	my @out;
	for(@lines) {
		s/\s+$//;
		s/^\s+//;
		my ($k,$v) = split /=/, $_, 2;
		$v = $Tag->filter('encode_entities', $v);
		push @out, qq{<input type=hidden name="$k" value="$v">};
	}
	return join "\n", @out;
}
EOR

## When uncommented, delivers a redirect if we get a request for an image
## DeliverImage Yes

## Map a subroutine to happen if the page is not there
SpecialSub  missing  ncheck_category

UserTag edisplay Alias error auto=1 class="alert alert-danger list-unstyled"
UserTag wdisplay Alias warnings auto=1 list_class="alert alert-success list-unstyled"
UserTag ecgi     Alias cgi keep=1 filter=encode_entities name=

CodeDef string2uri Filter
CodeDef string2uri Description Sanitize a string for use in a URL
CodeDef string2uri Routine <<EOR
sub {
	my $val = shift;
	$val =~ s|/|::|g;
	$val =~ s|-|_|g;
	$val =~ s|\s+|-|g;
	return $val;
}
EOR

CodeDef uri2string Filter
CodeDef uri2string Description Revert sanitized URL back to a string
CodeDef uri2string Routine <<EOR
sub {
	my $val = shift;
	$val =~ s|-| |g;
	$val =~ s|_|-|g;
	$val =~ s|::|/|g;
	return $val;
}
EOR

SearchProfile  include/profiles/searchprofiles

Jobs  log    __LOGDIR__/jobs.log
Jobs  base_directory  etc/jobs

Variable PIKUL 0
Variable PIKUL_ANTERAJA 1
Variable PIKUL_END 2