View | Details | Raw Unified | Return to bug 6874
Collapse All | Expand All

(-)a/C4/UploadedFiles.pm (-28 / +44 lines)
Lines 57-68 use Fcntl; Link Here
57
use Encode;
57
use Encode;
58
58
59
use C4::Context;
59
use C4::Context;
60
use C4::Koha;
60
61
61
sub _get_file_path {
62
sub _get_file_path {
62
    my ($id, $dirname, $filename) = @_;
63
    my ($hash, $dirname, $filename) = @_;
63
64
64
    my $upload_path = C4::Context->config('upload_path');
65
    my $upload_path = C4::Context->config('upload_path');
65
    my $filepath = "$upload_path/$dirname/${id}_$filename";
66
    if( !-d "$upload_path/$dirname" ) {
67
        mkdir "$upload_path/$dirname";
68
    }
69
    my $filepath = "$upload_path/$dirname/${hash}_$filename";
66
    $filepath =~ s|/+|/|g;
70
    $filepath =~ s|/+|/|g;
67
71
68
    return $filepath;
72
    return $filepath;
Lines 90-110 It returns undef if file is not found Link Here
90
=cut
94
=cut
91
95
92
sub GetUploadedFile {
96
sub GetUploadedFile {
93
    my ($id) = @_;
97
    my ( $hashvalue ) = @_;
94
98
95
    return unless $id;
99
    return unless $hashvalue;
96
100
97
    my $dbh = C4::Context->dbh;
101
    my $dbh = C4::Context->dbh;
98
    my $query = qq{
102
    my $query = qq{
99
        SELECT id, filename, dir
103
        SELECT hashvalue, filename, dir
100
        FROM uploaded_files
104
        FROM uploaded_files
101
        WHERE id = ?
105
        WHERE hashvalue = ?
102
    };
106
    };
103
    my $sth = $dbh->prepare($query);
107
    my $sth = $dbh->prepare($query);
104
    $sth->execute($id);
108
    $sth->execute( $hashvalue );
105
    my $file = $sth->fetchrow_hashref;
109
    my $file = $sth->fetchrow_hashref;
106
    if ($file) {
110
    if ($file) {
107
        $file->{filepath} = _get_file_path($file->{id}, $file->{dir},
111
        $file->{filepath} = _get_file_path($file->{hashvalue}, $file->{dir},
108
            $file->{filename});
112
            $file->{filename});
109
    }
113
    }
110
114
Lines 134-140 $cgi->upload('uploaded_file')->handle; Link Here
134
138
135
sub UploadFile {
139
sub UploadFile {
136
    my ($filename, $dir, $handle) = @_;
140
    my ($filename, $dir, $handle) = @_;
137
138
    $filename = decode_utf8($filename);
141
    $filename = decode_utf8($filename);
139
    if($filename =~ m#(^|/)\.\.(/|$)# or $dir =~ m#(^|/)\.\.(/|$)#) {
142
    if($filename =~ m#(^|/)\.\.(/|$)# or $dir =~ m#(^|/)\.\.(/|$)#) {
140
        warn "Filename or dirname contains '..'. Aborting upload";
143
        warn "Filename or dirname contains '..'. Aborting upload";
Lines 152-166 sub UploadFile { Link Here
152
    $sha->add($data);
155
    $sha->add($data);
153
    $sha->add($filename);
156
    $sha->add($filename);
154
    $sha->add($dir);
157
    $sha->add($dir);
155
    my $id = $sha->hexdigest;
158
    my $hash = $sha->hexdigest;
156
159
157
    # Test if this id already exist
160
    # Test if this id already exist
158
    my $file = GetUploadedFile($id);
161
    my $file = GetUploadedFile($hash);
159
    if ($file) {
162
    if ($file) {
160
        return $file->{id};
163
        return $file->{hashvalue};
161
    }
164
    }
162
165
163
    my $file_path = _get_file_path($id, $dir, $filename);
166
    my $file_path = _get_file_path($hash, $dir, $filename);
164
167
165
    my $out_fh;
168
    my $out_fh;
166
    # Create the file only if it doesn't exist
169
    # Create the file only if it doesn't exist
Lines 170-185 sub UploadFile { Link Here
170
    }
173
    }
171
174
172
    print $out_fh $data;
175
    print $out_fh $data;
176
    my $size= tell($out_fh);
173
    close $out_fh;
177
    close $out_fh;
174
178
175
    my $dbh = C4::Context->dbh;
179
    my $dbh = C4::Context->dbh;
176
    my $query = qq{
180
    my $query = qq{
177
        INSERT INTO uploaded_files (id, filename, dir)
181
        INSERT INTO uploaded_files (hashvalue, filename, filesize, dir, categorycode, owner) VALUES (?,?,?,?,?,?);
178
        VALUES (?,?, ?);
179
    };
182
    };
180
    my $sth = $dbh->prepare($query);
183
    my $sth = $dbh->prepare($query);
181
    if($sth->execute($id, $filename, $dir)) {
184
    my $uid= C4::Context->userenv? C4::Context->userenv->{number}: undef;
182
        return $id;
185
        # uid is null in unit test
186
    if($sth->execute($hash, $filename, $size, $dir, $dir, $uid)) {
187
        return $hash;
183
    }
188
    }
184
189
185
    return;
190
    return;
Lines 192-198 sub UploadFile { Link Here
192
Determine if a entry is dangling.
197
Determine if a entry is dangling.
193
198
194
Returns: 2 == no db entry
199
Returns: 2 == no db entry
195
         1 == no file
200
         1 == no plain file
196
         0 == both a file and db entry.
201
         0 == both a file and db entry.
197
        -1 == N/A (undef id / non-file-upload URL)
202
        -1 == N/A (undef id / non-file-upload URL)
198
203
Lines 230-238 sub DanglingEntry { Link Here
230
235
231
=head2 DelUploadedFile
236
=head2 DelUploadedFile
232
237
233
    C4::UploadedFiles::DelUploadedFile($id);
238
    C4::UploadedFiles::DelUploadedFile( $hash );
234
239
235
Remove a previously uploaded file, given its id.
240
Remove a previously uploaded file, given its hash value.
236
241
237
Returns: 1 == file deleted
242
Returns: 1 == file deleted
238
         0 == file not deleted
243
         0 == file not deleted
Lines 241-256 Returns: 1 == file deleted Link Here
241
=cut
246
=cut
242
247
243
sub DelUploadedFile {
248
sub DelUploadedFile {
244
    my ($id) = @_;
249
    my ( $hashval ) = @_;
245
    my $retval;
250
    my $retval;
246
251
247
    if ($id) {
252
    if ( $hashval ) {
248
        my $file = GetUploadedFile($id);
253
        my $file = GetUploadedFile( $hashval );
249
        if($file) {
254
        if($file) {
250
            my $file_path = $file->{filepath};
255
            my $file_path = $file->{filepath};
251
            my $file_deleted = 0;
256
            my $file_deleted = 0;
252
            unless( -f $file_path ) {
257
            unless( -f $file_path ) {
253
                warn "Id $file->{id} is in database but not in filesystem, removing id from database";
258
                warn "Id $file->{hashvalue} is in database but no plain file found, removing id from database";
254
                $file_deleted = 1;
259
                $file_deleted = 1;
255
            } else {
260
            } else {
256
                if(unlink $file_path) {
261
                if(unlink $file_path) {
Lines 265-274 sub DelUploadedFile { Link Here
265
            my $dbh = C4::Context->dbh;
270
            my $dbh = C4::Context->dbh;
266
            my $query = qq{
271
            my $query = qq{
267
                DELETE FROM uploaded_files
272
                DELETE FROM uploaded_files
268
                WHERE id = ?
273
                WHERE hashvalue = ?
269
            };
274
            };
270
            my $sth = $dbh->prepare($query);
275
            my $sth = $dbh->prepare($query);
271
            my $numrows = $sth->execute($id);
276
            my $numrows = $sth->execute( $hashval );
272
            # if either a DB entry or file was deleted,
277
            # if either a DB entry or file was deleted,
273
            # then clearly we have a deletion.
278
            # then clearly we have a deletion.
274
            if ($numrows>0 || $file_deleted==1) {
279
            if ($numrows>0 || $file_deleted==1) {
Lines 279-295 sub DelUploadedFile { Link Here
279
            }
284
            }
280
        }
285
        }
281
        else {
286
        else {
282
            warn "There was no file for id=($id)";
287
            warn "There was no file for hash $hashval.";
283
            $retval = -1;
288
            $retval = -1;
284
        }
289
        }
285
    }
290
    }
286
    else {
291
    else {
287
        warn "DelUploadFile called with no id.";
292
        warn "DelUploadFile called without hash value.";
288
        $retval = -1;
293
        $retval = -1;
289
    }
294
    }
290
    return $retval;
295
    return $retval;
291
}
296
}
292
297
298
=head2 getCategories
299
300
    getCategories returns a list of upload category codes and names
301
302
=cut
303
304
sub getCategories {
305
    my $cats = C4::Koha::GetAuthorisedValues('UPLOAD');
306
    [ map {{ code => $_->{authorised_value}, name => $_->{lib} }} @$cats ];
307
}
308
293
=head2 httpheaders
309
=head2 httpheaders
294
310
295
    httpheaders returns http headers for a retrievable upload
311
    httpheaders returns http headers for a retrievable upload
(-)a/cataloguing/value_builder/upload.pl (-68 / +21 lines)
Lines 1-5 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
2
3
# Converted to new plugin style (Bug 6874/See also 13437)
4
3
# This file is part of Koha.
5
# This file is part of Koha.
4
#
6
#
5
# Copyright (C) 2011-2012 BibLibre
7
# Copyright (C) 2011-2012 BibLibre
Lines 19-50 Link Here
19
21
20
use Modern::Perl;
22
use Modern::Perl;
21
use CGI qw/-utf8/;
23
use CGI qw/-utf8/;
22
use File::Basename;
23
24
24
use C4::Auth;
25
use C4::Auth;
25
use C4::Context;
26
use C4::Context;
26
use C4::Output;
27
use C4::Output;
27
use C4::UploadedFiles;
28
use C4::UploadedFiles;
28
29
29
sub plugin_parameters {
30
my $builder = sub {
30
    my ( $dbh, $record, $tagslib, $i, $tabloop ) = @_;
31
    my ( $params ) = @_;
31
    return "";
32
    my $function_name = $params->{id};
32
}
33
34
sub plugin_javascript {
35
    my ( $dbh, $record, $tagslib, $field_number, $tabloop ) = @_;
36
    my $function_name = $field_number;
37
    my $res           = "
33
    my $res           = "
38
    <script type=\"text/javascript\">
34
    <script type=\"text/javascript\">
39
        function Focus$function_name(subfield_managed) {
35
        function Click$function_name(event) {
40
            return 1;
36
            var index = event.data.id;
41
        }
42
43
        function Blur$function_name(subfield_managed) {
44
            return 1;
45
        }
46
47
        function Clic$function_name(index) {
48
            var id = document.getElementById(index).value;
37
            var id = document.getElementById(index).value;
49
            var IsFileUploadUrl=0;
38
            var IsFileUploadUrl=0;
50
            if (id.match(/opac-retrieve-file/)) {
39
            if (id.match(/opac-retrieve-file/)) {
Lines 55-70 sub plugin_javascript { Link Here
55
            }
44
            }
56
            var newin=window.open(\"../cataloguing/plugin_launcher.pl?plugin_name=upload.pl&index=\"+index+\"&id=\"+id+\"&from_popup=0\"+\"&IsFileUploadUrl=\"+IsFileUploadUrl, 'upload', 'width=600,height=400,toolbar=false,scrollbars=no');
45
            var newin=window.open(\"../cataloguing/plugin_launcher.pl?plugin_name=upload.pl&index=\"+index+\"&id=\"+id+\"&from_popup=0\"+\"&IsFileUploadUrl=\"+IsFileUploadUrl, 'upload', 'width=600,height=400,toolbar=false,scrollbars=no');
57
            newin.focus();
46
            newin.focus();
58
59
        }
47
        }
60
    </script>
48
    </script>
61
";
49
";
50
    return $res;
51
};
62
52
63
    return ( $function_name, $res );
53
my $launcher = sub {
64
}
54
    my ( $params ) = @_;
65
55
    my $input = $params->{cgi};
66
sub plugin {
67
    my ($input) = @_;
68
    my $index = $input->param('index');
56
    my $index = $input->param('index');
69
    my $id = $input->param('id');
57
    my $id = $input->param('id');
70
    my $delete = $input->param('delete');
58
    my $delete = $input->param('delete');
Lines 95-101 sub plugin { Link Here
95
    }
83
    }
96
84
97
    # Dealing with the uploaded file
85
    # Dealing with the uploaded file
98
    my $dir = $input->param('dir');
86
    my $dir = $input->param('uploadcategory');
99
    if ($uploaded_file and $dir) {
87
    if ($uploaded_file and $dir) {
100
        my $fh = $input->upload('uploaded_file');
88
        my $fh = $input->upload('uploaded_file');
101
89
Lines 132-147 sub plugin { Link Here
132
                -name => 'uploaded_file',
120
                -name => 'uploaded_file',
133
                -size => 50,
121
                -size => 50,
134
            );
122
            );
135
136
            my $dirs_tree = [ {
137
                name => '/',
138
                value => '/',
139
                dirs => finddirs($upload_path)
140
            } ];
141
142
            $template->param(
123
            $template->param(
143
                dirs_tree => $dirs_tree,
124
                filefield => $filefield,
144
                filefield => $filefield
125
                uploadcategories => C4::UploadedFiles::getCategories(),
145
            );
126
            );
146
        } else {
127
        } else {
147
            $template->param( error_upload_path_not_configured => 1 );
128
            $template->param( error_upload_path_not_configured => 1 );
Lines 165-211 sub plugin { Link Here
165
    );
146
    );
166
147
167
    output_html_with_http_headers $input, $cookie, $template->output;
148
    output_html_with_http_headers $input, $cookie, $template->output;
168
}
149
};
169
170
# Build a hierarchy of directories
171
sub finddirs {
172
    my $base = shift;
173
    my $upload_path = C4::Context->config('upload_path');
174
    my $found = 0;
175
    my @dirs;
176
    my @files = glob("$base/*");
177
    foreach (@files) {
178
        if (-d $_ and -w $_) {
179
            my $lastdirname = basename($_);
180
            my $dirname =  $_;
181
            $dirname =~ s/^$upload_path//g;
182
            push @dirs, {
183
                value => $dirname,
184
                name => $lastdirname,
185
                dirs => finddirs($_)
186
            };
187
            $found = 1;
188
        };
189
    }
190
    return \@dirs;
191
}
192
150
193
1;
151
return { builder => $builder, launcher => $launcher };
194
152
153
1;
195
154
196
__END__
155
__END__
197
156
198
=head1 upload.pl
157
=head1 upload.pl
199
158
200
This plugin allow to upload files on the server and reference it in a marc
159
This plugin allows to upload files on the server and reference it in a marc
201
field.
160
field.
202
161
203
Two system preference are used:
162
It uses config variable upload_path and pref OPACBaseURL.
204
205
=over 4
206
207
=item * upload_path: the real absolute path where files will be stored
208
209
=item * OPACBaseURL: for building URLs to be stored in MARC
210
163
211
=back
164
=cut
(-)a/installer/data/mysql/atomicupdate/06874_lastrevision.sql (+11 lines)
Line 0 Link Here
1
-- table adjustments for uploaded_files
2
ALTER TABLE uploaded_files
3
    CHANGE COLUMN id hashvalue char(40) NOT NULL,
4
    DROP PRIMARY KEY;
5
ALTER TABLE uploaded_files
6
    ADD COLUMN id int NOT NULL AUTO_INCREMENT FIRST,
7
    ADD CONSTRAINT PRIMARY KEY (id),
8
    ADD COLUMN filesize int,
9
    ADD COLUMN dtcreated timestamp,
10
    ADD COLUMN categorycode tinytext,
11
    ADD COLUMN owner int;
(-)a/installer/data/mysql/kohastructure.sql (-2 / +8 lines)
Lines 3366-3374 CREATE TABLE IF NOT EXISTS `borrower_modifications` ( Link Here
3366
3366
3367
DROP TABLE IF EXISTS uploaded_files;
3367
DROP TABLE IF EXISTS uploaded_files;
3368
CREATE TABLE uploaded_files (
3368
CREATE TABLE uploaded_files (
3369
    id CHAR(40) NOT NULL PRIMARY KEY,
3369
    id int(11) NOT NULL AUTO_INCREMENT,
3370
    hashvalue CHAR(40) NOT NULL,
3370
    filename TEXT NOT NULL,
3371
    filename TEXT NOT NULL,
3371
    dir TEXT NOT NULL
3372
    dir TEXT NOT NULL,
3373
    filesize int(11),
3374
    dtcreated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
3375
    categorycode tinytext,
3376
    owner int(11),
3377
    PRIMARY KEY (id)
3372
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3378
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3373
3379
3374
--
3380
--
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/upload.tt (-53 / +34 lines)
Lines 7-42 Link Here
7
    <script type="text/javascript" src="[% interface %]/lib/jquery/jquery.js"></script>
7
    <script type="text/javascript" src="[% interface %]/lib/jquery/jquery.js"></script>
8
    <link rel="stylesheet" type="text/css" href="[% themelang %]/css/staff-global.css" />
8
    <link rel="stylesheet" type="text/css" href="[% themelang %]/css/staff-global.css" />
9
    <script type="text/javascript">
9
    <script type="text/javascript">
10
      function ValidateForm() {
10
        function ValidateForm() {
11
        var filename = document.forms["UploadForm"]["uploaded_file"].value;
11
            var filename = document.forms["UploadForm"]["uploaded_file"].value;
12
        var selected = 0;
12
            if (!filename) {
13
        var value;
13
                alert("Please select a file to upload.");
14
        $('form').each(function() {
14
                return false;
15
          value = $(this).find('input[type="radio"][name="dir"]:checked').val();
15
            }
16
          if (value) {
16
            return true;
17
            selected = 1;
18
          }
19
        });
20
        if (!filename && !selected) {
21
          alert("Please select a file and its destination.");
22
          return false;
23
        }
24
        else if (!filename) {
25
          alert("Please select a file to upload.");
26
          return false;
27
        }
28
        else if (!selected) {
29
          alert("Please select a file destination.");
30
          return false;
31
        }
17
        }
32
        else {
33
          return true;
34
        }
35
      }
36
    </script>
18
    </script>
37
19
38
</head>
20
</head>
39
<body>
21
<body>
22
23
<div id="doc3" class="yui-t2"><div id="bd"><div id="yui-main">
24
40
[% IF ( success ) %]
25
[% IF ( success ) %]
41
26
42
    <script type="text/javascript">
27
    <script type="text/javascript">
Lines 63-90 Link Here
63
        <p>Error: Failed to upload file. See logs for details.</p>
48
        <p>Error: Failed to upload file. See logs for details.</p>
64
        <p><input type="button" value="close" onclick="window.close();" /></p>
49
        <p><input type="button" value="close" onclick="window.close();" /></p>
65
    [% ELSE %]
50
    [% ELSE %]
66
        [%# This block display recursively a directory tree in variable 'dirs' %]
67
        [% BLOCK list_dirs %]
68
            [% IF dirs.size %]
69
                <ul>
70
                    [% FOREACH dir IN dirs %]
71
                        <li style="list-style-type:none">
72
                            <input type="radio" name="dir" id="[% dir.value %]" value="[% dir.value %]">
73
                                <label for="[% dir.value %]">
74
                                    [% IF (dir.name == '/') %]
75
                                        <em>(root)</em>
76
                                    [% ELSE %]
77
                                        [% dir.name %]
78
                                    [% END %]
79
                                </label>
80
                            </input>
81
                            [% INCLUDE list_dirs dirs=dir.dirs %]
82
                        </li>
83
                    [% END %]
84
                </ul>
85
            [% END %]
86
        [% END %]
87
88
        [% IF (error_upload_path_not_configured) %]
51
        [% IF (error_upload_path_not_configured) %]
89
          <h2>Configuration error</h2>
52
          <h2>Configuration error</h2>
90
          <p>Configuration variable 'upload_path' is not configured.</p>
53
          <p>Configuration variable 'upload_path' is not configured.</p>
Lines 102-122 Link Here
102
          [% IF (dangling) %]
65
          [% IF (dangling) %]
103
              <p class="error">Error: The URL has no file to retrieve.</p>
66
              <p class="error">Error: The URL has no file to retrieve.</p>
104
          [% END %]
67
          [% END %]
105
          <h2>Please select the file to upload : </h2>
68
69
          <h2>Please select the file to upload:</h2>
106
          <form name="UploadForm" method="post" enctype="multipart/form-data" action="/cgi-bin/koha/cataloguing/plugin_launcher.pl" onsubmit="return ValidateForm()">
70
          <form name="UploadForm" method="post" enctype="multipart/form-data" action="/cgi-bin/koha/cataloguing/plugin_launcher.pl" onsubmit="return ValidateForm()">
107
              [% filefield %]
108
              <h3>Choose where to upload the file</h3>
109
              [% INCLUDE list_dirs dirs = dirs_tree %]
110
              <input type="hidden" name="from_popup" value="1" />
71
              <input type="hidden" name="from_popup" value="1" />
111
              <input type="hidden" name="plugin_name" value="upload.pl" />
72
              <input type="hidden" name="plugin_name" value="upload.pl" />
112
              <input type="hidden" name="index" value="[% index %]" />
73
              <input type="hidden" name="index" value="[% index %]" />
113
              <input type="submit" value="Upload file">
74
114
              <input type="button" value="Cancel" onclick="window.close();" />
75
              <div>[% filefield %]</div>
76
              <p/>
77
              <div>
78
                  <label for="uploadcategory">Category: </label>
79
                  [% IF uploadcategories %]
80
                      <select id="uploadcategory" name="uploadcategory">
81
                      [% FOREACH cat IN uploadcategories %]
82
                          <option value="[% cat.code %]">[% cat.name %]</option>
83
                      [% END %]
84
                      </select>
85
                  [% ELSE %]
86
                      <input type="hidden" name="uploadcategory" value="CATALOGUING" />
87
                  [% END %]
88
              </div>
89
              <p/>
90
              <fieldset class="action">
91
                  <input type="submit" value="Upload">
92
                  <input type="button" value="Cancel" onclick="window.close();" />
93
              </fieldset>
115
          </form>
94
          </form>
116
        [% END %]
95
        [% END %]
117
    [% END %]
96
    [% END %]
118
97
119
[% END %]
98
[% END %]
120
99
100
</div></div></div>
101
121
</body>
102
</body>
122
</html>
103
</html>
(-)a/t/db_dependent/UploadedFiles.t (-3 / +2 lines)
Lines 30-36 ok($id, "File uploaded, id is $id"); Link Here
30
30
31
my $file = C4::UploadedFiles::GetUploadedFile($id);
31
my $file = C4::UploadedFiles::GetUploadedFile($id);
32
isa_ok($file, 'HASH', "GetUploadedFiles($id)");
32
isa_ok($file, 'HASH', "GetUploadedFiles($id)");
33
foreach my $key (qw(id filename filepath dir)) {
33
foreach my $key (qw(hashvalue filename filepath dir)) {
34
    ok(exists $file->{$key}, "GetUploadedFile($id)->{$key} exists");
34
    ok(exists $file->{$key}, "GetUploadedFile($id)->{$key} exists");
35
}
35
}
36
36
Lines 47-53 close $fh; Link Here
47
47
48
my $DelResult;
48
my $DelResult;
49
is(C4::UploadedFiles::DelUploadedFile($id),1, "DelUploadedFile($id) returned 1 as expected.");
49
is(C4::UploadedFiles::DelUploadedFile($id),1, "DelUploadedFile($id) returned 1 as expected.");
50
warning_like { $DelResult=C4::UploadedFiles::DelUploadedFile($id); } qr/file for id=/, "Expected warning for deleting Dangling Entry.";
50
warning_like { $DelResult=C4::UploadedFiles::DelUploadedFile($id); } qr/file for hash/, "Expected warning for deleting Dangling Entry.";
51
is($DelResult,-1, "DelUploadedFile($id) returned -1 as expected.");
51
is($DelResult,-1, "DelUploadedFile($id) returned -1 as expected.");
52
ok(! -e $file->{filepath}, "File $file->{filepath} does not exist anymore");
52
ok(! -e $file->{filepath}, "File $file->{filepath} does not exist anymore");
53
53
54
- 

Return to bug 6874