#!/usr/bin/perl -Tw
#################################################################################
-# Kiriwrite Installer Script (install.cgi) #
+# Kiriwrite Installer Script (install.pl/install.cgi) #
# Installation script for Kiriwrite #
# #
-# Version: 0.1.0 #
+# Version: 0.5.0 #
+# mod_perl 2.x compatabile version #
# #
-# Copyright (C) 2005-2007 Steve Brokenshire <sbrokenshire@xestia.co.uk> #
+# Copyright (C) 2005-2008 Steve Brokenshire <sbrokenshire@xestia.co.uk> #
# #
# This program is free software; you can redistribute it and/or modify it under #
# the terms of the GNU General Public License as published by the Free #
use warnings; # Write warnings to the HTTP Server Log file.
use utf8;
-#use CGI qw(:standard *table *Tr *td);
-use CGI::Lite;
-#use CGI::Carp('fatalsToBrowser'); # Output errors to the browser.
+
+eval "use CGI::Lite";
+
+if ($@){
+ print "Content-type: text/html;\r\n\r\n";
+ print "The CGI::Lite Perl Module is not installed. Please install CGI::Lite and then run this installation script again. CGI::Lite can be installed through CPAN.";
+ exit;
+}
+
+# Check if mod_perl is running and if it is then add a notice to say
+# that additional configuration has to be made.
+
+my $modperlenabled = 0;
+my $installscriptname = "install.cgi";
+my $kiriwritescriptname = "kiriwrite.cgi";
+
+if ($ENV{'MOD_PERL'}){
+
+ # MOD_PERL 2.X SPECIFIC SECTION.
+
+ use lib '';
+ chdir('');
+
+ $modperlenabled = 1;
+ $installscriptname = "install.pl";
+ $kiriwritescriptname = "kiriwrite.pl";
+
+}
# Setup strings in specific languages. Style should be no spacing for
# language title and one tabbed spacing for each string.
my $default_textarearows = "10";
my $default_textareacols = "50";
+my $default_outputmodule = "Normal";
+
my $default_server = "localhost";
my $default_port = "3306";
my $default_protocol = "tcp";
$kiriwrite_lang{"en-GB"}{"presmoduleblank"} = "The presentation module name given is blank.";
$kiriwrite_lang{"en-GB"}{"presmoduleinvalid"} = "The presentation module name given is invalid.";
-
+
$kiriwrite_lang{"en-GB"}{"dbmoduleblank"} = "The database module name given is blank.";
$kiriwrite_lang{"en-GB"}{"dbmoduleinvalid"} = "The database module name given is invalid.";
+ $kiriwrite_lang{"en-GB"}{"outputmoduleblank"} = "The output module name given is blank.";
+ $kiriwrite_lang{"en-GB"}{"outputmoduleinvalid"} = "The output module name given is invalid.";
+
$kiriwrite_lang{"en-GB"}{"presmodulemissing"} = "The presentation module with the filename given is missing.";
+ $kiriwrite_lang{"en-GB"}{"outputmodulemissing"} = "The output module with the filename given is missing.";
$kiriwrite_lang{"en-GB"}{"dbmodulemissing"} = "The database module with the filename given is missing.";
$kiriwrite_lang{"en-GB"}{"languagefilenamemissing"} = "The language file with the filename given is missing.";
$kiriwrite_lang{"en-GB"}{"installertitle"} = "Kiriwrite Installer";
$kiriwrite_lang{"en-GB"}{"installertext"} = "This installer script will setup the configuration file used for Kiriwrite. The settings displayed here can be changed at a later date by selecting the Edit Settings link in the View Settings sub-menu.";
+ $kiriwrite_lang{"en-GB"}{"modperlnotice"} = "mod_perl has been detected. Please ensure that you have setup this script and the main Kiriwrite script so that mod_perl can use Kiriwrite properly. Please read the mod_perl specific part of Chapter 1: Installation in the Kiriwrite documentation.";
$kiriwrite_lang{"en-GB"}{"dependencytitle"} = "Dependency and file testing results";
$kiriwrite_lang{"en-GB"}{"requiredmodules"} = "Required Modules";
$kiriwrite_lang{"en-GB"}{"perlmodules"} = "These Perl modules are used internally by Kiriwrite.";
$kiriwrite_lang{"en-GB"}{"systemlanguage"} = "System Language";
$kiriwrite_lang{"en-GB"}{"modules"} = "Modules";
$kiriwrite_lang{"en-GB"}{"presentationmodule"} = "Presentation Module";
+ $kiriwrite_lang{"en-GB"}{"outputmodule"} = "Output Module";
$kiriwrite_lang{"en-GB"}{"databasemodule"} = "Database Module";
$kiriwrite_lang{"en-GB"}{"databaseserver"} = "Database Server";
$kiriwrite_lang{"en-GB"}{"databaseport"} = "Database Port";
$kiriwrite_lang{"en-GB"}{"installscriptremoved"} = "The installer script was removed.";
$kiriwrite_lang{"en-GB"}{"installedmessage"} = "The configuration file for Kiriwrite has been written. To change the settings in the configuration file at a later date use the Edit Settings link in the View Settings sub-menu at the top of the page when using Kiriwrite.";
$kiriwrite_lang{"en-GB"}{"cannotremovescript"} = "Unable to remove the installer script: %s. The installer script will have to be deleted manually.";
- $kiriwrite_lang{"en-GB"}{"usekiriwritetext"} = "To use Kiriwrite click or select the link below (will not work if the Kiriwrite script is not called kiriwrite.cgi):";
+ $kiriwrite_lang{"en-GB"}{"usekiriwritetext"} = "To use Kiriwrite click or select the link below (will not work if the Kiriwrite script is not called kiriwrite.cgi/kiriwrite.pl):";
$kiriwrite_lang{"en-GB"}{"usekiriwritelink"} = "Start using Kiriwrite.";
my $query_lite = new CGI::Lite;
open (my $configfile, "> " . "kiriwrite.cfg");
print $configfile "[config]
- directory_data_db = $passedsettings->{DatabaseDirectory}
- directory_data_output = $passedsettings->{OutputDirectory}
- directory_noncgi_images = $passedsettings->{ImagesURIPath}
-
- system_language = $passedsettings->{Language}
- system_presmodule = $passedsettings->{PresentationModule}
- system_dbmodule = $passedsettings->{DatabaseModule}
- system_datetime = $passedsettings->{DateFormat}
+directory_data_db = $passedsettings->{DatabaseDirectory}
+directory_data_output = $passedsettings->{OutputDirectory}
+directory_noncgi_images = $passedsettings->{ImagesURIPath}
+
+system_language = $passedsettings->{Language}
+system_presmodule = $passedsettings->{PresentationModule}
+system_outputmodule = $passedsettings->{OutputModule}
+system_dbmodule = $passedsettings->{DatabaseModule}
+system_datetime = $passedsettings->{DateFormat}
- display_textareacols = $passedsettings->{TextAreaCols}
- display_textarearows = $passedsettings->{TextAreaRows}
- display_pagecount = 50
- display_filtercount = 50
- display_templatecount = 50
+display_textareacols = $passedsettings->{TextAreaCols}
+display_textarearows = $passedsettings->{TextAreaRows}
+display_pagecount = 50
+display_filtercount = 50
+display_templatecount = 50
- database_server = $passedsettings->{DatabaseServer}
- database_port = $passedsettings->{DatabasePort}
- database_protocol = $passedsettings->{DatabaseProtocol}
- database_sqldatabase = $passedsettings->{DatabaseName}
- database_username = $passedsettings->{DatabaseUsername}
- database_password = $passedsettings->{DatabasePassword}
- database_tableprefix = $passedsettings->{DatabaseTablePrefix}
+database_server = $passedsettings->{DatabaseServer}
+database_port = $passedsettings->{DatabasePort}
+database_protocol = $passedsettings->{DatabaseProtocol}
+database_sqldatabase = $passedsettings->{DatabaseName}
+database_username = $passedsettings->{DatabaseUsername}
+database_password = $passedsettings->{DatabasePassword}
+database_tableprefix = $passedsettings->{DatabaseTablePrefix}
";
close ($configfile);
}
+sub kiriwrite_processconfig{
+#################################################################################
+# kiriwrite_processconfig: Processes an INI style configuration file. #
+# #
+# Usage: #
+# #
+# kiriwrite_processconfig(data); #
+# #
+# data Specifies the data to process. #
+#################################################################################
+
+ my (@settings) = @_;
+
+ my ($settings_line, %settings, $settings, $sectionname, $setting_name, $setting_value);
+
+ foreach $settings_line (@settings){
+
+ next if !$settings_line;
+
+ # Check if the first character is a bracket.
+
+ if (substr($settings_line, 0, 1) eq "["){
+ $settings_line =~ s/\[//;
+ $settings_line =~ s/\](.*)//;
+ $settings_line =~ s/\n//;
+ $sectionname = $settings_line;
+ next;
+ }
+
+ $setting_name = $settings_line;
+ $setting_value = $settings_line;
+ $setting_name =~ s/\=(.*)//;
+ $setting_name =~ s/\n//;
+ $setting_value =~ s/(.*)\=//;
+ $setting_value =~ s/\n//;
+
+ # Remove the spacing before and after the '=' sign.
+
+ $setting_name =~ s/\s+$//;
+ $setting_value =~ s/^\s+//;
+ $setting_value =~ s/\r//;
+
+ $settings{$sectionname}{$setting_name} = $setting_value;
+
+ }
+
+ return %settings;
+
+}
+
#################################################################################
# End list of subroutines. #
#################################################################################
my $http_query_language = $form_data->{'language'};
my $http_query_presmodule = $form_data->{'presmodule'};
+ my $http_query_outputmodule = $form_data->{'outputmodule'};
my $http_query_dbmodule = $form_data->{'dbmodule'};
my $http_query_databaseserver = $form_data->{'databaseserver'};
# Check the module names to see if they're valid.
my $kiriwrite_presmodule_modulename_check = kiriwrite_variablecheck($http_query_presmodule, "module", 0, 1);
+ my $kiriwrite_outputmodule_modulename_check = kiriwrite_variablecheck($http_query_outputmodule, "module", 0, 1);
my $kiriwrite_dbmodule_modulename_check = kiriwrite_variablecheck($http_query_dbmodule, "module", 0, 1);
if ($kiriwrite_presmodule_modulename_check eq 1){
}
+ if ($kiriwrite_outputmodule_modulename_check eq 1){
+
+ # The output module name is blank, so return
+ # an error.
+
+ kiriwrite_error("outputmoduleblank");
+
+ }
+
+ if ($kiriwrite_outputmodule_modulename_check eq 2){
+
+ # The output module name is invalid, so return
+ # an error.
+
+ kiriwrite_error("outputmoduleinvalid");
+
+ }
+
if ($kiriwrite_dbmodule_modulename_check eq 1){
# The database module name is blank, so return
}
- # Check if the database module, presentation module and
- # language file exists.
+ # Check if the database module, presentation module,
+ # output module and language file exists.
if (!-e "Modules/Presentation/" . $http_query_presmodule . ".pm"){
}
+ if (!-e "Modules/Output/" . $http_query_outputmodule . ".pm"){
+
+ # The database module is missing so return an
+ # error.
+
+ kiriwrite_error("outputmodulemissing");
+
+ }
+
if (!-e "Modules/Database/" . $http_query_dbmodule . ".pm"){
# The database module is missing so return an
# Write the new configuration file.
- kiriwrite_writeconfig({ DatabaseDirectory => $http_query_dbdirectory, OutputDirectory => $http_query_outputdirectory, ImagesURIPath => $http_query_imagesuripath, TextAreaCols => $http_query_textareacols, TextAreaRows => $http_query_textarearows, DateFormat => $finaldateformat, Language => $http_query_language, PresentationModule => $http_query_presmodule, DatabaseModule => $http_query_dbmodule, DatabaseServer => $http_query_databaseserver, DatabasePort => $http_query_databaseport, DatabaseProtocol => $http_query_databaseprotocol, DatabaseName => $http_query_databasename, DatabaseUsername => $http_query_databaseusername, DatabasePassword => $http_query_databasepassword, DatabaseTablePrefix => $http_query_databasetableprefix });
+ kiriwrite_writeconfig({ DatabaseDirectory => $http_query_dbdirectory, OutputDirectory => $http_query_outputdirectory, ImagesURIPath => $http_query_imagesuripath, TextAreaCols => $http_query_textareacols, TextAreaRows => $http_query_textarearows, DateFormat => $finaldateformat, Language => $http_query_language, PresentationModule => $http_query_presmodule, OutputModule => $http_query_outputmodule, DatabaseModule => $http_query_dbmodule, DatabaseServer => $http_query_databaseserver, DatabasePort => $http_query_databaseport, DatabaseProtocol => $http_query_databaseprotocol, DatabaseName => $http_query_databasename, DatabaseUsername => $http_query_databaseusername, DatabasePassword => $http_query_databasepassword, DatabaseTablePrefix => $http_query_databasetableprefix });
my $installscriptmessage = "";
if ($http_query_removeinstallscript eq "on"){
- if (unlink("install.cgi")){
+ if (unlink($installscriptname)){
$installscriptmessage = $kiriwrite_lang{$language_selected}{installscriptremoved};
print "<br /><br />\n";
print $installscriptmessage;
- }
+ }
print "<br /><br />\n";
print $kiriwrite_lang{$language_selected}{usekiriwritetext};
print "<br /><br />\n";
- print "<a href=\"kiriwrite.cgi\">$kiriwrite_lang{$language_selected}{usekiriwritelink}</a>";
+ print "<a href=\"" . $kiriwritescriptname . "\">$kiriwrite_lang{$language_selected}{usekiriwritelink}</a>";
print "</body>\n</html>";
exit;
# Check to see if the needed Perl modules are installed.
-$test_list{CheckConfigAuto}{Name} = "Config::Auto";
-$test_list{CheckConfigAuto}{Type} = "dependency";
-$test_list{CheckConfigAuto}{Code} = "Config::Auto";
-
$test_list{CheckDBI}{Name} = "DBI";
$test_list{CheckDBI}{Type} = "dependency";
$test_list{CheckDBI}{Code} = "DBI";
-$test_list{CheckTieHash}{Name} = "Tie::IxHash";
-$test_list{CheckTieHash}{Type} = "dependency";
-$test_list{CheckTieHash}{Code} = "Tie::IxHash";
-
$test_list{CheckCGILite}{Name} = "CGI::Lite";
$test_list{CheckCGILite}{Type} = "dependency";
$test_list{CheckCGILite}{Code} = "CGI::Lite";
$test_list{Encode}{Type} = "dependency";
$test_list{Encode}{Code} = "Encode";
+$test_list{HashSearch}{Name} = "Hash::Search";
+$test_list{HashSearch}{Type} = "dependency";
+$test_list{HashSearch}{Code} = "Hash::Search";
+
+$test_list{CheckTieHash}{Name} = "Tie::IxHash";
+$test_list{CheckTieHash}{Type} = "dependency";
+$test_list{CheckTieHash}{Code} = "Tie::IxHash";
+
$test_list{DBDmysql}{Name} = "DBD::mysql";
$test_list{DBDmysql}{Type} = "database";
$test_list{DBDmysql}{Code} = "DBD::mysql";
$test_list{LanguageDirectory}{Code} = "lang";
$test_list{LanguageDirectory}{Writeable} = "0";
-$test_list{LibraryDirectory}{Name} = "Library Directory (lib)";
-$test_list{LibraryDirectory}{Type} = "file";
-$test_list{LibraryDirectory}{Code} = "lib";
-$test_list{LibraryDirectory}{Writeable} = "0";
-
$test_list{ModulesDirectory}{Name} = "Modules Directory (Modules)";
$test_list{ModulesDirectory}{Type} = "file";
$test_list{ModulesDirectory}{Code} = "Modules";
$test_list{PresModulesDirectory}{Code} = "Modules/Presentation";
$test_list{PresModulesDirectory}{Writeable} = "0";
+$test_list{SystemModulesDirectory}{Name} = "System Modules Directory (Modules/System)";
+$test_list{SystemModulesDirectory}{Type} = "file";
+$test_list{SystemModulesDirectory}{Code} = "Modules/System";
+$test_list{SystemModulesDirectory}{Writeable} = "0";
+
# Preform those tests.
foreach $test (keys %test_list){
$installlanguage_out = $installlanguage_out . "</select>\n";
-kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{installertitle}, "languagebar", "<form action=\"install.cgi\" method=\"POST\">\n$installlanguage_out\n<input type=\"submit\" value=\"$kiriwrite_lang{$language_selected}{switch}\">\n</form>\n", "languagebarselect");
+kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{installertitle}, "languagebar", "<form action=\"" . $installscriptname . "\" method=\"POST\">\n$installlanguage_out\n<input type=\"submit\" value=\"$kiriwrite_lang{$language_selected}{switch}\">\n</form>\n", "languagebarselect");
print "</table>";
print "<h2>$kiriwrite_lang{$language_selected}{installertitle}</h2>\n";
print $kiriwrite_lang{$language_selected}{installertext};
+
+if ($modperlenabled eq 1){
+ print "<br /><br />";
+ print $kiriwrite_lang{$language_selected}{modperlnotice};
+}
+
print "<h3>$kiriwrite_lang{$language_selected}{dependencytitle}</h3>\n";
print "<h4>$kiriwrite_lang{$language_selected}{requiredmodules}</h4>\n";
print $kiriwrite_lang{$language_selected}{perlmodules};
print $kiriwrite_lang{$language_selected}{databasemodulestext};
print "<br /><br />\n";
+print "<table>\n";
+
if ($database_error eq 1){
print $kiriwrite_lang{$language_selected}{warningmessage};
print "<table>";
-kiriwrite_addtablerow("Filename", "tablecellheader", "Result", "tablecellheader");
+kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{filename}, "tablecellheader", "Result", "tablecellheader");
foreach $test (keys %file_results) {
my @language_short;
my (%available_languages, $available_languages);
my @presentation_modules;
+my @output_modules;
my @database_modules;
my $select_data = "";
-my $language_data;
+my (%language_data, $language_data);
+my @lang_data;
+my $kiriwrite_languagefilehandle;
my $language_out = "";
my ($presmodule_name, $presmodule_out) = "";
my ($dbmodule_name, $dbmodule_out) = "";
+my ($outputmodule_name, $outputmodule_out) = "";
# Get the list of available languages.
# Load the language file.
- $language_data = Config::Auto::parse("lang/" . $language_file, format => "ini");
-
- # Load the XML data.
- #$language_xml_data = $xsl->XMLin("lang/" . $language_file);
+ open ($kiriwrite_languagefilehandle, "lang/" . $language_file);
+ @lang_data = <$kiriwrite_languagefilehandle>;
+ %language_data = kiriwrite_processconfig(@lang_data);
+ close ($kiriwrite_languagefilehandle);
# Get the friendly name for the language file.
$language_file_friendly = $language_file;
$language_file_friendly =~ s/.lang$//g;
- $language_name = $language_data->{about}->{name};
+ $language_name = $language_data{about}{name};
$available_languages{$language_file_friendly} = $language_name . " (" . $language_file_friendly . ")";
}
+# Get the list of output modules.
+
+opendir(OUTPUTDIR, "Modules/Output");
+my @outputmodule_directory = grep /m*\.pm$/, readdir(OUTPUTDIR);
+closedir(OUTPUTDIR);
+
+foreach my $outputmodule_file (@outputmodule_directory){
+
+ # Get the friendly name for the database module.
+
+ $outputmodule_file =~ s/.pm$//g;
+ push(@output_modules, $outputmodule_file);
+
+}
+
# Get the list of database modules.
opendir(DATABASEDIR, "Modules/Database");
print $kiriwrite_lang{$language_selected}{settingstext};
print "<br /><br />\n";
-print "<form action=\"install.cgi\" method=\"POST\">";
+print "<form action=\"" . $installscriptname . "\" method=\"POST\">";
print "<input type=\"hidden\" name=\"confirm\" value=\"1\">\n<input type=\"hidden\" name=\"installlanguage\" value=\"$language_selected\">\n";
print "<table width=\"100%\">";
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{setting}, "tablecellheader", $kiriwrite_lang{$language_selected}{value}, "tablecellheader");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{directories}, "tablecellheader", "", "tablecellheader");
-kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{databasedirectory}, "tablname", "<input type=\"text\" name=\"dbdirectory\" size=\"32\" maxlength=\"64\" value=\"$default_dbdirectory\">", "tabledata");
+kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{databasedirectory}, "tablename", "<input type=\"text\" name=\"dbdirectory\" size=\"32\" maxlength=\"64\" value=\"$default_dbdirectory\">", "tabledata");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{outputdirectory}, "tablename", "<input type=\"text\" name=\"outputdirectory\" size=\"32\" maxlength=\"64\" value=\"$default_outputdirectory\">", "tabledata");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{imagesuripath}, "tablename", "<input type=\"text\" name=\"imagesuripath\" size=\"32\" maxlength=\"64\" value=\"$default_imagesuri\">", "tabledata");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{display}, "tablecellheader", "", "tablecellheader");
$select_data = $select_data . "<option value=\"$select_name\">" . $select_name . "</option>\n";
}
-kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{dateformat}, "tablename", "<select>$select_data</select>\n<input type=\"text\" size=\"32\" maxlength=\"64\" name=\"customdateformat\">", "tabledata");
+kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{dateformat}, "tablename", "<select name=\"dateformat\">$select_data</select>\n<input type=\"text\" size=\"32\" maxlength=\"64\" name=\"customdateformat\">", "tabledata");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{language}, "tablecellheader", "", "tablecellheader");
foreach my $language (keys %available_languages){
}
}
-kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{systemlanguage}, "tablename", $language_out, "tabledata");
+kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{systemlanguage}, "tablename", "<select name=\"language\">\r\n$language_out\r\n</select>", "tabledata");
+
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{modules}, "tablecellheader", "", "tablecellheader");
+
foreach $presmodule_name (@presentation_modules){
$presmodule_out = $presmodule_out . "<option value=\"$presmodule_name\">$presmodule_name</option>";
}
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{presentationmodule}, "tablename", "<select name=\"presmodule\">$presmodule_out</select>", "tabledata");
+
foreach $dbmodule_name (@database_modules){
$dbmodule_out = $dbmodule_out . "<option value=\"$dbmodule_name\">$dbmodule_name</option>";
}
-
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{databasemodule}, "tablename", "<select name=\"dbmodule\">$dbmodule_out</select>", "tabledata");
+
+foreach $outputmodule_name (@output_modules){
+ if ($default_outputmodule = $outputmodule_name){
+ $outputmodule_out = $outputmodule_out . "<option value=\"$outputmodule_name\" selected>$outputmodule_name</option>";
+ } else {
+ $outputmodule_out = $outputmodule_out . "<option value=\"$outputmodule_name\">$outputmodule_name</option>";
+ }
+}
+kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{outputmodule}, "tablename", "<select name=\"outputmodule\">$outputmodule_out</select>", "tabledata");
+
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{databaseserver}, "tablename", "<input type=\"text\" name=\"databaseserver\" size=\"32\" maxlength=\"128\" value=\"$default_server\">\n", "tabledata");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{databaseport}, "tablename", "<input type=\"text\" name=\"databaseport\" maxlength=\"5\" size=\"5\" value=\"$default_port\">\n", "tabledata");
kiriwrite_addtablerow($kiriwrite_lang{$language_selected}{databaseprotocol}, "tablename", "<select name=\"databaseprotocol\">\n<option value=\"tcp\">tcp</option>\n<option value=\"udp\">udp</option>\n</select>\n", "tabledata");