* Created service- and serviceInstance- specific constructors so that a single module can have distinct constructors depending on how it is invoked. These constructors are called serviceInit() and serviceInstanceInit(), and both chain to the existing init() constructor (so no change are required by this).

* Changed FileStrings so that it doesn't have to be updated every time the file string format changes. The format is now one line per piece of metadata, then a blank line, then the string data. If additional metadata is added later then this will automatically support it.
* Renamed the dataSource.strings service to dataSource.strings.customised, and renamed its get() method to getCustomisedString().
* Changed the semantics of dataSource.strings.customised so that it no longer looks for a default string if it can't find a customised one (and thus removed getDefaultString).
* Abstracted the Generic output module even more. It now consists of output.generic (a service instance with its own constructor) and dataSource.strings (a pure service), the latter of which is a wrapper around dataSource.strings.customised and dataSource.strings.defaults.
* Updated Coses to work with the new dataSource.strings insterface.
* Removed the test app DataSource::ConsoleStrings and DataSource::HTTPStrings files, since they were redundant with the default output files.
* Removed all the default strings in the CosesEditor and Login components since they are pretty pointless.
* Factored out the call to dump() in the GenericOutputs module.
* Changed setString in the MySQL string data source so that it will now add a blank string (it used to delete the string if it was blank, but that meant that it was not possible to customise strings away).
* Added a piece of metadata to strings: their version number.
* Updated the customised string data source stubs to mention the version data now stored with all strings
* Added a getAllStringVersions method to the customised strings data source which returns all the string names and their version numbers.
* Made the customised strings data source check the version number of every string in its database during setupInstall to make sure that they are all up to date, version-wise. If any are out of date, the user is notified.
* Added support for the new version column to the MySQL version of the customised string data source.
* Updated the increasingly misnamed CosesEditor to support the versioned strings stuff.
* Factored out some code in the CosesEditor.
* Added version information to all default strings. All default strings are now at version 1.
* Fixed a typo in a FileStrings dump statement.
* Fixed the calls to setProgress in the MySQL user and strings data sources and in the user field factory to use the correct syntax (a parsable dotted string instead of unlocalisable plain English).
* Updated the Generic output module's documentation to match what now happens.
This commit is contained in:
ian%hixie.ch 2001-11-22 15:46:42 +00:00
Родитель 61d6d30534
Коммит ee423a9430
24 изменённых файлов: 277 добавлений и 281 удалений

Просмотреть файл

@ -71,7 +71,7 @@ sub create {
} else {
$class->dump(10, "Called constructor of class $class, creating object...");
my $self = $class->bless(@_); # call our real constructor
$self->init(@_);
$self->serviceInit(@_);
return $self;
}
}
@ -85,12 +85,22 @@ sub serviceCreate {
}
$class->dump(10, "Called service constructor of class $class, creating object...");
my $self = $class->bless(@_); # call our real constructor
$self->init(@_);
$self->serviceInstanceInit(@_);
return $self;
}
sub init {} # stub for services
sub serviceInit {
my $self = shift;
$self->init(@_);
}
sub serviceInstanceInit {
my $self = shift;
$self->init(@_);
}
# provide a constructor that always constructs a new copy of the
# class. This is used by services that implement factories for objects
# implemented in the same class (e.g., session objects do this).

Просмотреть файл

@ -44,7 +44,7 @@ sub getDefaultString {
my($app, $protocol, $string) = @_;
# this is protocol agnostic stuff :-)
if ($string eq 'debug.dumpVars') {
return ('COSES', <<eof);
return ('COSES', '1', <<eof);
<!--
!
! This example will dump every single string passed into it. For

Просмотреть файл

@ -66,16 +66,24 @@ sub getDefaultString {
$self->assert(open(FILE, "<$filename"), 1, "Could not open output template file '$filename' for reading: $!");
# get the data type (platform's line delimiter)
local $/ = "\n";
my $type = <FILE>;
chomp($type);
my @data;
my $line;
while (defined($line = <FILE>)) {
chomp($line);
if ($line eq '') {
# stop this when we reach the first blank line
last;
}
push(@data, $line);
}
# and then slurp entire file (no record delimiter)
local $/ = undef;
my $data = <FILE>;
push(@data, <FILE>);
$self->assert(close(FILE), 3, "Could not close output template file '$filename': $!");
return ($type, $data);
return @data;
} else {
# file does not exist
$self->dump(9, "No file for string '$string' in protocol '$protocol' (looking for '$filename')4");
$self->dump(9, "No file for string '$string' in protocol '$protocol' (looking for '$filename')");
return; # no can do, sir
}
}

Просмотреть файл

@ -39,10 +39,13 @@ sub provides {
my $class = shift;
my($service) = @_;
# XXX this class should provide a 'clear caches' service (as should some others)
return ($service eq 'dataSource.strings' or
$service eq 'setup.install' or
return ($service eq 'dataSource.strings.customised' or
$service eq 'setup.events.start' or
$service eq 'setup.events.end' or
$service eq 'setup.install' or
$service eq 'dispatcher.output.generic' or
$service eq 'dispatcher.output' or
$service eq 'dataSource.strings.default' or
$class->SUPER::provides($service));
}
@ -58,8 +61,8 @@ sub databaseName {
return 'default';
}
# returns ($type, $string)
sub get {
# returns ($type, $version, $string)
sub getCustomisedString {
my $self = shift;
my($app, $session, $protocol, $string) = @_;
# error handling makes code ugly :-)
@ -86,19 +89,19 @@ sub get {
# XXX do we want to do an error here or something?
$self->warn(4, "While I was looking for the string '$string' in protocol '$protocol' using variant '$variant', I failed with: $@");
}
if (not scalar(@results)) {
$self->dump(9, "Did not find a string for '$string', going to look in the defaults...");
@results = $self->getDefaultString($app, $protocol, $string);
$self->assert(scalar(@results), 1, "Couldn't find a string to display for '$string' in protocol '$protocol'");
if (scalar(@results)) {
$self->stringsCache->{$variant}->{$string} = \@results;
return @results;
} else {
$self->dump(9, "Did not find a customised string for '$string' in protocol '$protocol'");
return;
}
$self->stringsCache->{$variant}->{$string} = \@results;
return @results;
} else {
return @{$self->stringsCache->{$variant}->{$string}};
}
} else {
$self->dump(9, "String datasource is disabled, going to use default for string '$string'.");
return $self->getDefaultString($app, $protocol, $string);
$self->dump(9, "String datasource is disabled, skipping");
return;
}
}
@ -168,6 +171,65 @@ sub setupEnding {
$self->enabled(1);
}
# setup.install
sub setupInstall {
my $self = shift;
my($app) = @_;
my $oldStrings = [];
# get all strings (variant id, variant name, variant protocol, string name, string version)
$app->output->setupProgress('strings.versionCheck');
my $strings = $self->getAllStringVersions($app); # arrayref of arrayrefs
foreach my $string (@$strings) {
# get version of default for $string->name in $string->protocol
my($variantID, $variantName, $variantProtocol, $stringName, $stringVersion) = @$string;
my($defaultStringType, $defaultStringVersion, $defaultStringData) = $app->getSelectingService('dataSource.strings.default')->getDefaultString($app, $variantProtocol, $stringName);
# if version < default string's version
if ($stringVersion < $defaultStringVersion) {
# XXX this is a numeric comparison because I am assuming
# that versions are simply integers. There is no reason
# this should actually be the case, so we may wish to
# implement a service for comparing versions and then use
# that here.
push(@$oldStrings, [@$string, $defaultStringVersion]);
}
}
if (scalar(@$oldStrings) > 0) {
# output array
$app->output->setupNewStringReport($oldStrings);
}
return;
}
# dispatcher.output.generic (used by the setupInstall method above
# assuming you are using a generic output system)
sub outputSetupNewStringReport {
my $self = shift;
my($app, $output, $oldStrings) = @_;
$output->output('setup.newStringReport', {
'oldStrings' => $oldStrings,
});
}
# dispatcher.output
sub strings {
return (
'setup.newStringsReport' => 'If some of the strings that are customised in this local installation have had their defaults changed, then this output will be triggered in addition to the various setup.progress calls and so on. It has one entry in the data hash. oldStrings, which is an array of arrays containing the variant id, the variant name, the variant protocol, the string name, the string version number, and the new version number of the default string. Details about exactly what changed should be found in the documentation.',
);
}
# dataSource.strings.default
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
if ($protocol eq 'stdout') {
if ($string eq 'setup.newStringsReport') {
return ('COSES', '1', '<text>Note: The following strings have had their defaults updated since you last customised them:<br/><set variable="string" value="(data.oldStrings)" source="values" order="lexical"><text value="string (string.3) in variant (string.1)"/> (<text value="protocol (string.2)"/>): yours=<text value="(string.4)"/>, new=<text value="(string.5)"/><br/></set></text>')
}
}
return; # nope, sorry
}
# XXX The next four SO have to change...
sub acceptType {
@ -201,13 +263,7 @@ sub getString {
my $self = shift;
# my($app, $variant, $string) = @_;
$self->notImplemented();
# return type, data
}
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
return $app->getSelectingServiceList('dataSource.strings.default')->getDefaultString($app, $protocol, $string);
# return type, version, data
}
sub getVariants {
@ -228,14 +284,14 @@ sub getVariantStrings {
my $self = shift;
# my($app, $variant) = @_;
$self->notImplemented();
# return ( string => [ type, data ] )*;
# return ( string => [ type, version, data ] )*;
}
sub getStringVariants {
my $self = shift;
# my($app, $string) = @_;
$self->notImplemented();
# return ( variant => [ type, data ] )*;
# return ( variant => [ type, version, data ] )*;
}
sub getDescribedVariants {
@ -245,6 +301,13 @@ sub getDescribedVariants {
# return { id => { name, protocol, quality, type, encoding, charset, language, description, translator } }*
}
sub getAllStringVersions {
my $self = shift;
# my($app) = @_;
$self->notImplemented();
# return ( variant id, variant name, variant protocol, string id, string name, string version )*
}
# an undefined $id means "add me please"
sub setVariant {
my $self = shift;
@ -254,12 +317,7 @@ sub setVariant {
sub setString {
my $self = shift;
# my($app, $variant, $string, $type, $data) = @_;
# my($app, $variant, $string, $type, $version, $data) = @_;
# if $data = '' then delete the relevant string from the database
$self->notImplemented();
}
sub setupInstall {
my $self = shift;
$self->notImplemented();
}

Просмотреть файл

@ -40,7 +40,7 @@ sub databaseType {
sub getString {
my $self = shift;
my($app, $variant, $string) = @_;
return $self->database($app)->execute('SELECT type, data FROM strings WHERE variant = ? AND name = ?', $variant, $string)->row;
return $self->database($app)->execute('SELECT type, version, data FROM strings WHERE variant = ? AND name = ?', $variant, $string)->row;
}
sub getVariants {
@ -79,7 +79,7 @@ sub getVariantStrings {
my $self = shift;
my($app, $variant) = @_;
my %result = ();
foreach my $string ($self->database($app)->execute('SELECT name, type, data FROM strings WHERE variant = ?', $variant)->rows) {
foreach my $string ($self->database($app)->execute('SELECT name, type, version, data FROM strings WHERE variant = ?', $variant)->rows) {
$result{$string->[0]} = [$string->[1], $string->[2]];
}
return %result;
@ -89,12 +89,18 @@ sub getStringVariants {
my $self = shift;
my($app, $string) = @_;
my %result = ();
foreach my $variant ($self->database($app)->execute('SELECT variant, type, data FROM strings WHERE name = ?', $string)->rows) {
foreach my $variant ($self->database($app)->execute('SELECT variant, type, version, data FROM strings WHERE name = ?', $string)->rows) {
$result{$variant->[0]} = [$variant->[1], $variant->[2]];
}
return %result;
}
sub getAllStringVersions {
my $self = shift;
my($app) = @_;
return $self->database($app)->execute('SELECT stringVariants.id, stringVariants.name, stringVariants.protocol, strings.name, strings.version FROM stringVariants, strings WHERE stringVariants.id = strings.variant')->rows;
}
sub setVariant {
my $self = shift;
my($app, $id, $name, $protocol, $quality, $type, $encoding, $charset, $language, $description, $translator) = @_;
@ -107,9 +113,9 @@ sub setVariant {
sub setString {
my $self = shift;
my($app, $variant, $string, $type, $data) = @_;
if ((defined($data)) and (length($data) > 0)) {
$self->database($app)->execute('REPLACE INTO stringVariants SET variant=?, string=?, type=?, data=?', $variant, $string, $type, $data);
my($app, $variant, $version, $string, $type, $data) = @_;
if (defined($data)) {
$self->database($app)->execute('REPLACE INTO stringVariants SET variant=?, string=?, type=?, version=?, data=?', $variant, $string, $type, $version, $data);
} else {
$self->database($app)->execute('DELETE FROM stringVariants WHERE variant = ? AND string = ?', $variant, $string);
}
@ -122,7 +128,7 @@ sub setupInstall {
$self->dump(9, 'about to configure string data source...');
if (not $helper->tableExists($app, $self->database($app), 'stringVariants')) {
$self->debug('going to create \'stringVariants\' table');
$app->output->setupProgress('strings data source (creating stringVariants database)');
$app->output->setupProgress('dataSource.strings.stringVariants');
$self->database($app)->execute('
CREATE TABLE stringVariants (
id integer unsigned auto_increment NOT NULL PRIMARY KEY,
@ -143,12 +149,13 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'strings')) {
$self->debug('going to create \'strings\' table');
$app->output->setupProgress('strings data source (creating strings database)');
$app->output->setupProgress('dataSource.strings.strings');
$self->database($app)->execute('
CREATE TABLE strings (
variant integer unsigned NOT NULL,
name varchar(32) NOT NULL,
type varchar(32) NOT NULL,
version varchar(32) NOT NULL,
data text,
PRIMARY KEY (variant, name)
)
@ -158,7 +165,10 @@ sub setupInstall {
if (not $helper->columnExists($app, $self->database($app), 'strings', 'type')) {
$self->database($app)->execute('ALTER TABLE strings ADD COLUMN type varchar(32) NOT NULL');
}
if (not $helper->columnExists($app, $self->database($app), 'strings', 'version')) {
$self->database($app)->execute('ALTER TABLE strings ADD COLUMN version varchar(32) NOT NULL');
}
}
$self->dump(9, 'done configuring string data source');
return;
return $self->SUPER::setupInstall(@_);
}

Просмотреть файл

@ -312,7 +312,7 @@ sub setupInstall {
$self->dump(9, 'about to configure user data source...');
if (not $helper->tableExists($app, $self->database($app), 'user')) {
$self->debug('going to create \'user\' table');
$app->output->setupProgress('user data source (creating user database)');
$app->output->setupProgress('dataSource.user.user');
$self->database($app)->execute('
CREATE TABLE user (
userID integer unsigned auto_increment NOT NULL PRIMARY KEY,
@ -340,7 +340,7 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'userData')) {
$self->debug('going to create \'userData\' table');
$app->output->setupProgress('user data source (creating userData database)');
$app->output->setupProgress('dataSource.user.userData');
$self->database($app)->execute('
CREATE TABLE userData (
userID integer unsigned NOT NULL,
@ -361,7 +361,7 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'userDataTypes')) {
$self->debug('going to create \'userDataTypes\' table');
$app->output->setupProgress('user data source (creating userDataTypes database)');
$app->output->setupProgress('dataSource.user.userDataTypes');
$self->database($app)->execute('
CREATE TABLE userDataTypes (
fieldID integer unsigned auto_increment NOT NULL PRIMARY KEY,
@ -390,7 +390,7 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'userGroupsMapping')) {
$self->debug('going to create \'userGroupsMapping\' table');
$app->output->setupProgress('user data source (creating userGroupsMapping database)');
$app->output->setupProgress('dataSource.user.userGroupsMapping');
$self->database($app)->execute('
CREATE TABLE userGroupsMapping (
userID integer unsigned NOT NULL,
@ -409,7 +409,7 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'groups')) {
$self->debug('going to create \'groups\' table');
$app->output->setupProgress('user data source (creating groups database)');
$app->output->setupProgress('dataSource.user.groups');
$self->database($app)->execute('
CREATE TABLE groups (
groupID integer unsigned auto_increment NOT NULL PRIMARY KEY,
@ -428,7 +428,7 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'groupRightsMapping')) {
$self->debug('going to create \'groupRightsMapping\' table');
$app->output->setupProgress('user data source (creating groupRightsMapping database)');
$app->output->setupProgress('dataSource.user.groupRightsMapping');
$self->database($app)->execute('
CREATE TABLE groupRightsMapping (
groupID integer unsigned NOT NULL,
@ -447,7 +447,7 @@ sub setupInstall {
}
if (not $helper->tableExists($app, $self->database($app), 'rights')) {
$self->debug('going to create \'rights\' table');
$app->output->setupProgress('user data source (creating rights database)');
$app->output->setupProgress('dataSource.user.rights');
$self->database($app)->execute('
CREATE TABLE rights (
rightID integer unsigned auto_increment NOT NULL PRIMARY KEY,

Просмотреть файл

@ -73,14 +73,16 @@ use PLIF::Output;
# database which looks up the name of the database, which is used to
# look up the list of variants and the specific string which should be
# used from those variants. If that fails, then the string data source
# will instead ask each of the default string data sources in turn for
# a suitable string.
# will just return a "nope, sorry, not me" response.
#
# If that happens, then the output method instead asks the default
# string datasources.
#
# The output method then calls for an appropriate string expander
# service, passes it the string and the data hash, and waits for
# another string in return.
#
# The string expander tytpically passes this string to an XML service
# The string expander typically passes this string to an XML service
# (which typically calls expat) to get it parsed and then handles it
# as appropriate to get some string output.
#
@ -96,11 +98,18 @@ use PLIF::Output;
# To find the list of strings required, do this:
# my %strings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
sub provides {
my $class = shift;
my($service) = @_;
return ($service eq 'dataSource.strings' or
$class->SUPER::provides($service));
}
sub protocol {
return 'generic';
}
sub init {
sub serviceInstanceInit {
my $self = shift;
$self->SUPER::init(@_);
my($app, $session, $protocol) = @_;
@ -109,6 +118,7 @@ sub init {
$self->propertySet('outputter', $self->app->getService('output.generic.'.$self->actualProtocol));
}
# output.generic service instance method
sub output {
my $self = shift;
my($string, $data, $session) = @_;
@ -116,21 +126,11 @@ sub output {
$session = $self->actualSession;
}
$self->fillData($data);
$self->outputter->output($self->app, $session, $self->getString($session, $string, $data));
}
sub getString {
my $self = shift;
my($session, $name, $data) = @_;
my($type, $string) = $self->app->getService('dataSource.strings')->get($self->app, $session, $self->actualProtocol, $name);
my $expander = $self->app->getService("string.expander.named.$name");
if (not defined($expander)) {
$expander = $self->app->getService("string.expander.$type");
$self->assert($expander, 1, "Could not find a string expander for string '$name' of type '$type'");
}
return $expander->expand($self->app, $self, $session, $self->actualProtocol, $string, $data);
$self->outputter->output($self->app, $session,
$self->app->getService('dataSource.strings')->getExpandedString($self->app, $session, $self->actualProtocol, $string, $data));
}
# output.generic service instance method
# If we don't implement the output handler directly, let's see if some
# specific output dispatcher service for this protocol does.
# Note: We pass ourselves as the 'output object for this protocol'
@ -145,6 +145,7 @@ sub methodMissing {
}
}
# output.generic service instance method
sub fillData {
my $self = shift;
my($data) = @_;
@ -155,3 +156,28 @@ sub fillData {
$data->{'input'} = $self->app->input->hash;
$data->{'output'} = $self->outputter->hash;
}
# dataSource.strings default implementation
sub getExpandedString {
my $self = shift;
my($app, $session, $protocol, $name, $data) = @_;
my($type, $version, $string) = $self->getString($app, $session, $protocol, $name);
my $expander = $app->getService("string.expander.named.$name");
if (not defined($expander)) {
$expander = $app->getService("string.expander.$type");
$self->assert($expander, 1, "Could not find a string expander for string '$name' of type '$type'");
}
return $expander->expand($app, $self, $session, $protocol, $string, $data);
}
# dataSource.strings default implementation
sub getString {
my $self = shift;
my($app, $session, $protocol, $name) = @_;
my @string = $app->getSelectingServiceList('dataSource.strings.customised')->getCustomisedString($app, $session, $protocol, $name);
if (not scalar(@string)) {
@string = $app->getSelectingServiceList('dataSource.strings.default')->getDefaultString($app, $protocol, $name);
$self->assert(scalar(@string), 1, "No suitable '$name' string available for the '$protocol' protocol");
}
return @string;
}

Просмотреть файл

@ -137,9 +137,9 @@ sub getDefaultString {
my($app, $protocol, $string) = @_;
if ($protocol eq 'stdout') {
if ($string eq 'setup') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses"><if lvalue="(data.failed)" condition="=" rvalue="1">Failed with:<br/><text value="(data.result)"/></if><else>Succeeded!</else><br/></text>');
return ('COSES', '1', '<text xmlns="http://bugzilla.mozilla.org/coses"><if lvalue="(data.failed)" condition="=" rvalue="1">Can\'t continue: argument <text value="(data.result)"/> is missing.</if><else>Succeeded!</else><br/></text>');
} elsif ($string eq 'setup.progress') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">Setup: configuring <text value="(data.component)"/>...<br/></text>');
return ('COSES', '1', '<text xmlns="http://bugzilla.mozilla.org/coses">Setup: configuring <text value="(data.component)"/>...<br/></text>');
}
}
return; # nope, sorry

Просмотреть файл

@ -44,7 +44,6 @@ sub provides {
$service eq 'dispatcher.commands' or
$service eq 'dispatcher.output.generic' or
$service eq 'dispatcher.output' or
$service eq 'dataSource.strings.default' or
$service eq 'setup.install' or
$class->SUPER::provides($service));
}
@ -56,15 +55,15 @@ sub cmdCosesEditor {
my($app) = @_;
my $user = $app->getService('user.login')->hasRight($app, 'cosesEditor');
if (defined($user)) {
my %variants = $app->getService('dataSource.strings')->getDescribedVariants();
my $variants = $self->getDescribedVariants($app);
my $variantsSortColumn = $app->input->getArgument('cosesEditorVariantsSortColumn');
my %strings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
my $strings = $self->getExpectedStrings($app);
my $stringsSortColumn = $app->input->getArgument('cosesEditorStringsSortColumn');
# if (defined($user)) {
$user->setting(\$variantsSortColumn, 'cosesEditor.index.variantsSortColumn');
$user->setting(\$stringsSortColumn, 'cosesEditor.index.stringsSortColumn');
# }
$app->output->cosesEditorIndex(\%variants, $variantsSortColumn, \%strings, $stringsSortColumn);
$app->output->cosesEditorIndex($variants, $variantsSortColumn, $strings, $stringsSortColumn);
} # else, user has been notified
}
@ -74,10 +73,11 @@ sub cmdCosesVariantAdd {
my($app) = @_;
my $user = $app->getService('user.login')->hasRight($app, 'cosesEditor');
if (defined($user)) {
my @data = ('', '', 1.0, '', '', '', '', '', '');
my $protocol = $app->input->getArgument('cosesEditorVariantProtocol');
my @data = ('', $protocol, 1.0, '', '', '', '', '', '');
my $id = $app->getService('dataSource.strings')->setVariant($app, undef, @data);
my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
$app->output->cosesEditorVariant($id, @data, \%expectedStrings, {});
my $expectedStrings = $self->getExpectedStrings($app, $protocol);
$app->output->cosesEditorVariant($id, @data, $expectedStrings, {});
} # else, user has been notified
}
@ -90,9 +90,9 @@ sub cmdCosesVariantEdit {
my $id = $app->input->getArgument('cosesEditorVariantID');
my $dataSource = $app->getService('dataSource.strings');
my @data = $dataSource->getVariant($app, $id);
my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
my %variantStrings = $dataSource->getVariantStrings($app, $id);
$app->output->cosesEditorVariant($id, @data, \%expectedStrings, \%variantStrings);
my $expectedStrings = $self->getExpectedStrings($app, $data[1]);
my $variantStrings = \$dataSource->getVariantStrings($app, $id);
$app->output->cosesEditorVariant($id, @data, $expectedStrings, $variantStrings);
} # else, user has been notified
}
@ -102,9 +102,9 @@ sub cmdCosesVariantAddString {
my($app) = @_;
my $user = $app->getService('user.login')->hasRight($app, 'cosesEditor');
if (defined($user)) {
my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
my($id, $data, $variantStrings) = $self->getVariantEditorArguments($app);
$app->output->cosesEditorVariant($id, @$data, \%expectedStrings, $variantStrings);
my $expectedStrings = $self->getExpectedStrings($app, $data->[1]);
$app->output->cosesEditorVariant($id, @$data, $expectedStrings, $variantStrings);
} # else, user has been notified
}
@ -131,11 +131,10 @@ sub cmdCosesStringEdit {
my $user = $app->getService('user.login')->hasRight($app, 'cosesEditor');
if (defined($user)) {
my $id = $app->input->getArgument('cosesEditorStringID');
my %strings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
my $dataSource = $app->getService('dataSource.strings');
my %expectedVariants = $dataSource->getDescribedVariants();
my %stringVariants = $dataSource->getStringVariants($app, $id);
$app->output->cosesEditorString($id, $strings{$id}, \%expectedVariants, \%stringVariants);
my $strings = $self->getExpectedStrings($app);
my $expectedVariants = $self->getDescribedVariants($app, $id);
my $stringVariants = \$app->getService('dataSource.strings')->getStringVariants($app, $id);
$app->output->cosesEditorString($id, $strings->{$id}, $expectedVariants, $stringVariants);
} # else, user has been notified
}
@ -147,10 +146,11 @@ sub cmdCosesStringCommit {
if (defined($user)) {
my $input = $app->input;
my $id = $input->getArgument('cosesEditorStringID');
my %variants = ();
my %variants;
my $index = 0;
while (defined(my $name = $input->getArgument('cosesEditorStringVariant${index}Name'))) {
$variants{$name} = [$input->getArgument('cosesEditorStringVariant${index}Type'),
$variants{$name} = [$input->getArgument('cosesEditorStringVariant${index}Type'),
$input->getArgument('cosesEditorStringVariant${index}Version'),
$input->getArgument('cosesEditorStringVariant${index}Value')];
$index += 1;
}
@ -186,8 +186,9 @@ sub cmdCosesVariantExport {
foreach my $string (keys(%strings)) {
my $name = $XML->escape($string);
my $type = $XML->escape($strings{$string}->[0]);
my $value = $XML->escape($strings{$string}->[1]);
$result.= " <string name=\"$name\" type=\"$type\">$value</string>\n";
my $version = $XML->escape($strings{$string}->[1]);
my $value = $XML->escape($strings{$string}->[2]);
$result.= " <string name=\"$name\" type=\"$type\" version=\"$version\">$value</string>\n";
}
$result .= '</variant>';
$app->output->cosesEditorExport($id, $result);
@ -207,8 +208,9 @@ sub cmdCosesVariantImport {
my $XML = $app->getService('service.xml');
my $data = {
'depth' => 0,
'string' => undef,
'name' => undef,
'type' => undef,
'version' => undef,
'variant' => [], # same at all scopes (because walkNesting() is not a deep copy)
'strings' => {}, # same at all scopes (because walkNesting() is not a deep copy)
};
@ -222,7 +224,7 @@ sub cmdCosesVariantImport {
}
# display data
my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
my %expectedStrings = $self->getExpectedStrings($app);
my %variantStrings = $dataSource->getVariantStrings($app, $id);
$app->output->cosesEditorVariant($id, @{$data->{'variant'}}, \%expectedStrings, \%variantStrings);
} # else, user has been notified
@ -246,11 +248,12 @@ sub walkElement {
}
} elsif ($tagName eq '{http://bugzilla.mozilla.org/variant/1}string') {
if ($data->{'depth'} == 1) {
if (exists($attributes->{'name'})) {
$data->{'string'} = $attributes->{'name'};
$data->{'type'} = $attributes->{'type'};
} else {
$self->error(1, 'invalid variant document format - missing attribute \'name\' on <string>');
foreach my $name (qw(name type version)) {
if (exists($attributes->{$name})) {
$data->{$name} = $attributes->{$name};
} else {
$self->error(1, "invalid variant document format - missing attribute '$name' on <string>");
}
}
} else {
$self->error(1, 'invalid variant document format - <string> not child of <variant>');
@ -266,7 +269,7 @@ sub walkText {
my $self = shift;
my($text, $data) = @_;
if (defined($data->{'string'})) {
$data->{'strings'}->{$data->{'string'}} = [$data->{'type'}, $text];
$data->{'strings'}->{$data->{'name'}} = [$data->{'type'}, $data->{'version'}, $text];
} elsif ($text !~ /^\w*$/o) {
$self->error(1, "invalid variant document format - unexpected text");
}
@ -337,41 +340,13 @@ sub outputCosesEditorExport {
# dispatcher.output
sub strings {
return (
'cosesEditor.index' => 'The COSES editor index. The data.variants hash (variant ID => hash with keys name, protocol, quality, type, encoding, charset, language, description, and translator) should be sorted by the data.variantsSortColumn, and the data.strings hash (name=>description) should be sorted by the data.stringsSortColumn (these are typically set by the cosesEditorVariantsSortColumn and cosesEditorStringsSortColumn arguments). Typical commands that this should lead to: cosesVariantAdd (no arguments), cosesVariantEdit (cosesEditorVariantID), cosesStringEdit (cosesEditorStringID), cosesVariantExport (cosesEditorVariantID), cosesVariantImport (cosesEditorImportData, the contents of an XML file)',
'cosesEditor.variant' => 'The COSES variant editor. The data hash contains: protocol, quality, type, encoding, charset, language, description and translator (hereon "the variant data"), variant, an expectedStrings hash (name=>description), and a variantStrings hash (name=>[type,value]). The two hashes are likely to overlap. Typical commands that this should lead to: cosesVariantCommit and cosesVariantAddString (cosesEditorVariantID, cosesEditorVariantX where X is each of the variant data, cosesEditorVariantStringNName, cosesEditorVariantStringNType and cosesEditorVariantStringNValue where N is a number from 0 to as high as required, and cosesEditorStringNewName, cosesEditorStringNewType and cosesEditorVariantStringNewValue)',
'cosesEditor.string' => 'The COSES string editor. The name of the string being edited and its description are in data.string and data.description. The data.expectedVariants contains a list of all variants (variant ID => hash with keys name, protocol, quality, type, encoding, charset, language, description, and translator), and data.stringVariants hosts the currently set strings (variant=>value). The main command that this should lead to is: cosesStringCommit (cosesEditorStringID, cosesEditorStringVariantNName, cosesEditorStringVariantNType and cosesEditorStringVariantNValue where N is a number from 0 to as high as required)',
'cosesEditor.index' => 'The COSES editor index. The data.variants hash (variant ID => hash with keys name, protocol, quality, type, encoding, charset, language, description, and translator) should be sorted by the data.variantsSortColumn, and the data.strings hash (name=>description) should be sorted by the data.stringsSortColumn (these are typically set by the cosesEditorVariantsSortColumn and cosesEditorStringsSortColumn arguments). Typical commands that this should lead to: cosesVariantAdd (optional cosesEditorVariantProtocol), cosesVariantEdit (cosesEditorVariantID), cosesStringEdit (cosesEditorStringID), cosesVariantExport (cosesEditorVariantID), cosesVariantImport (cosesEditorImportData, the contents of an XML file)',
'cosesEditor.variant' => 'The COSES variant editor. The data hash contains: protocol, quality, type, encoding, charset, language, description and translator (hereon "the variant data"), variant, an expectedStrings hash (name=>description), and a variantStrings hash (name=>[type,version,value]). The two hashes are likely to overlap. Typical commands that this should lead to: cosesVariantCommit and cosesVariantAddString (cosesEditorVariantID, cosesEditorVariantX where X is each of the variant data, cosesEditorVariantStringNName, cosesEditorVariantStringNType, cosesEditorVariantStringNVersion, and cosesEditorVariantStringNValue where N is a number from 0 to as high as required, and cosesEditorStringNewName, cosesEditorStringNewType, cosesEditorStringNewVersion and cosesEditorVariantStringNewValue)',
'cosesEditor.string' => 'The COSES string editor. The name of the string being edited and its description are in data.string and data.description. The data.expectedVariants contains a list of all variants (variant ID => hash with keys name, protocol, quality, type, encoding, charset, language, description, and translator), and data.stringVariants hosts the currently set strings (variant=>value). The main command that this should lead to is: cosesStringCommit (cosesEditorStringID, cosesEditorStringVariantNName, cosesEditorStringVariantNType, cosesEditorStringVariantNVersion and cosesEditorStringVariantNValue where N is a number from 0 to as high as required)',
'cosesEditor.export' => 'The COSES variant export feature. data.variant holds the id of the variant, and data.output holds the XML representation of the variant.',
);
}
# dataSource.strings.default
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
if ($protocol eq 'stdout') {
if ($string eq 'cosesEditor.index') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">COSES Editor<br/></text>');
} elsif ($string eq 'cosesEditor.variant') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">COSES Editor<br/>Variant Editor<br/></text>');
} elsif ($string eq 'cosesEditor.string') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">COSES Editor<br/>String Editor<br/></text>');
} elsif ($string eq 'cosesEditor.export') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses"><text variable="(data.output)"/><br/></text>');
}
} elsif ($protocol eq 'http') {
if ($string eq 'cosesEditor.index') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/plain<br/><br/>COSES Editor: Index</text>');
} elsif ($string eq 'cosesEditor.variant') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/plain<br/><br/>COSES Editor: Variant Editor</text>');
} elsif ($string eq 'cosesEditor.string') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/plain<br/><br/>COSES Editor: String Editor</text>');
} elsif ($string eq 'cosesEditor.export') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/xml<br/><br/><text variable="(data.output)"/></text>');
}
}
return; # nope, sorry
}
# setup.install
# XXX at least part of this could also be implemented as a user field
# factory registerer hook -- does this matter?
@ -405,13 +380,44 @@ sub getVariantEditorArguments {
my $index = 0;
while (defined(my $name = $input->getArgument('cosesEditorVariantString${index}Name'))) {
$variantStrings{$name} = [$input->getArgument('cosesEditorVariantString${index}Type'),
$input->getArgument('cosesEditorVariantString${index}Version'),
$input->getArgument('cosesEditorVariantString${index}Value')];
$index += 1;
}
my $newName = $input->getArgument('cosesEditorVariantStringNewName');
if ((defined($newName)) and ($newName ne '')) {
$variantStrings{$newName} = [$input->getArgument('cosesEditorVariantStringNewType'),
$input->getArgument('cosesEditorVariantStringNewVersion'),
$input->getArgument('cosesEditorVariantStringNewValue')];
}
return ($id, \@data, \%variantStrings);
}
sub getExpectedStrings {
my $self = shift;
my($app, $protocol) = @_;
my $strings = $app->getCollectingServiceList('dispatcher.output')->strings();
if (defined($protocol)) {
my $defaults = $app->getSelectingService('dataSource.strings.default');
foreach my $string (keys(%$strings)) {
$strings->{$string} = {
'description' => $strings->{$string},
'default' => $defaults->getDefaultString($app, $protocol, $string),
};
}
}
return $strings;
}
sub getDescribedVariants {
my $self = shift;
my($app, $string) = @_;
my $variants = \$app->getService('dataSource.strings')->getDescribedVariants($app);
if (defined($string)) {
my $defaults = $app->getSelectingService('dataSource.strings.default');
foreach my $variant (keys(%$variants)) {
push(@{$variants->{$variant}}, $defaults->getDefaultString($app, $variants->{$variant}->[1], $string));
}
}
return $variants;
}

Просмотреть файл

@ -43,7 +43,6 @@ sub provides {
$service eq 'dispatcher.commands' or
$service eq 'dispatcher.output.generic' or
$service eq 'dispatcher.output' or
$service eq 'dataSource.strings.default' or
$class->SUPER::provides($service));
}
@ -195,30 +194,6 @@ sub strings {
);
}
# dataSource.strings.default
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
if ($protocol eq 'stdout') {
if ($string eq 'login.accessDenied') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">Access Denied<br/></text>');
} elsif ($string eq 'login.failed') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses"><if lvalue="(data.tried)" condition="!=" rvalue="0">Wrong username or password.</if><else>You must give your username or password.</else><br/><!-- XXX offer to create an account or send the password --><br/></text>');
} elsif ($string eq 'login.detailsSent') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">Login details were sent. (Protocol: <text value="(data.protocol)"/>; Address: <text value="(data.address)"/>)<br/></text>');
}
} elsif ($protocol eq 'http') {
if ($string eq 'login.accessDenied') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 401 Access Denied<br/>Content-Type: text/plain<br/><br/>Access Denied</text>');
} elsif ($string eq 'login.failed') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 401 Login Required<br/>WWW-Authenticate: Basic realm="<text value="(data.app.name)"/>"<br/>Content-Type: text/plain<br/><br/><if lvalue="(data.tried)" condition="!=" rvalue="0">Wrong username or password.</if><else>You must give your username or password.</else><br/><!-- XXX offer to create an account or send the password --></text>');
} elsif ($string eq 'login.detailsSent') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/plain<br/><br/>Login details were sent.<br/>Protocol: <text value="(data.protocol)"/><br/>Address: <text value="(data.address)"/></text>');
}
}
return; # nope, sorry
}
# internal routines

Просмотреть файл

@ -170,17 +170,18 @@ sub expand {
push(@index, $index);
push(@stack, $stack);
$index = 0;
$stack = $xmlService->parseNS($self->getString($app, $session, $protocol,
$self->evaluateExpression($attributes->{'href'}, $scope)));
my($type, $version, $string) = $app->getService('dataSource.strings')->getString($app, $session, $protocol, $self->evaluateExpression($attributes->{'href'}, $scope));
$self->assert($type eq 'COSES', 1, 'Tried to include a non-COSES string as COSES data. Set the \'parse\' attribute to \'text\' or \'x-auto\' to handle this correctly.');
$stack = $xmlService->parseNS($string);
push(@scope, $superscope);
} elsif ($attributes->{'parse'} eq 'text') {
# raw text inclusion
$result .= $self->escape($app, $self->getString($app, $session, $protocol,
$self->evaluateExpression($attributes->{'href'}, $scope)), $scope);
my($type, $version, $string) = $app->getService('dataSource.strings')->getString($app, $session, $protocol, $self->evaluateExpression($attributes->{'href'}, $scope));
$result .= $self->escape($app, $string, $scope);
} elsif ($attributes->{'parse'} eq 'x-auto') {
# Get the string expanded automatically and
# insert it into the result.
$result .= $self->escape($app, $output->getString($session, $self->evaluateExpression($attributes->{'href'}, $scope), $scope), $scope);
$result .= $self->escape($app, $app->getService('dataSource.strings')->getExpandedString($app, $session, $protocol, $self->evaluateExpression($attributes->{'href'}, $scope), $scope), $scope);
}
next node; # skip default handling
} elsif ($node eq '{http://bugzilla.mozilla.org/coses}else') {
@ -283,13 +284,6 @@ sub expand {
}
}
sub getString {
my $self = shift;
my($app, $session, $protocol, $name) = @_;
my($type, $string) = $app->getService('dataSource.strings')->get($app, $session, $protocol, $name);
return $string;
}
sub evaluateVariable {
my $self = shift;
my($variable, $scope) = @_;

Просмотреть файл

@ -75,17 +75,18 @@ sub strings {
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
if ($string eq 'error') {
$self->dump(9, 'Looks like an error occured, because the string \'error\' is being requested');
}
if ($protocol eq 'stdout') {
if ($string eq 'request') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">\'<text value="(data.argument)"/>\'<if lvalue="(data.defaults.length)" condition=">" rvalue="0"> (default: \'<set variable="default" value="(data.defaults)" source="keys" order="default"><text value="(data.defaults.(default))"/><if lvalue="(default)" condition="!=" rvalue="0">\', \'</if></set>\')</if>? </text>');
return ('COSES', '1', '<text xmlns="http://bugzilla.mozilla.org/coses">\'<text value="(data.argument)"/>\'<if lvalue="(data.defaults.length)" condition=">" rvalue="0"> (default: \'<set variable="default" value="(data.defaults)" source="keys" order="default"><text value="(data.defaults.(default))"/><if lvalue="(default)" condition="!=" rvalue="0">\', \'</if></set>\')</if>? </text>');
} elsif ($string eq 'error') {
$self->dump(9, 'Looks like an error occured, because the string \'error\' is being requested');
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">Error:<br/><text value="(data.error)"/><br/></text>');
return ('COSES', '1', '<text xmlns="http://bugzilla.mozilla.org/coses">Error:<br/><text value="(data.error)"/><br/></text>');
}
} elsif ($protocol eq 'http') {
if ($string eq 'error') {
$self->dump(9, 'Looks like an error occured, because the string \'error\' is being requested');
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 500 Internal Error<br/>Content-Type: text/plain<br/><br/>Error:<br/><text value="(data.error)"/></text>');
return ('COSES', '1', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 500 Internal Error<br/>Content-Type: text/plain<br/><br/>Error:<br/><text value="(data.error)"/></text>');
}
}
return; # nope, sorry

Просмотреть файл

@ -130,7 +130,7 @@ sub removeField {
sub setupInstall {
my $self = shift;
my($app) = @_;
$app->output->setupProgress('user fields');
$app->output->setupProgress('user.fieldFactory');
$app->getCollectingServiceList('user.fieldRegisterer')->register($app, $self);
return;
}

Просмотреть файл

@ -1,53 +0,0 @@
# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
#
# This file is MPL/GPL dual-licensed under the following terms:
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and
# limitations under the License.
#
# The Original Code is PLIF 1.0.
# The Initial Developer of the Original Code is Ian Hickson.
#
# Alternatively, the contents of this file may be used under the terms
# of the GNU General Public License Version 2 or later (the "GPL"), in
# which case the provisions of the GPL are applicable instead of those
# above. If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the MPL, indicate your decision by
# deleting the provisions above and replace them with the notice and
# other provisions required by the GPL. If you do not delete the
# provisions above, a recipient may use your version of this file
# under either the MPL or the GPL.
package DataSource::ConsoleStrings;
use strict;
use vars qw(@ISA);
use PLIF::DataSource;
@ISA = qw(PLIF::DataSource);
1;
sub provides {
my $class = shift;
my($service) = @_;
return ($service eq 'dataSource.strings.default' or $class->SUPER::provides($service));
}
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
if ($protocol ne 'stdout') {
return; # ``we don't do duvets!!!''
}
if ($string eq 'hello') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">Hello <if lvalue="(data.session)" condition="ne" rvalue="">user #<text value="(data.session.userID)"/></if><else>World</else>!<br/></text>');
} else {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">Er. <include href="debug.dumpVars"/></text>');
}
}

Просмотреть файл

@ -1,53 +0,0 @@
# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
#
# This file is MPL/GPL dual-licensed under the following terms:
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and
# limitations under the License.
#
# The Original Code is PLIF 1.0.
# The Initial Developer of the Original Code is Ian Hickson.
#
# Alternatively, the contents of this file may be used under the terms
# of the GNU General Public License Version 2 or later (the "GPL"), in
# which case the provisions of the GPL are applicable instead of those
# above. If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the MPL, indicate your decision by
# deleting the provisions above and replace them with the notice and
# other provisions required by the GPL. If you do not delete the
# provisions above, a recipient may use your version of this file
# under either the MPL or the GPL.
package DataSource::HTTPStrings;
use strict;
use vars qw(@ISA);
use PLIF::DataSource;
@ISA = qw(PLIF::DataSource);
1;
sub provides {
my $class = shift;
my($service) = @_;
return ($service eq 'dataSource.strings.default' or $class->SUPER::provides($service));
}
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
if ($protocol ne 'http') {
return; # ``we don't do CDs!!!''
}
if ($string eq 'hello') {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/plain<br/><br/>Hello <if lvalue="(data.session)" condition="ne" rvalue="">user #<text value="(data.session.userID)"/></if><else>World</else>!<br/><br/>visit nph-Main?command=Login to log in if you haven\'t already.<br/>At the moment to create a username and password, you have to ask Hixie to edit the database... :-/ (use open/sesame to test)<br/><br/><include href="debug.dumpVars"/><br/><br/><shrink source="(data.input.arguments)" target="shrunken"><include href="debug.dumpVars"/><br/><br/><expand source="(shrunken)" target="expanded"><include href="debug.dumpVars"/></expand></shrink><br/><br/><text escape="uri">Welcome To The URI World</text><br/><text escape="html">Welcome To The &lt;HTML&gt; World</text><br/><text escape="html"><text escape="uri"><text escape="xml">Welcome To &gt; The HTML+URI+XML+foo World</text></text></text></text>');
} else {
return ('COSES', '<text xmlns="http://bugzilla.mozilla.org/coses">HTTP/1.1 200 OK<br/>Content-Type: text/plain<br/><br/>Er. <include href="debug.dumpVars"/></text>');
}
}

Просмотреть файл

@ -67,8 +67,6 @@ sub registerServices {
PLIF::Service::ContactMethod::AIM
Output
Configuration
DataSource::ConsoleStrings
DataSource::HTTPStrings
));
}

Просмотреть файл

@ -1,2 +1,4 @@
COSES
1
<text xmlns="http://bugzilla.mozilla.org/coses" value="Hey there. Your password is '(data.password)', and you can login just by giving AIM screen name as your username. Seeya!"/>

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<text>

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<set variable="title" value="Hello World">

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<set variable="title" value="Access Denied">

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<set variable="title" value="Details Sent">

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<set variable="title" value="Login">

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<!-- - - - - - - -+

Просмотреть файл

@ -1,4 +1,6 @@
COSES
1
<text xml:space="default" xmlns="http://bugzilla.mozilla.org/coses">
<!-- - - - - - - -+