Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Serious problem with the input validation has been fixed by processing
[kiriwrite/.git] / cgi-files / kiriwrite.cgi
1 #!/usr/bin/perl -Tw
3 #################################################################################
4 # Kiriwrite (kiriwrite.cgi)                                                     #
5 # Main program script                                                           #
6 #                                                                               #
7 # Version: 0.1.0                                                                #
8 #                                                                               #
9 # Copyright (C) 2005-2007 Steve Brokenshire <sbrokenshire@xestia.co.uk>         #
10 #                                                                               #
11 # This program is free software; you can redistribute it and/or modify it under #
12 # the terms of the GNU General Public License as published by the Free          #
13 # Software Foundation; as version 2 of the License.                             #
14 #                                                                               #
15 # This program is distributed in the hope that it will be useful, but WITHOUT   #
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
17 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.#
18 #                                                                               #
19 # You should have received a copy of the GNU General Public License along with  #
20 # this program; if not, write to the Free Software Foundation, Inc., 51         #
21 # Franklin St, Fifth Floor, Boston, MA 02110-1301 USA                           #
22 #################################################################################
24 use strict;                             # Throw errors if there's something wrong.
25 use warnings;                           # Write warnings to the HTTP Server Log file.
27 use utf8;
28 use CGI::Lite;
29 use Tie::IxHash;
31 # This is commented out because it uses a fair bit of CPU usage.
33 #use CGI::Carp('fatalsToBrowser');      # Output errors to the browser.
35 # Declare global variables for Kiriwrite settings and languages.
37 our ($kiriwrite_config, %kiriwrite_config, %kiriwrite_lang, $kiriwrite_lang, $kiriwrite_version, %kiriwrite_version, $kiriwrite_env, %kiriwrite_env, $kiriwrite_presmodule, $kiriwrite_dbmodule, $form_data);
39 # Setup the version information for Kiriwrite.
41 %kiriwrite_version = (
42         "major"         => 0,
43         "minor"         => 2,
44         "revision"      => 0
45 );
47 sub BEGIN{
48 #################################################################################
49 # BEGIN: Get the enviroment stuff                                               #
50 #################################################################################
52         # Get the script filename.
54         my $env_script_name = $ENV{'SCRIPT_NAME'};
56         # Process the script filename until there is only the
57         # filename itself.
59         my $env_script_name_length = length($env_script_name);
60         my $filename_seek = 0;
61         my $filename_char = "";
62         my $filename_last = 0;
64         do {
65                 $filename_char = substr($env_script_name, $filename_seek, 1);
66                 if ($filename_char eq "/"){
67                         $filename_last = $filename_seek + 1;
68                 }
69                 $filename_seek++;
70         } until ($filename_seek eq $env_script_name_length || $env_script_name_length eq 0);
72         my $env_script_name_finallength = $env_script_name_length - $filename_last;
73         my $script_filename = substr($env_script_name, $filename_last, $env_script_name_finallength);
75         # Setup the needed enviroment variables for Kiriwrite.
77         %kiriwrite_env = (
78                 "script_filename" => $script_filename,
79         );
81 }
83 #################################################################################
84 # Begin listing the functions needed.                                           #
85 #################################################################################
87 sub kiriwrite_selectedlist{
88 #################################################################################
89 # kiriwrite_page_selectedlist: Get the list of selected pages to use.           #
90 #                                                                               #
91 # Usage:                                                                        #
92 #                                                                               #
93 # kiriwrite_page_selectedlist();                                                #
94 #################################################################################
96         my $count       = $form_data->{'count'};
98         # Check if the list of files has a value and if not set it 0.
100         if (!$count){
102                 $count = 0;
104         }
106         # Define some values for later.
108         my @filename_list; 
109         my @selected_list;
110         my @final_list;
112         my $filename;
113         my $selected;
115         my $final_count = 0;
116         my $seek = 0;
118         # Get the list of filenames.
120         do {
122                 # Get the values from id[]
124                 $seek++;
126                 $filename               = $form_data->{'id[' . $seek . ']'};
127                 $filename_list[$seek]   = $filename;
129         } until ($seek eq $count || $count eq 0);
131         # Get the list of selected filenames.
133         $seek = 0;
135         do {
137                 # Get the values from name[]
139                 $seek++;
141                 $selected       = $form_data->{'name[' . $seek . ']'};
143                 if (!$selected){
145                         $selected = 'off';
147                 }
149                 $selected_list[$seek]   = $selected;
151         } until ($seek eq $count || $count eq 0);
153         # Create a final list of filenames to be used for
154         # processing.
156         $seek = 0;
158         do {
160                 # Check if the selected value is on and include
161                 # the filename in the final list.
163                 $seek++;
165                 $selected       = $selected_list[$seek];
167                 if ($selected eq "on"){
169                         $filename       = $filename_list[$seek];
170                         $final_list[$final_count] = $filename;
171                         $final_count++;
173                 }
175         } until ($seek eq $count || $count eq 0);
177         return @final_list;
181 sub kiriwrite_settings_load{
182 #################################################################################
183 # kiriwrite_settings_load: Load the configuration settings into the global      #
184 # variables.                                                                    #
185 #                                                                               #
186 # Usage:                                                                        #
187 #                                                                               #
188 # kiriwrite_settings_load();                                                    #
189 #################################################################################
191         # Load the required Perl modules.
193         use Config::Auto;
195         # Check if the Kiriwrite configuration file exists before using it and
196         # return an critical error if it doesn't exist.
198         my $kiriwrite_conf_exist = kiriwrite_fileexists("kiriwrite.cfg");
200         if ($kiriwrite_conf_exist eq 1){
202                 # The configuration really does not exist so return an critical error.
204                 kiriwrite_critical("configfilemissing");
206         }
208         # Check if the Kiriwrite configuration file has valid permission settings
209         # before using it and return an critical error if it doesn't have the
210         # valid permission settings.
212         my $kiriwrite_conf_permissions = kiriwrite_filepermissions("kiriwrite.cfg", 1, 0);
214         if ($kiriwrite_conf_permissions eq 1){
216                 # The permission settings for the Kiriwrite configuration file are
217                 # invalid, so return an critical error.
219                 kiriwrite_critical("configfileinvalidpermissions");
221         }
223         # Converts the XML file into meaningful data for later on in this subroutine.
225         my $kiriwrite_conf_file = 'kiriwrite.cfg';
226         my $config = Config::Auto::parse($kiriwrite_conf_file, format => "ini");
228         # Go and fetch the settings and place them into a hash (that is global).
230         %kiriwrite_config = (
232                 "directory_data_db"             => $config->{config}{directory_data_db},
233                 "directory_data_output"         => $config->{config}{directory_data_output},
234                 "directory_noncgi_images"       => $config->{config}{directory_noncgi_images},
236                 "system_language"               => $config->{config}{system_language},
237                 "system_presmodule"             => $config->{config}{system_presmodule},
238                 "system_dbmodule"               => $config->{config}{system_dbmodule},
239                 "system_datetime"               => $config->{config}{system_datetime},
241                 "display_textarearows"          => $config->{config}{display_textarearows},
242                 "display_textareacols"          => $config->{config}{display_textareacols},
244                 "database_server"               => $config->{config}{database_server},
245                 "database_port"                 => $config->{config}{database_port},
246                 "database_protocol"             => $config->{config}{database_protocol},
247                 "database_sqldatabase"          => $config->{config}{database_sqldatabase},
248                 "database_username"             => $config->{config}{database_username},
249                 "database_password"             => $config->{config}{database_password},
250                 "database_tableprefix"          => $config->{config}{database_tableprefix}
252         );
254         # Do a validation check on all of the variables that were loaded into the global configuration hash.
256         kiriwrite_variablecheck($kiriwrite_config{"directory_data_db"}, "maxlength", 64, 0);
257         kiriwrite_variablecheck($kiriwrite_config{"directory_data_output"}, "maxlength", 64, 0);
258         kiriwrite_variablecheck($kiriwrite_config{"directory_noncgi_images"}, "maxlength", 512, 0);
259         kiriwrite_variablecheck($kiriwrite_config{"directory_data_template"}, "maxlength", 64, 0);
261         my $kiriwrite_config_language_filename = kiriwrite_variablecheck($kiriwrite_config{"system_language"}, "language_filename", "", 1);
262         my $kiriwrite_config_presmodule_filename = kiriwrite_variablecheck($kiriwrite_config{"system_presmodule"}, "module", 0, 1);
263         my $kiriwrite_config_dbmodule_filename = kiriwrite_variablecheck($kiriwrite_config{"system_dbmodule"}, "module", 0, 1);
265         my $kiriwrite_config_textarearows_maxlength = kiriwrite_variablecheck($kiriwrite_config{"display_textarearows"}, "maxlength", 3, 1);
266         my $kiriwrite_config_textarearows_number = kiriwrite_variablecheck($kiriwrite_config{"display_textareacols"}, "numbers", 0, 1);
267         my $kiriwrite_config_textareacols_maxlength = kiriwrite_variablecheck($kiriwrite_config{"display_textareacols"}, "maxlength", 3, 1);
268         my $kiriwrite_config_textareacols_number = kiriwrite_variablecheck($kiriwrite_config{"display_textareacols"}, "numbers", 0, 1);
270         # Check if the language filename is valid and return an critical error if
271         # they aren't.
273         if ($kiriwrite_config_language_filename eq 1){
275                 # The language filename is blank so return an critical error.
277                 kiriwrite_critical("languagefilenameblank");
279         } elsif ($kiriwrite_config_language_filename eq 2){
281                 # The language filename is invalid so return an critical error.
283                 kiriwrite_critical("languagefilenameinvalid");
285         }
287         # Check if the presentation and database module names are valid and return a critical
288         # error if they aren't.
290         if ($kiriwrite_config_presmodule_filename eq 1){
292                 # The presentation module filename given is blank so return an 
293                 # critical error.
295                 kiriwrite_critical("presmoduleblank");
297         }
299         if ($kiriwrite_config_presmodule_filename eq 2){
301                 # The presentation module filename is invalid so return an
302                 # critical error.
304                 kiriwrite_critical("presmoduleinvalid");
306         }
308         if ($kiriwrite_config_dbmodule_filename eq 1){
310                 # The database module filename given is blank so return an
311                 # critical error.
313                 kiriwrite_critical("dbmoduleblank");
315         }
317         if ($kiriwrite_config_dbmodule_filename eq 2){
319                 # The database module filename given is invalid so return
320                 # an critical error.
322                 kiriwrite_critical("dbmoduleinvalid");
324         }
326         # Check if the text area column and row values are blank and return a critical
327         # error if they are.
329         if (!$kiriwrite_config{"display_textarearows"}){
331                 # The text area row value is blank so return
332                 # a critical error.
334                 kiriwrite_critical("textarearowblank");
336         }
338         if (!$kiriwrite_config{"display_textareacols"}){
340                 # The text area column value is blank so return
341                 # a critical error.
343                 kiriwrite_critical("textareacolblank");
345         }
347         # Check if the text area column and row values to see if they are valid and return
348         # a critical error if they aren't.
350         if ($kiriwrite_config_textarearows_maxlength eq 1){
352                 # The text area row value is too long so return an
353                 # critical error.
355                 kiriwrite_critical("textarearowtoolong");
357         }
359         if ($kiriwrite_config_textarearows_number eq 1){
361                 # The text area row value is invalid so return an
362                 # critical error.
364                 kiriwrite_critical("textarearowinvalid");
366         }
368         if ($kiriwrite_config_textareacols_maxlength eq 1){
370                 # The text area column value is too long so return
371                 # an critical error.
373                 kiriwrite_critical("textareacoltoolong");
375         }
377         if ($kiriwrite_config_textareacols_number eq 1){
379                 # The text area column value is invalid so return
380                 # an critical error.
382                 kiriwrite_critical("textareacolinvalid");
384         }
386         # Check if the language file does exist before loading it and return an critical error
387         # if it does not exist.
389         my $kiriwrite_config_language_fileexists = kiriwrite_fileexists("lang/" . $kiriwrite_config{"system_language"} . ".lang");
391         if ($kiriwrite_config_language_fileexists eq 1){
393                 # Language file does not exist so return an critical error.
395                 kiriwrite_critical("languagefilemissing");
397         }
399         # Check if the language file has valid permission settings and return an critical error if
400         # the language file has invalid permissions settings.
402         my $kiriwrite_config_language_filepermissions = kiriwrite_filepermissions("lang/" . $kiriwrite_config{"system_language"} . ".lang", 1, 0);
404         if ($kiriwrite_config_language_filepermissions eq 1){
406                 # Language file contains invalid permissions so return an critical error.
408                 kiriwrite_critical("languagefilenameinvalidpermissions");
410         }
412         # Load the language file.
414         $kiriwrite_lang = Config::Auto::parse("lang/" . $kiriwrite_config{"system_language"} . ".lang", format => "ini");
416         # Check if the presentation module does exist before loading it and return an critical error
417         # if the presentation module does not exist.
419         my $kiriwrite_config_presmodule_fileexists = kiriwrite_fileexists("Modules/Presentation/" . $kiriwrite_config{"system_presmodule"} . ".pm");
421         if ($kiriwrite_config_presmodule_fileexists eq 1){
423                 # Presentation module does not exist so return an critical error.
425                 kiriwrite_critical("presmodulemissing");
427         }
429         # Check if the presentation module does have the valid permission settings and return a
430         # critical error if the presentation module contains invalid permission settings.
432         my $kiriwrite_config_presmodule_permissions = kiriwrite_filepermissions("Modules/Presentation/" . $kiriwrite_config{"system_presmodule"} . ".pm", 1, 0);
434         if ($kiriwrite_config_presmodule_permissions eq 1){
436                 # Presentation module contains invalid permissions so return an critical error.
438                 kiriwrite_critical("presmoduleinvalidpermissions");
440         }
442         # Check if the database module does exist before loading it and return an critical error
443         # if the database module does not exist.
445         my $kiriwrite_config_dbmodule_fileexists = kiriwrite_fileexists("Modules/Database/" . $kiriwrite_config{"system_dbmodule"} . ".pm");
447         if ($kiriwrite_config_dbmodule_fileexists eq 1){
449                 # Database module does not exist so return an critical error.
451                 kiriwrite_critical("dbmodulemissing");
453         }
455         # Check if the database module does have the valid permission settings and return an
456         # critical error if the database module contains invalid permission settings.
458         my $kiriwrite_config_dbmodule_permissions = kiriwrite_filepermissions("Modules/Database/" . $kiriwrite_config{"system_dbmodule"} . ".pm", 1, 0);
460         if ($kiriwrite_config_dbmodule_permissions eq 1){
462                 # Presentation module contains invalid permissions so return an critical error.
464                 kiriwrite_critical("dbmoduleinvalidpermissions");
466         }
468         # Include the Modules directory.
470         use lib "Modules/";
472         # Load the presentation module.
474         my $presmodulename = "Presentation::" . $kiriwrite_config{"system_presmodule"};
475         ($presmodulename) = $presmodulename =~ m/^(.*)$/g;
476         eval "use " . $presmodulename;
477         $presmodulename = "Kiriwrite::Presentation::" . $kiriwrite_config{"system_presmodule"};
478         $kiriwrite_presmodule = $presmodulename->new();
480         # Load the database module.
482         my $dbmodulename = "Database::" . $kiriwrite_config{"system_dbmodule"};
483         ($dbmodulename) = $dbmodulename =~ m/^(.*)$/g;
484         eval "use " . $dbmodulename;
485         $dbmodulename = "Kiriwrite::Database::" . $kiriwrite_config{"system_dbmodule"};
486         $kiriwrite_dbmodule = $dbmodulename->new();
488         # Load the following settings to the database module.
490         $kiriwrite_dbmodule->loadsettings({ Directory => $kiriwrite_config{"directory_data_db"}, DateTime => $kiriwrite_config{"system_datetime"}, Server => $kiriwrite_config{"database_server"}, Port => $kiriwrite_config{"database_port"}, Protocol => $kiriwrite_config{"database_protocol"}, Database => $kiriwrite_config{"database_sqldatabase"}, Username => $kiriwrite_config{"database_username"}, Password => $kiriwrite_config{"database_password"}, TablePrefix => $kiriwrite_config{"database_tableprefix"} });
492         return;
496 sub kiriwrite_variablecheck{
497 #################################################################################
498 # kiriwrite_variablecheck: Checks the variables for any invalid characters.     #
499 #                                                                               #
500 # Usage:                                                                        #
501 #                                                                               #
502 # kiriwrite_variablecheck(variable, type, length, noerror);                     #
503 #                                                                               #
504 # variable      Specifies the variable to be checked.                           #
505 # type          Specifies what type the variable is.                            #
506 # option        Specifies the maximum/minimum length of the variable            #
507 #               (if minlength/maxlength is used) or if the filename should be   #
508 #               checked to see if it is blank.                                  #
509 # noerror       Specifies if Kiriwrite should return an error or not on         #
510 #               certain values.                                                 #
511 #################################################################################
513         # Get the values that were passed to the subroutine.
515         my ($variable_data, $variable_type, $variable_option, $variable_noerror) = @_;
517         if ($variable_type eq "numbers"){
519                 # Check for numbers and return an error if there is anything else than numebrs.
521                 my $variable_data_validated = $variable_data;   # Copy the variable_data to variable_data_validated.
522                 $variable_data_validated =~ tr/0-9//d;          # Take away all of the numbers and from the variable. 
523                                                                 # If it only contains numbers then it should be blank.
525                 if ($variable_data_validated eq ""){
526                         # The validated variable is blank. So continue to the end of this section where the return function should be.
527                 } else {
528                         # The variable is not blank, so check if the no error value is set
529                         # to 1 or not.
531                         if ($variable_noerror eq 1){
533                                 # The validated variable is not blank and the noerror
534                                 # value is set to 1. So return an value of 1.
535                                 # (meaning that the data is invalid).
537                                 return 1;
539                         } elsif ($variable_noerror eq 0) {
541                                 # The validated variable is not blank and the noerror
542                                 # value is set to 0.
544                                 kiriwrite_error("invalidvariable");
546                         } else {
548                                 # The variable noerror value is something else
549                                 # pther than 1 or 0. So return an error.
551                                 kiriwrite_error("invalidvariable");
553                         }
555                 }
557                 return 0;
559         } elsif ($variable_type eq "lettersnumbers"){
561                 # Check for letters and numbers and return an error if there is anything else other
562                 # than letters and numbers.
564                 my $variable_data_validated = $variable_data;   # Copy the variable_data to variable_data_validated
565                 $variable_data_validated =~ tr/a-zA-Z0-9.//d;
566                 $variable_data_validated =~ s/\s//g;
568                 if ($variable_data_validated eq ""){
569                         # The validated variable is blank. So continue to the end of this section where the return function should be.
570                 } else {
571                         # The variable is not blank, so check if the no error value is set
572                         # to 1 or not.
574                         if ($variable_noerror eq 1){
576                                 # The validated variable is not blank and the noerror
577                                 # value is set to 1. So return an value of 1.
578                                 # (meaning that the data is invalid).
580                                 return 1;
582                         } elsif ($variable_noerror eq 0) {
584                                 # The validated variable is not blank and the noerror
585                                 # value is set to 0.
587                                 kiriwrite_error("invalidvariable");
589                         } else {
591                                 # The variable noerror value is something else
592                                 # pther than 1 or 0. So return an error.
594                                 kiriwrite_error("invalidvariable");
596                         }
598                 }
600                 return 0;
602         } elsif ($variable_type eq "maxlength"){
603                 # Check for the length of the variable, return an error if it is longer than the length specified.
605                 # Check if the variable_data string is blank, if it is then set the variable_data_length
606                 # to '0'.
608                 my $variable_data_length = 0;
610                 if (!$variable_data){
612                         # Set variable_data_length to '0'.
613                         $variable_data_length = 0;
615                 } else {
617                         # Get the length of the variable recieved.
618                         $variable_data_length = length($variable_data);
620                 }
624                 if ($variable_data_length > $variable_option){
626                         # The variable length is longer than it should be so check if
627                         # the no error value is set 1.
629                         if ($variable_noerror eq 1){
631                                 # The no error value is set to 1, so return an
632                                 # value of 1 (meaning tha the variable is
633                                 # too long to be used).
635                                 return 1;
637                         } elsif ($variable_noerror eq 0){
639                                 # The no error value is set to 0, so return
640                                 # an error.
642                                 kiriwrite_error("variabletoolong");
644                         } else {
646                                 # The no error value is something else other
647                                 # than 0 or 1, so return an error.
649                                 kiriwrite_error("variabletoolong");
651                         }
653                 } else {
655                         # The variable length is exactly or shorter than specified, so continue to end of this section where
656                         # the return function should be.
658                 }
660                 return 0;
662         } elsif ($variable_type eq "blank"){
663                 # Check if the variable is blank and if it is blank, then return an error.
665                 if (!$variable_data){
667                         # The variable data really is blank, so check what
668                         # the no error value is set.
670                         if ($variable_noerror eq 1){
672                                 # The no error value is set to 1, so return
673                                 # a value of 1 (saying that the variable was
674                                 # blank).
676                                 return 1;
678                         } elsif ($variable_noerror eq 0){
680                                 # The no error value is set to 0, so return
681                                 # an error.
683                                 kiriwrite_error("blankvariable");
685                         } else {
687                                 # The no error value is something else other
688                                 # than 0 or 1, so return an error.
690                                 kiriwrite_error("invalidvariable");
692                         }
694                 }
696                 return 0;
698         } elsif ($variable_type eq "filename"){
699                 # Check for letters and numbers, if anything else than letters and numbers is there (including spaces) return
700                 # an error.
702                 # Check if the filename passed is blank, if it is then return with an error.
704                 if ($variable_data eq ""){
706                         # The filename specified is blank, so check what the
707                         # noerror value is set.
709                         if ($variable_noerror eq 1){
711                                 # The no error value is set to 1 so return
712                                 # a value of 1 (meaning that the filename
713                                 # was blank).
715                                 return 1;
717                         } elsif ($variable_noerror eq 0){
719                                 # The no error value is set to 1 so return
720                                 # an error.
722                                 kiriwrite_error("blankfilename");
724                         } else {
726                                 # The no error value is something else other
727                                 # than 0 or 1, so return an error.
729                                 kiriwrite_error("invalidvariable");
731                         }
733                 } else {
736                 }
738                 my $variable_data_validated = $variable_data;
739                 $variable_data_validated =~ tr/a-zA-Z0-9\.//d;
741                 # Check if the validated data variable is blank, if it is 
742                 # then continue to the end of this section where the return 
743                 # function should be, otherwise return an error.
745                 if ($variable_data_validated eq ""){
747                         # The validated data variable is blank, meaning that 
748                         # it only contained letters and numbers.
750                 } else {
752                         # The validated data variable is not blank, meaning 
753                         # that it contains something else, so return an error
754                         # (or a value).
756                         if ($variable_noerror eq 1){
758                                 # The no error value is set to 1 so return
759                                 # an value of 2. (meaning that the filename
760                                 # is invalid).
763                                 return 2;
765                         } elsif ($variable_noerror eq 0){
767                                 # The no error value is set to 0 so return
768                                 # an error.
770                                 kiriwrite_error("invalidfilename");
772                         } else {
774                                 # The no error value is something else other
775                                 # than 0 or 1 so return an error.
777                                 kiriwrite_error("invalidvariable");
779                         }
781                 }
783                 return 0;
785         } elsif ($variable_type eq "filenameindir"){
786                 # Check if the filename is in the directory and return an
787                 # error if it isn't.
789                 if ($variable_data eq ""){
791                         # The filename specified is blank, so check what the
792                         # noerror value is set.
794                         if ($variable_noerror eq 1){
796                                 # The no error value is set to 1 so return
797                                 # a value of 1 (meaning that the filename
798                                 # was blank).
800                                 return 1;
802                         } elsif ($variable_noerror eq 0){
804                                 # The no error value is set to 1 so return
805                                 # an error.
807                                 kiriwrite_error("blankfilename");
809                         } else {
811                                 # The no error value is something else other
812                                 # than 0 or 1, so return an error.
814                                 kiriwrite_error("invalidvariable");
816                         }
818                 } else {
821                 }
823                 # Set the following variables for later on.
825                 my $variable_data_length = 0;
826                 my $variable_data_char = "";
827                 my $variable_data_validated = "";
828                 my $variable_data_seek = 0;
829                 my $variable_database_list = "";
830                 my $variable_database_listcurrent = "";
831                 my $variable_data_firstlevel = 1;
833                 # Get the length of the variable recieved.
835                 $variable_data_length = length($variable_data);
837                 # Check if the database filename contains the directory command
838                 # for up a directory level and if it is, return an error
839                 # or return with a number.
841                 do {
843                         # Get a character from the filename passed to this subroutine.
845                         $variable_data_char = substr($variable_data, $variable_data_seek, 1);
847                         # Check if the current character is the forward slash character.
849                         if ($variable_data_char eq "/"){
851                                 # Check if the current directory is blank (and on the first level), or if the
852                                 # current directory contains two dots or one dot, if it does return an error.
854                                 if ($variable_database_listcurrent eq "" && $variable_data_firstlevel eq 1 || $variable_database_listcurrent eq ".." || $variable_database_listcurrent eq "."){
856                                         # Check if the noerror value is set to 1, if it is return an
857                                         # number, else return an proper error.
859                                         if ($variable_noerror eq 1){
861                                                 # Page filename contains invalid characters and
862                                                 # the no error value is set to 1 so return a 
863                                                 # value of 2 (meaning that the page filename
864                                                 # is invalid).
866                                                 return 2;
868                                         } elsif ($variable_noerror eq 0) {
870                                                 # Page filename contains invalid characters and
871                                                 # the no error value is set to 0 so return an
872                                                 # error.
874                                                 kiriwrite_error("invalidfilename");
876                                         } else {
878                                                 # The no error value is something else other
879                                                 # than 0 or 1 so return an error.
881                                                 kiriwrite_error("invalidvariable");
883                                         }
885                                 }
887                                 # Append the forward slash, clear the current directory name and set
888                                 # the first directory level value to 0.
890                                 $variable_database_list = $variable_database_list . $variable_data_char;
891                                 $variable_database_listcurrent = "";
892                                 $variable_data_firstlevel = 0;
894                         } else {
896                                 # Append the current character to the directory name and to the current
897                                 # directory name.
899                                 $variable_database_list = $variable_database_list . $variable_data_char;
900                                 $variable_database_listcurrent = $variable_database_listcurrent . $variable_data_char;
902                         }
904                         # Increment the seek counter.
906                         $variable_data_seek++;
908                 } until ($variable_data_seek eq $variable_data_length);
910                 return 0;
912         } elsif ($variable_type eq "datetime"){
913                 # Check if the date and time setting format is valid.
915                 if ($variable_data eq ""){
917                         if ($variable_noerror eq 1){
919                                 # The no error value is set to 1 so return
920                                 # a value of 1 (meaning that the date and
921                                 # time format was blank).
923                                 return 1;
925                         } elsif ($variable_noerror eq 0){
927                                 # The no error value is set to 1 so return
928                                 # an error.
930                                 kiriwrite_error("blankdatetimeformat");
932                         } else {
934                                 # The no error value is something else other
935                                 # than 0 or 1, so return an error.
937                                 kiriwrite_error("invalidvariable");
939                         }
941                 }
943                 my $variable_data_validated = $variable_data;
944                 $variable_data_validated =~ tr|dDmMyYhms/():[ ]||d;
946                 if ($variable_data_validated eq ""){
948                         # The date and time format is valid. So
949                         # skip this bit.
951                 } else {
953                         # The validated data variable is not blank, meaning 
954                         # that it contains something else, so return an error
955                         # (or a value).
957                         if ($variable_noerror eq 1){
959                                 # The no error value is set to 1 so return
960                                 # an value of 2. (meaning that the date and
961                                 # time format was invalid).
963                                 return 2;
965                         } elsif ($variable_noerror eq 0){
967                                 # The no error value is set to 0 so return
968                                 # an error.
970                                 kiriwrite_error("invaliddatetimeformat");
972                         } else {
974                                 # The no error value is something else other
975                                 # than 0 or 1 so return an error.
977                                 kiriwrite_error("invalidvariable");
979                         }
981                 }
983                 return 0;
985         } elsif ($variable_type eq "directory"){
986                 # Check if the directory only contains letters and numbers and
987                 # return an error if anything else appears.
989                 my $variable_data_validated = $variable_data;
990                 $variable_data_validated =~ tr/a-zA-Z0-9//d;
992                 if ($variable_data eq ""){
994                         if ($variable_noerror eq 1){
996                                 # The no error value is set to 1 so return
997                                 # a value of 1 (meaning that the directory
998                                 # name was blank).
1000                                 return 1;
1002                         } elsif ($variable_noerror eq 0){
1004                                 # The no error value is set to 1 so return
1005                                 # an error.
1007                                 kiriwrite_error("blankdirectory");
1009                         } else {
1011                                 # The no error value is something else other
1012                                 # than 0 or 1, so return an error.
1014                                 kiriwrite_error("invalidvariable");
1016                         }
1018                 }
1020                 if ($variable_data_validated eq ""){
1022                         # The validated data variable is blank, meaning that
1023                         # it only contains letters and numbers.
1025                 } else {
1027                         # The validated data variable is not blank, meaning 
1028                         # that it contains something else, so return an error
1029                         # (or a value).
1031                         if ($variable_noerror eq 1){
1033                                 # The no error value is set to 1 so return
1034                                 # an value of 2. (meaning that the directory
1035                                 # name is invalid).
1037                                 return 2;
1039                         } elsif ($variable_noerror eq 0){
1041                                 # The no error value is set to 0 so return
1042                                 # an error.
1044                                 kiriwrite_error("invaliddirectory");
1046                         } else {
1048                                 # The no error value is something else other
1049                                 # than 0 or 1 so return an error.
1051                                 kiriwrite_error("invalidvariable");
1053                         }
1055                 }
1057                 return 0;
1059         } elsif ($variable_type eq "language_filename"){
1061                 # The variable type is a language filename type.
1062                 # Check if the language file name is blank and 
1063                 # if it is then return an error (or value).
1065                 if ($variable_data eq ""){
1067                         # The language filename is blank so check the
1068                         # no error value and return an error (or value).
1070                         if ($variable_noerror eq 1){
1072                                 # Language filename is blank and the no error value
1073                                 # is set as 1, so return a value of 1 (saying that
1074                                 # the language filename is blank).
1076                                 return 1;
1078                         } elsif ($variable_noerror eq 0) {
1080                                 # Language filename is blank and the no error value
1081                                 # is not set as 1, so return an error.
1083                                 kiriwrite_critical("languagefilenameblank");
1085                         } else {
1087                                 # The noerror value is something else other
1088                                 # than 0 or 1 so return an error.
1090                                 kiriwrite_error("invalidvariable");
1092                         }
1094                 }
1096                 # Set the following variables for later on.
1098                 my $variable_data_length = 0;
1099                 my $variable_data_char = "";
1100                 my $variable_data_seek = 0;
1102                 # Get the length of the language file name.
1104                 $variable_data_length = length($variable_data);
1106                 do {
1108                         # Get a character from the language filename passed to this 
1109                         # subroutine and the character the seek counter value is set
1110                         # to.
1112                         $variable_data_char = substr($variable_data, $variable_data_seek, 1);
1114                         # Check if the language filename contains a forward slash or a dot, 
1115                         # if the selected character is a forward slash then return an error
1116                         # (or value).
1118                         if ($variable_data_char eq "/" || $variable_data_char eq "."){
1120                                 # The language filename contains a forward slash or
1121                                 # a dot so depending on the no error value, return
1122                                 # an error or a value.
1124                                 if ($variable_noerror eq 1){
1126                                         # Language filename contains a forward slash or a dot
1127                                         # and the no error value has been set to 1, so return 
1128                                         # an value of 2 (saying that the language file name is 
1129                                         # invalid).
1131                                         return 2;
1133                                 } elsif ($variable_noerror eq 0) {
1135                                         # Language filename contains a forward slash and the no
1136                                         # error value has not been set to 1, so return an error.
1138                                         kiriwrite_critical("languagefilenameinvalid");
1140                                 } else {
1142                                         # The noerror value is something else other than
1143                                         # 1 or 0 so return an error.
1145                                         kiriwrite_error("invalidvariable");
1147                                 }
1149                         }
1151                         # Increment the seek counter.
1153                         $variable_data_seek++;
1155                 } until ($variable_data_seek eq $variable_data_length);
1157                 return 0;
1159         } elsif ($variable_type eq "pagesetting"){
1161                 # The variable type is a page setting, so check if the page
1162                 # setting has one of the valid options.
1164                 if ($variable_data eq 0 || $variable_data eq 1 || $variable_data eq 2 || $variable_data eq 3){
1166                         # The variable is one of the options above, so continue
1167                         # to the end of this section.
1169                 } else {
1171                         # The variable is not one of the options above, so check
1172                         # and see if a error or a value should be returned.
1174                         if ($variable_noerror eq 1){
1176                                 # The page setting is invalid and the no error
1177                                 # value is set 1, so return a value of 1
1178                                 # (saying that the page setting value is
1179                                 # invalid).
1181                                 return 1;
1183                         } elsif ($variable_noerror eq 0) {
1185                                 # Page setting is invalid and the no error value
1186                                 # is not 1, so return an error.
1188                                 kiriwrite_error("invalidvariable");
1190                         } else {
1192                                 # The no error value is something else other
1193                                 # than 0 or 1 so return an error.
1195                                 kiriwrite_error("invalidvariable");
1197                         }
1199                 }
1201                 return 0;
1203         } elsif ($variable_type eq "page_filename"){
1204          
1205                 # The variable type is a page filename type. Check
1206                 # if the data is empty and if it is then return an
1207                 # error (or value).
1209                 if ($variable_data eq ""){
1211                         # The filename is blank so check the no error
1212                         # value and depending on it return an value
1213                         # or an error.
1215                         if ($variable_noerror eq 1){
1217                                 # Page filename is blank and the no error value
1218                                 # is set as 1, so return a value of 1 (saying
1219                                 # the filename is blank).
1221                                 return 1;
1223                         } elsif ($variable_noerror eq 0) {
1225                                 # Page filename is blank and the no error value
1226                                 # is not 1, so return an error.
1228                                 kiriwrite_error("emptypagefilename");
1230                         } else {
1232                                 # The no error value is something else other
1233                                 # than 0 or 1 so return an error.
1235                                 kiriwrite_error("invalidvariable");
1237                         }
1238                 }
1240                 # Set the following variables for later on.
1243                 my $variable_data_length = 0;
1244                 my $variable_data_slash = 0;
1245                 my $variable_data_char = "";
1246                 my $variable_data_validated = "";
1247                 my $variable_data_seek = 0;
1248                 my $variable_database_list = "";
1249                 my $variable_database_listcurrent = "";
1250                 my $variable_data_firstlevel = 1;
1252                 # Get the length of the filename.
1254                 $variable_data_length = length($variable_data);
1256                 # Check that only valid characters should be appearing in
1257                 # the filename.
1259                 $variable_data_validated = $variable_data;
1260                 $variable_data_validated =~ tr|a-zA-Z0-9\.\/\-_||d;
1262                 if ($variable_data_validated ne ""){
1264                         # The validated variable is not blank, meaning the
1265                         # variable contains invalid characters, so return
1266                         # an error.
1268                         if ($variable_noerror eq 1){
1270                                 # Page filename contains invalid characters and
1271                                 # the no error value is set to 1 so return a 
1272                                 # value of 2 (meaning that the page filename
1273                                 # is invalid).
1275                                 return 2;
1277                         } elsif ($variable_noerror eq 0) {
1279                                 # Page filename contains invalid characters and
1280                                 # the no error value is set to 0 so return an
1281                                 # error.
1283                                 kiriwrite_error("invalidfilename");
1285                         } else {
1287                                 # The no error value is something else other
1288                                 # than 0 or 1 so return an error.
1290                                 kiriwrite_error("invalidvariable");
1292                         }
1294                 }
1296                 # Check if the page filename contains the directory command
1297                 # for up a directory level and if it is, return an error
1298                 # or return with a number.
1300                 do {
1302                         # Get a character from the filename passed to this subroutine.
1304                         $variable_data_char = substr($variable_data, $variable_data_seek, 1);
1306                         # Check if the current character is the forward slash character.
1308                         if ($variable_data_char eq "/"){
1310                                 # Check if the current directory is blank (and on the first level), or if the
1311                                 # current directory contains two dots or one dot, if it does return an error.
1313                                 $variable_data_slash = 1;
1315                                 if ($variable_database_listcurrent eq "" && $variable_data_firstlevel eq 1 || $variable_database_listcurrent eq ".." || $variable_database_listcurrent eq "."){
1317                                         # Check if the noerror value is set to 1, if it is return an
1318                                         # number, else return an proper error.
1320                                         if ($variable_noerror eq 1){
1322                                                 # Page filename contains invalid characters and
1323                                                 # the no error value is set to 1 so return a 
1324                                                 # value of 2 (meaning that the page filename
1325                                                 # is invalid).
1327                                                 return 2;
1329                                         } elsif ($variable_noerror eq 0) {
1331                                                 # Page filename contains invalid characters and
1332                                                 # the no error value is set to 0 so return an
1333                                                 # error.
1335                                                 kiriwrite_error("invalidfilename");
1337                                         } else {
1339                                                 # The no error value is something else other
1340                                                 # than 0 or 1 so return an error.
1342                                                 kiriwrite_error("invalidvariable");
1344                                         }
1346                                 }
1348                                 # Append the forward slash, clear the current directory name and set
1349                                 # the first directory level value to 0.
1351                                 $variable_database_list = $variable_database_list . $variable_data_char;
1352                                 $variable_database_listcurrent = "";
1353                                 $variable_data_firstlevel = 0;
1355                         } else {
1357                                 # Append the current character to the directory name and to the current
1358                                 # directory name.
1360                                 $variable_data_slash = 0;
1362                                 $variable_database_list = $variable_database_list . $variable_data_char;
1363                                 $variable_database_listcurrent = $variable_database_listcurrent . $variable_data_char;
1365                         }
1367                         # Increment the seek counter.
1369                         $variable_data_seek++;
1371                 } until ($variable_data_seek eq $variable_data_length);
1373                 # Check if the last character is a slash and return an
1374                 # error if it is.
1376                 if ($variable_data_slash eq 1){
1378                         if ($variable_noerror eq 1){
1380                                 # Last character is a slash and the no error 
1381                                 # value is set to 1 so return a value of 2 
1382                                 # (meaning that the page filename is invalid).
1384                                 return 2;
1386                         } elsif ($variable_noerror eq 0) {
1388                                 # Page filename contains a slash for the last
1389                                 # character and the no error value is set to 0 
1390                                 # so return an error.
1392                                 kiriwrite_error("invalidfilename");
1394                         } else {
1396                                 # The no error value is something else other
1397                                 # than 0 or 1 so return an error.
1399                                 kiriwrite_error("invalidvariable");
1401                         }
1403                 }
1405                 return 0;
1407         } elsif ($variable_type eq "module"){
1409                 # The variable type is a presentation module filename.
1411                 # Check if the variable_data is blank and if it is
1412                 # return an error.
1414                 if ($variable_data eq ""){
1416                         # The presentation module is blank so check if an error
1417                         # value should be returned or a number should be
1418                         # returned.
1420                         if ($variable_noerror eq 1){
1422                                 # Module name is blank and the no error value 
1423                                 # is set to 1 so return a value of 2 (meaning 
1424                                 # that the page filename is blank).
1426                                 return 1;
1428                         } elsif ($variable_noerror eq 0) {
1430                                 # Module name contains is blank and the no error 
1431                                 # value is set to 0 so return an error.
1433                                 kiriwrite_critical("moduleblank");
1435                         } else {
1437                                 # The no error value is something else other
1438                                 # than 0 or 1 so return an error.
1440                                 kiriwrite_critical("invalidvalue");
1442                         }
1444                 } else {
1446                 }
1448                 my $variable_data_validated = $variable_data;
1449                 $variable_data_validated =~ tr/a-zA-Z0-9//d;
1451                 if ($variable_data_validated eq ""){
1453                 } else {
1455                         if ($variable_noerror eq 1){
1457                                 # Module name contains invalid characters and
1458                                 # the no error value is set to 1 so return a 
1459                                 # value of 2 (meaning that the page filename
1460                                 # is invalid).
1462                                 return 2;
1464                         } elsif ($variable_noerror eq 0) {
1466                                 # Module name contains invalid characters and
1467                                 # the no error value is set to 0 so return an
1468                                 # error.
1470                                 kiriwrite_critical("moduleinvalid");
1472                         } else {
1474                                 # The no error value is something else other
1475                                 # than 0 or 1 so return an error.
1477                                 kiriwrite_error("invalidvalue");
1479                         }
1481                 }
1483                 return 0;
1485         } elsif ($variable_type eq "utf8"){
1487                 # The variable type is a UTF8 string.
1489                 if (!$variable_data){
1491                         $variable_data = "";
1493                 }
1495                 my $chunk = 0;
1496                 my $process = 8192;
1497                 my $length = 0;
1498                 my $chunkdata = "";
1500                 while ($chunk < $length){
1502                         $chunkdata = substr($variable_data, $chunk, $process);
1504                         if ($chunkdata =~ m/\A(
1505                                 [\x09\x0A\x0D\x20-\x7E]            # ASCII
1506                                 | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
1507                                 |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
1508                                 | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
1509                                 |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
1510                                 |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
1511                                 | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
1512                                 |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
1513                         )*\z/x){
1515                                 # The UTF-8 string is valid.
1516         
1517                         } else {
1518         
1519                                 # The UTF-8 string is not valid, check if the no error
1520                                 # value is set to 1 and return an error if it isn't.
1521         
1522                                 if ($variable_noerror eq 1){
1523         
1524                                         # The no error value has been set to 1, so return
1525                                         # a value of 1 (meaning that the UTF-8 string is
1526                                         # invalid).
1527         
1528                                         return 1; 
1529         
1530                                 } elsif ($variable_noerror eq 0) {
1531         
1532                                         # The no error value has been set to 0, so return
1533                                         # an error.
1534         
1535                                         kiriwrite_error("invalidutf8");
1536         
1537                                 } else {
1538         
1539                                         # The no error value is something else other than 0
1540                                         # or 1, so return an error.
1541         
1542                                         kiriwrite_error("invalidoption");
1543         
1544                                 }
1545         
1546                         }
1549                         $chunk = $chunk + $process;
1551                 }
1553 #               # Check if the string is a valid UTF8 string.
1554
1555 #               if ($variable_data =~ m/^(
1556 #                       [\x09\x0A\x0D\x20-\x7E]              # ASCII
1557 #                       | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
1558 #                       |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
1559 #                       | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
1560 #                       |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
1561 #                       |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
1562 #                       | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
1563 #                       |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
1564 #               )*$/x){
1565
1566 #                       # The UTF-8 string is valid.
1567
1568 #               } else {
1569
1570 #                       # The UTF-8 string is not valid, check if the no error
1571 #                       # value is set to 1 and return an error if it isn't.
1572
1573 #                       if ($variable_noerror eq 1){
1574
1575 #                               # The no error value has been set to 1, so return
1576 #                               # a value of 1 (meaning that the UTF-8 string is
1577 #                               # invalid).
1578
1579 #                               return 1; 
1580
1581 #                       } elsif ($variable_noerror eq 0) {
1582
1583 #                               # The no error value has been set to 0, so return
1584 #                               # an error.
1585
1586 #                               kiriwrite_error("invalidutf8");
1587
1588 #                       } else {
1589
1590 #                               # The no error value is something else other than 0
1591 #                               # or 1, so return an error.
1592
1593 #                               kiriwrite_error("invalidoption");
1594
1595 #                       }
1596
1597 #               }
1599                 return 0;
1601         } elsif ($variable_type eq "serverprotocol"){
1603                 # Check if the server protocol is TCP or UDP and return
1604                 # an error if it isn't.
1606                 if ($variable_data ne "tcp" && $variable_data ne "udp"){
1608                         # The protocol given is not valid, check if the no
1609                         # error value is set to 1 and return an error if it isn't.
1611                         if ($variable_noerror eq 1){
1613                                 # The no error value has been set to 1, so return a
1614                                 # value of 1 (meaning that the server protocol is
1615                                 # invalid).
1617                                 return 1;
1619                         } elsif ($variable_noerror eq 0){
1621                                 # The no error value has been set to 0, so return
1622                                 # an error.
1624                                 kiriwrite_error("serverprotocolinvalid");
1626                         } else {
1628                                 # The no error value is something else other than 0
1629                                 # or 1, so return an error.
1631                                 kiriwrite_error("invalidoption");
1633                         }
1635                 }
1637                 return 0;
1639         } elsif ($variable_type eq "port"){
1641                 # Check if the port number given is less than 0 or more than 65535
1642                 # and return an error if it is.
1644                 if ($variable_data < 0 || $variable_data > 65535){
1646                         # The port number is less than 0 and more than 65535 so
1647                         # check if the no error value is set to 1 and return an
1648                         # error if it isn't.
1650                         if ($variable_noerror eq 1){
1652                                 # The no error value has been set to 1, so return a
1653                                 # value of 1 (meaning that the port number is invalid).
1655                                 return 1;
1657                         } elsif ($variable_noerror eq 0){
1659                                 # The no error value has been set to 0, so return
1660                                 # an error.
1662                                 kiriwrite_error("serverportnumberinvalid");
1664                         } else {
1666                                 # The no error value is something else other than 0
1667                                 # or 1, so return an error.
1669                                 kiriwrite_error("invalidoption");
1671                         }
1673                 }
1675                 return 0;
1677         }
1679         # Another type than the valid ones above has been specified so return an error specifying an invalid option.
1680         kiriwrite_error("invalidoption");
1684 sub kiriwrite_output_header{
1685 #################################################################################
1686 # kiriwrite_output_header: Outputs the header to the browser/stdout/console.    #
1687 #                                                                               #
1688 # Usage:                                                                        #
1689 #                                                                               #
1690 # kiriwrite_output_header();                                                    #
1691 #################################################################################
1693         # Print a header saying that the page expires immediately since the
1694         # date is set in the past.
1696         print "Expires: Sun, 01 Jan 2006 00:00:00 GMT\r\n";
1697         print "Content-Type: text/html; charset=utf-8;\r\n\r\n";
1698         return;
1701 sub kiriwrite_processfilename{
1702 #################################################################################
1703 # kiriwrite_processfilename: Processes a name and turns it into a filename that #
1704 # can be used by Kiriwrite.                                                     #
1705 #                                                                               #
1706 # Usage:                                                                        #
1707 #                                                                               #
1708 # kiriwrite_processfilename(text);                                              #
1709 #                                                                               #
1710 # text          Specifies the text to be used in the process for creating a new #
1711 #               filename.                                                       #
1712 #################################################################################
1714         # Get the values that have been passed to the subroutine.
1716         my ($process_text) = @_;
1718         # Define some variables that will be used later on.
1720         my $processed_stageone  = "";
1721         my $processed_stagetwo  = "";
1722         my $processed_length    = "";
1723         my $processed_char      = "";
1724         my $processed_seek      = 0;
1725         my $processed_filename  = "";
1727         # Set the first stage value of the processed filename to the
1728         # process filename and then filter it out to only contain
1729         # numbers and letters (no spaces) and then convert the
1730         # capitals to small letters.
1732         $processed_stageone = $process_text;
1733         $processed_stageone =~ tr#a-zA-Z0-9##cd;
1734         $processed_stageone =~ tr/A-Z/a-z/;
1736         # Now set the second stage value of the processed filename
1737         # to the first stage value of the processed filename and
1738         # then limit the filename down to 32 characters.
1740         $processed_stagetwo = $processed_stageone;
1741         $processed_length = length($processed_stagetwo);
1743         # Process the second stage filename into the final 
1744         # filename and do so until the seek counter is 32
1745         # or reaches the length of the second stage filename.
1747         do {
1749                 # Get the character that is the seek counter
1750                 # is set at.
1752                 $processed_char = substr($processed_stagetwo, $processed_seek, 1);
1754                 # Append to the final processed filename.
1756                 $processed_filename = $processed_filename . $processed_char;
1758                 # Increment the seek counter.
1760                 $processed_seek++;
1762         } until ($processed_seek eq 32 || $processed_seek eq $processed_length);
1764         return $processed_filename;
1768 sub kiriwrite_language{
1769 #################################################################################
1770 # kiriwrite_language: Process language strings that needs certain text inserted.#
1771 #                                                                               #
1772 # Usage:                                                                        #
1773 #                                                                               #
1774 # kiriwrite_language(string, [text, text, ...]);                                #
1775 #                                                                               #
1776 # string        Specifies the string to process.                                #
1777 # text          Specifies the text to pass to the string (can be repeated many  #
1778 #               times).                                                         #
1779 #################################################################################
1781         my $string = shift;
1782         my $item;
1784         foreach $item (@_){
1786                 $string =~ s/%s/$item/;
1788         }
1790         return $string;
1794 sub kiriwrite_error{
1795 #################################################################################
1796 # kiriwrite_error: Prints out an error message.                                 #
1797 #                                                                               #
1798 # Usage:                                                                        #
1799 #                                                                               #
1800 # kiriwrite_error(errortype, errorext);                                         #
1801 #                                                                               #
1802 # errortype     Specifies the type of error that occured.                       #
1803 # errorext      Specifies the extended error information.                       #
1804 #################################################################################
1806         # Get the error type from the subroutine.
1808         my ($error_type, $error_extended) = @_;
1810         # Disconnect from the database server.
1812         if ($kiriwrite_dbmodule){
1813                 $kiriwrite_dbmodule->disconnect();
1814         }
1816         # Load the list of error messages.
1818         my @kiriwrite_error = (
1820                 # Catch all error message.
1821                 "generic", 
1823                 # Standard error messages.
1824                 "blankfilename", "blankvariable", "fileexists", "internalerror", "invalidoption", "invalidaction", "invalidfilename", "invalidmode", "invalidutf8", "invalidvariable", "variabletoolong",
1826                 # Specific error messages.
1827                 "blankcompiletype", "blankdatabasepageadd", "blankdirectory", "blankfindfilter", "blankdatetimeformat", "browsenumbertoolong", "browsenumberinvalid",  "databaseconnectionerror", "databasecategoriestoolong", "databasecopysame", "databasealreadyexists", "datadirectorymissing", "datadirectoryinvalidpermissions", "databasedescriptiontoolong", "databasefilenameinvalid", "databasefilenametoolong", "databaseerror", "databaseinvalidpermissions", "databasenameinvalid", "databasenametoolong", "databasenameblank", "databasemissingfile", "databasemovemissingfile", "databasenorename", "databasemovesame", "dbmoduleblank", "dbmoduleinvalid", "dbdirectoryblank", "dbdirectoryinvalid", "dbmodulemissing", "filtersdatabasenotcreated", "filtersdbdatabaseerror", "filtersdbpermissions", "filtersdbmissing", "filteridblank", "filterdoesnotexist", "filteridinvalid", "filteridtoolong", "findfiltertoolong", "filterpriorityinvalid", "filterpriorityinvalidchars", "filterprioritytoolong", "invalidcompiletype", "invalidpagenumber", "nopagesselected",      "invaliddirectory", "invaliddatetimeformat", "invalidlanguagefilename", "languagefilenamemissing", "moduleblank", "moduleinvalid",      "newcopydatabasedatabaseerror", "newcopydatabasedoesnotexist", "newcopydatabasefileinvalidpermissions", "newmovedatabasedatabaseerror", "newmovedatabasedoesnotexist", "newmovedatabasefileinvalidpermissions", "nodatabasesavailable", "nodatabaseselected", "noeditvaluesselected", "oldcopydatabasedatabaseerror", "oldcopydatabasedoesnotexist", "oldcopydatabasefileinvalidpermissions", "oldmovedatabasedatabaseerror",   "oldmovedatabasedoesnotexist", "oldmovedatabasefileinvalidpermissions", "outputdirectoryblank", "outputdirectoryinvalid", "outputdirectorymissing", "outputdirectoryinvalidpermissions", "overridetemplatevalueinvalid", "overridetemplatetoolong", "overridetemplateinvalid",  "presmoduleblank", "presmoduleinvalid", "presmodulemissing", "pagefilenamedoesnotexist", "pagefilenameexists", "pagefilenameinvalid", "pagefilenametoolong", "pagefilenameblank", "pagetitletoolong", "pagedescriptiontoolong", "pagesectiontoolong", "pagedatabasefilenametoolong", "pagesettingstoolong", "pagesettingsinvalid", "pagetemplatefilenametoolong", "replacefiltertoolong", "servernameinvalid", "servernametoolong", "serverdatabasenameinvalid", "serverdatabasenametoolong", "serverdatabaseusernameinvalid", "serverdatabaseusernametoolong", "serverdatabasepasswordtoolong", "serverdatabasetableprefixinvalid", "serverdatabasetableprefixtoolong", "serverportnumberinvalid", "serverportnumberinvalidcharacters", "serverportnumbertoolong", "serverprotocolnametoolong", "serverprotocolinvalid", "templatenameblank", "templatefilenameexists", "templatefilenameinvalid", "templatedatabaseerror", "templatedatabaseinvalidpermissions", "templatedatabaseinvalidformat", "templatedirectoryblank", "templatedirectoryinvalid", "templatedatabasenotcreated", "templatefilenametoolong", "templatenametoolong", "templatedescriptiontoolong", "templatedatabasemissing", "templatedoesnotexist", "templatefilenameblank", "textarearowblank", "textarearowtoolong", "textarearowinvalid", "textareacolblank", "textareacoltoolong", "textareacolinvalid"
1829         );
1831         # Check if the error message name is a valid error message name
1832         # and return the generic error message if it isn't.
1834         my $error_string = "";
1836         if (grep /^$error_type$/, @kiriwrite_error){
1838                 # The error type is valid so get the error language string
1839                 # associated with this error messsage name.
1841                 $error_string = $kiriwrite_lang->{error}->{$error_type};
1843         } else {
1845                 # The error type is invalid so set the error language
1846                 # string using the generic error message name.
1848                 $error_string = $kiriwrite_lang->{error}->{generic};
1850         }
1852         $kiriwrite_presmodule->clear();
1854         $kiriwrite_presmodule->startbox("errorbox");
1855         $kiriwrite_presmodule->addtext($kiriwrite_lang->{error}->{error}, { Style => "errorheader" });
1856         $kiriwrite_presmodule->addlinebreak();
1857         $kiriwrite_presmodule->addtext($error_string, { Style => "errortext" });
1859         # Check to see if extended error information was passed.
1861         if ($error_extended){
1863                 # Write the extended error information.
1865                 $kiriwrite_presmodule->addlinebreak();
1866                 $kiriwrite_presmodule->addlinebreak();
1867                 $kiriwrite_presmodule->addtext($kiriwrite_lang->{error}->{extendederror});
1868                 $kiriwrite_presmodule->addlinebreak();
1869                 $kiriwrite_presmodule->addlinebreak();
1870                 $kiriwrite_presmodule->startbox("datalist");
1871                 $kiriwrite_presmodule->addtext($error_extended);
1872                 $kiriwrite_presmodule->endbox();
1874         }
1876         $kiriwrite_presmodule->endbox();
1878         kiriwrite_output_header;
1879         kiriwrite_output_page($kiriwrite_lang->{error}->{error}, $kiriwrite_presmodule->grab(), "none");
1881         exit;
1885 sub kiriwrite_fileexists{
1886 #################################################################################
1887 # kiriwrite_fileexists: Check if a file exists and returns a value depending on #
1888 # if the file exists or not.                                                    #
1889 #                                                                               # 
1890 # Usage:                                                                        #
1891 #                                                                               #
1892 # kiriwrite_fileexists(filename);                                               #
1893 #                                                                               #
1894 # filename      Specifies the file name to check if it exists or not.           #
1895 #################################################################################
1897         # Get the value that was passed to the subroutine.
1899         my ($filename) = @_;
1901         # Check if the filename exists, if it does, return a value of 0, else
1902         # return a value of 1, meaning that the file was not found.
1904         if (-e $filename){
1906                 # Specified file does exist so return a value of 0.
1908                 return 0;
1910         } else {
1912                 # Specified file does not exist so return a value of 1.
1914                 return 1;
1916         }
1920 sub kiriwrite_filepermissions{
1921 #################################################################################
1922 # kiriwrite_filepermissions: Check if the file permissions of a file and return #
1923 # either a 1 saying that the permissions are valid or return a 0 saying that    #
1924 # the permissions are invalid.                                                  #
1925 #                                                                               #
1926 # Usage:                                                                        #
1927 #                                                                               #
1928 # kiriwrite_filepermissions(filename, [read], [write], [filemissingskip]);      #
1929 #                                                                               #
1930 # filename              Specifies the filename to check for permissions.        #
1931 # read                  Preform check that the file is readable.                #
1932 # write                 Preform check that the file is writeable.               #
1933 # filemissingskip       Skip the check of seeing if it can read or write if the #
1934 #                       file is missing.                                        #
1935 #################################################################################
1937         # Get the values that was passed to the subroutine.
1939         my ($filename, $readpermission, $writepermission, $ignorechecks) = @_;
1941         # Check to make sure that the read permission and write permission values
1942         # are only 1 character long.
1944         kiriwrite_variablecheck($readpermission, "maxlength", 1, 0);
1945         kiriwrite_variablecheck($writepermission, "maxlength", 1, 0);
1946         kiriwrite_variablecheck($ignorechecks, "maxlength", 1, 0);
1948         my $ignorechecks_result = 0;
1950         # Check if the file should be ignored for read and write checking if 
1951         # it doesn't exist.
1953         if ($ignorechecks){
1955                 if (-e $filename){
1957                         # The file exists so the checks are to be done.
1959                         $ignorechecks_result = 0;
1961                 } else {
1963                         # The file does not exist so the checks don't need to
1964                         # be done to prevent false positives.
1966                         $ignorechecks_result = 1;
1968                 }
1970         } else {
1972                 $ignorechecks_result = 0;
1974         }
1976         # Check if the file should be checked to see if it can be read.
1978         if ($readpermission && $ignorechecks_result eq 0){
1980                 # The file should be checked to see if it does contain read permissions
1981                 # and return a 0 if it is invalid.
1983                 if (-r $filename){
1985                         # The file is readable, so do nothing.
1987                 } else {
1989                         # The file is not readable, so return 1.
1991                         return 1;
1993                 }
1995         }
1997         # Check if the file should be checked to see if it can be written.
1999         if ($writepermission && $ignorechecks_result eq 0){
2001                 # The file should be checked to see if it does contain write permissions
2002                 # and return a 0 if it is invalid.
2004                 if (-w $filename){
2006                         # The file is writeable, so do nothing.
2008                 } else {
2010                         # The file is not writeable, so return 1.
2012                         return 1;
2014                 }
2016         }
2018         # No problems have occured, so return 0.
2020         return 0;
2024 sub kiriwrite_utf8convert{
2025 #################################################################################
2026 # kiriwrite_utf8convert: Properly converts values into UTF-8 values.            #
2027 #                                                                               #
2028 # Usage:                                                                        #
2029 #                                                                               #
2030 # utfstring     # The UTF-8 string to convert.                                  #
2031 #################################################################################
2033         # Get the values passed to the subroutine.
2035         my ($utfstring) = @_;
2037         # Load the Encode perl module.
2039         use Encode qw(decode_utf8);
2041         # Convert the string.
2043         my $finalutf8 = Encode::decode_utf8( $utfstring );
2045         return $finalutf8;
2049 sub kiriwrite_critical{
2050 #################################################################################
2051 # kiriwrite_critical: Displays an critical error message that cannot be         #
2052 # normally by the kiriwrite_error subroutine.                                   #
2053 #                                                                               #
2054 # Usage:                                                                        #
2055 #                                                                               #
2056 # errortype     Specifies the type of critical error that has occured.          #
2057 #################################################################################
2059         # Get the value that was passed to the subroutine.
2061         my ($error_type) = @_;
2063         my %error_list;
2065         # Get the error type from the errortype string.
2067         %error_list = (
2069                 # Generic critical error message.
2071                 "generic"                       => "A critical error has occured but the error is not known to Kiriwrite.",
2073                 # Specific critical error messages.
2075                 "configfilemissing"             => "The Kiriwrite configuration file is missing! Running the installer script for Kiriwrite is recommended.",
2076                 "configfileinvalidpermissions"  => "The Kiriwrite configuration file has invalid permission settings set! Please set the valid permission settings for the configuration file.",
2077                 "dbmodulemissing"               => "The database module is missing! Running the installer script for Kiriwrite is recommended.",
2078                 "dbmoduleinvalidpermissions"    => "The database module cannot be used as it has invalid permission settings set! Please set the valid permission settings for the configuration file.",
2079                 "dbmoduleinvalid"               => "The database module name given is invalid. Running the installer script for Kiriwrite is recommended.",
2080                 "invalidvalue"                  => "An invalid value was passed.",
2081                 "languagefilenameblank"         => "The language filename given is blank! Running the installer script for Kiriwrite is recommended.",
2082                 "languagefilenameinvalid"       => "The language filename given is invalid! Running the installer script for Kiriwrite is recommended.",
2083                 "languagefilemissing"   => "The language filename given does not exist. Running the installer script for Kiriwrite is recommended.",
2084                 "languagefilenameinvalidpermissions"    => "The language file with the filename given has invalid permissions set. Please set the valid permission settings for the language file.",
2085                 "presmodulemissing"             => "The presentation module is missing! Running the installer script for Kiriwrite is recommended.",
2086                 "presmoduleinvalidpermissions"  => "The presentation module cannot be used as it has invalid permission settings set! Please set the valid permission settings for the presentation module.",
2087                 "presmoduleinvalid"             => "The presentation module name given is invalid. Running the installer script for Kiriwrite is recommended.",
2088                 "textarearowblank"              => "The text area row value given is blank.",
2089                 "textarearowtoolong"            => "The text area row value is too long. Running the installer script for Kiriwrite is recommended.",
2090                 "textarearowinvalid"            => "The text area row value is invalid. Running the installer script for Kiriwrite is recommended.",
2091                 "textareacolblank"              => "The text area row value given is blank.",
2092                 "textareacoltoolong"            => "The text area column value is too long. Running the installer script for Kiriwrite is recommended.",
2093                 "textareacolinvalid"            => "The text area column value is invalid. Running the installer script for Kiriwrite is recommended.",
2095         );
2097         if (!$error_list{$error_type}){
2099                 $error_type = "generic";
2101         }
2103         print "Expires: Sun, 01 Jan 2006 00:00:00 GMT\r\n";
2104         print "Content-Type: text/html; charset=utf-8;\r\n\r\n";
2105         print "Critical Error: " . $error_list{$error_type};
2106         exit;
2110 sub kiriwrite_output_page{
2111 #################################################################################
2112 # kiriwrite_output_page: Outputs the page to the browser/stdout/console.        #
2113 #                                                                               #
2114 # Usage:                                                                        #
2115 #                                                                               #
2116 # kiriwrite_output_page(pagetitle, pagedata, menutype);                         #
2117 #                                                                               #
2118 # pagetitle     Specifies the page title.                                       #
2119 # pagedata      Specifies the page data.                                        #
2120 # menutype      Prints out which menu to use.                                   #
2121 #################################################################################
2123         my ($pagetitle, $pagedata, $menutype) = @_;
2125         # Open the script page template and load it into the scriptpage variable,
2126         # while declaring the variable.
2128         open (my $filehandle_scriptpage, "<:utf8", 'page.html');
2129         my @scriptpage = <$filehandle_scriptpage>;
2130         binmode $filehandle_scriptpage, ':utf8';
2131         close ($filehandle_scriptpage);
2133         # Define the variables required.
2135         my $scriptpageline = "";
2136         my $pageoutput = "";
2137         my $menuoutput = "";
2139         $kiriwrite_presmodule->clear();
2141         # Print out the main menu for Kiriwrite.
2143         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=db", { Text => $kiriwrite_lang->{menu}->{viewdatabases} });
2144         $kiriwrite_presmodule->addtext(" | ");
2145         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=page", { Text => $kiriwrite_lang->{menu}->{viewpages} });
2146         $kiriwrite_presmodule->addtext(" | ");
2147         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=filter", { Text => $kiriwrite_lang->{menu}->{viewfilters} });
2148         $kiriwrite_presmodule->addtext(" | ");
2149         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=template", { Text => $kiriwrite_lang->{menu}->{viewtemplates} });
2150         $kiriwrite_presmodule->addtext(" | ");
2151         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=compile", { Text => $kiriwrite_lang->{menu}->{compilepages} });
2152         $kiriwrite_presmodule->addtext(" | ");
2153         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=settings", { Text => $kiriwrite_lang->{menu}->{viewsettings} });
2154         $kiriwrite_presmodule->addlinebreak();
2156         # Check what menu is going to be printed along with the default 'top' menu.
2158         if ($menutype eq "database"){
2160                 # If the menu type is database then print out the database sub-menu.
2162                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=db", { Text => $kiriwrite_lang->{database}->{submenu_viewdatabases} });
2163                 $kiriwrite_presmodule->addtext(" | ");
2164                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=db&action=new", { Text => $kiriwrite_lang->{database}->{submenu_adddatabase} });
2166         } elsif ($menutype eq "pages"){
2167                 # If the menu type is pages then print out the pages sub-menu.
2169                 # First, fetch the database name from the HTTP query string.
2171                 my $db_filename = $form_data->{'database'};
2173                 # Check if a value has been placed in the db_filename string.
2175                 if (!$db_filename){
2177                         # As the database filename is blank, don't add an option to add a page.
2179                 } else {
2181                         # A database file has been specified so add an option to add a page to
2182                         # the selected database.
2184                         $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=page&action=add&database="  . $db_filename, { Text => $kiriwrite_lang->{pages}->{submenu_addpage} });
2186                 }
2188         } elsif ($menutype eq "filter"){
2190                 # If the menu type is filters then print out the filter sub-menu.
2192                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=filter", { Text => $kiriwrite_lang->{filter}->{submenu_showfilters} });
2193                 $kiriwrite_presmodule->addtext(" | ");
2194                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=filter&action=add", { Text => $kiriwrite_lang->{filter}->{submenu_addfilter} });
2196         } elsif ($menutype eq "settings"){
2198                 # If the menu type is options then print out the options sub-menu.
2200                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=settings", { Text => $kiriwrite_lang->{setting}->{submenu_viewsettings} });
2201                 $kiriwrite_presmodule->addtext(" | ");
2202                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=settings&action=edit", { Text => $kiriwrite_lang->{setting}->{submenu_editsettings} });
2204         } elsif ($menutype eq "template"){
2206                 # If the menu type is template then print out the template sub-menu.
2208                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=template", { Text => $kiriwrite_lang->{template}->{submenu_showtemplates} });
2209                 $kiriwrite_presmodule->addtext(" | ");
2210                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=template&action=add", { Text => $kiriwrite_lang->{template}->{submenu_addtemplate} });
2212         } elsif ($menutype eq "compile"){
2214                 # If the menu type is compile then print out the compile sub-menu.
2216                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=compile", { Text => $kiriwrite_lang->{compile}->{submenu_listdatabases} });
2217                 $kiriwrite_presmodule->addtext(" | ");
2218                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=compile&action=all", { Text => $kiriwrite_lang->{compile}->{submenu_compileall} });
2219                 $kiriwrite_presmodule->addtext(" | ");
2220                 $kiriwrite_presmodule->addlink($kiriwrite_env{'script_filename'} . "?mode=compile&action=clean", { Text => $kiriwrite_lang->{compile}->{submenu_cleanoutputdirectory} });
2222         }
2224         $menuoutput = $kiriwrite_presmodule->grab();
2226         # Find <kiriwrite> tages and replace with the apporiate variables.
2228         foreach $scriptpageline (@scriptpage){
2230                 $scriptpageline =~ s/<kiriwrite:menu>/$menuoutput/g;
2231                 $scriptpageline =~ s/<kiriwrite:imagespath>/$kiriwrite_config{"directory_noncgi_images"}/g;
2232                 $scriptpageline =~ s/<kiriwrite:pagedata>/$pagedata/g;
2234                 # Check if page title specified is blank, otherwise add a page title
2235                 # to the title.
2237                 if ($pagetitle eq ""){
2238                         $scriptpageline =~ s/<kiriwrite:title>//g;
2239                 } else {
2240                         $scriptpageline =~ s/<kiriwrite:title>/ ($pagetitle)/g;
2241                 }
2243                 
2245                 # Append processed line to the pageoutput variable.
2247                 $pageoutput = $pageoutput . $scriptpageline;
2249         }
2251         binmode STDOUT, ':utf8';
2253         print $pageoutput;
2255         return;
2259 #################################################################################
2260 # End listing the functions needed.                                             #
2261 #################################################################################
2263 #################################################################################
2264 # Begin proper script execution.                                                #
2265 #################################################################################
2267 kiriwrite_settings_load;        # Load the configuration options.
2269 my $query_lite = new CGI::Lite;
2271 # Check if a mode has been specified and if a mode has been specified, continue
2272 # and work out what mode has been specified.
2274 $form_data = $query_lite->parse_form_data;
2276 if ($form_data->{'mode'}){
2277         my $http_query_mode = $form_data->{'mode'};
2279         if ($http_query_mode eq "db"){
2281                 # If mode is 'db' (database), then load the database perl library and
2282                 # check what action is required.
2284                 require "./lib/database.lib";
2286         } elsif ($http_query_mode eq "page"){
2288                 # If mode is 'page', load the page library and then check what 
2289                 # action is required.
2291                 require "./lib/page.lib";
2293         } elsif ($http_query_mode eq "filter"){
2295                 # Load the filter perl library and then check the
2296                 # value of the action HTTP query.
2298                 require "./lib/filter.lib";
2300         } elsif ($http_query_mode eq "template"){
2302                 # Load the template perl library and check if an action has
2303                 # been specified in the HTTP query.
2305                 require "./lib/template.lib";
2307         } elsif ($http_query_mode eq "compile"){
2309                 # Load the compile perl library.
2311                 require "./lib/compile.lib";
2313         } elsif ($http_query_mode eq "settings"){
2315                 # Load the settings perl library.
2317                 require "./lib/settings.lib";
2319         } else {
2320                 # Another mode has been specified than the ones above, so return an error saying that
2321                 # an invalid option was specified.
2323                 kiriwrite_error("invalidmode");
2324         }
2326 } else {
2328         # No mode has been specified, so print the default "first-run" view of the
2329         # database list.
2331         require "./lib/database.lib";
2333         my $pagedata = kiriwrite_database_list();
2335         kiriwrite_output_header;                # Output the header to browser/console/stdout.
2336         kiriwrite_output_page("", $pagedata, "database");       # Output the page to browser/console/stdout.
2337         exit;                                   # End the script.
2341 __END__
2343 =head1 NAME
2345 Kiriwrite
2347 =head1 DESCRIPTION
2349 Web-based webpage compiler.
2351 =head1 AUTHOR
2353 Steve Brokenshire <sbrokenshire@xestia.co.uk>
2355 =head1 USAGE
2357 This perl script is intended to be used on a web server which has CGI with Perl support or with mod_perl support.
2359 =head1 DOCUMENTATION
2361 For more information on how to use Kiriwrite, please see the documentation that was included with Kiriwrite.
2363 - From the Xestia Documentation website: http://documentation.xestia.co.uk and click on the Kiriwrite link on the page.
2365 - From the Documentation directory from the Kiriwrite source packages (.tar/.tar.gz/.tar.bz2).
2367 - In the /usr/share/doc/kiriwrite directory if you installed the distribution-specific packages (and also have access to the server itself).
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy