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

(-)a/C4/Auth.pm (+1 lines)
Lines 363-368 sub get_template_and_user { Link Here
363
            LocalCoverImages            => C4::Context->preference('LocalCoverImages'),
363
            LocalCoverImages            => C4::Context->preference('LocalCoverImages'),
364
            OPACLocalCoverImages        => C4::Context->preference('OPACLocalCoverImages'),
364
            OPACLocalCoverImages        => C4::Context->preference('OPACLocalCoverImages'),
365
            AllowMultipleCovers         => C4::Context->preference('AllowMultipleCovers'),
365
            AllowMultipleCovers         => C4::Context->preference('AllowMultipleCovers'),
366
            EnableBorrowerFiles         => C4::Context->preference('EnableBorrowerFiles'),
366
        );
367
        );
367
    }
368
    }
368
    else {
369
    else {
(-)a/Koha/Borrower/Files.pm (+155 lines)
Line 0 Link Here
1
package Koha::Borrower::Files;
2
3
# Copyright 2012 Kyle M Hall
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
23
24
use C4::Context;
25
use C4::Output;
26
use C4::Dates;
27
use C4::Debug;
28
29
BEGIN {
30
31
    # set the version for version checking
32
    $VERSION = 0.01;
33
    require Exporter;
34
    @ISA    = qw(Exporter);
35
    @EXPORT = qw(
36
37
    );
38
39
    my $debug = C4::Context->preference("DebugLevel");
40
}
41
42
=head1 NAME
43
44
Koha::Borrower::Files - Module for managing borrower files
45
46
=cut
47
48
sub new {
49
    my ( $class, %args ) = @_;
50
    my $self = bless( {}, $class );
51
52
    $self->{'borrowernumber'} = $args{'borrowernumber'};
53
54
    return $self;
55
}
56
57
=item GetFilesInfo()
58
59
    my $bf = Koha::Borrower::Files->new( borrowernumber => $borrowernumber );
60
    my $files_hashref = $bf->GetFilesInfo
61
62
=cut
63
64
sub GetFilesInfo {
65
    my $self = shift;
66
67
    my $dbh   = C4::Context->dbh;
68
    my $query = "
69
        SELECT
70
            file_id,
71
            file_name,
72
            file_type,
73
            file_description,
74
            date_uploaded
75
        FROM borrower_files
76
        WHERE borrowernumber = ?
77
        ORDER BY file_name, date_uploaded
78
    ";
79
    my $sth = $dbh->prepare($query);
80
    $sth->execute( $self->{'borrowernumber'} );
81
    return $sth->fetchall_arrayref( {} );
82
}
83
84
=item AddFile()
85
    my $bf = Koha::Borrower::Files->new( borrowernumber => $borrowernumber );
86
    $bh->AddFile( name => $filename, type => $mimetype, description => $description, content => $content );
87
=cut
88
89
sub AddFile {
90
    my ( $self, %args ) = @_;
91
92
    my $name        = $args{'name'};
93
    my $type        = $args{'type'};
94
    my $description = $args{'description'};
95
    my $content     = $args{'content'};
96
97
    return unless ( $name && $content );
98
99
    my $dbh   = C4::Context->dbh;
100
    my $query = "
101
        INSERT INTO borrower_files ( borrowernumber, file_name, file_type, file_description, file_content )
102
        VALUES ( ?,?,?,?,? )
103
    ";
104
    my $sth = $dbh->prepare($query);
105
    $sth->execute( $self->{'borrowernumber'},
106
        $name, $type, $description, $content );
107
}
108
109
=item GetFile()
110
    my $bf = Koha::Borrower::Files->new( borrowernumber => $borrowernumber );
111
    my $file = $bh->GetFile( file_id => $file_id );
112
=cut
113
114
sub GetFile {
115
    my ( $self, %args ) = @_;
116
117
    my $file_id = $args{'id'};
118
119
    my $dbh   = C4::Context->dbh;
120
    my $query = "
121
        SELECT * FROM borrower_files WHERE file_id = ? AND borrowernumber = ?
122
    ";
123
    my $sth = $dbh->prepare($query);
124
    $sth->execute( $file_id, $self->{'borrowernumber'} );
125
    return $sth->fetchrow_hashref();
126
}
127
128
=item DelFile()
129
    my $bf = Koha::Borrower::Files->new( borrowernumber => $borrowernumber );
130
    $bh->DelFile( file_id => $file_id );
131
=cut
132
133
sub DelFile {
134
    my ( $self, %args ) = @_;
135
136
    my $file_id = $args{'id'};
137
138
    my $dbh   = C4::Context->dbh;
139
    my $query = "
140
        DELETE FROM borrower_files WHERE file_id = ? AND borrowernumber = ?
141
    ";
142
    my $sth = $dbh->prepare($query);
143
    $sth->execute( $file_id, $self->{'borrowernumber'} );
144
}
145
146
1;
147
__END__
148
149
=back
150
151
=head1 AUTHOR
152
153
Kyle M Hall <kyle.m.hall@gmail.com>
154
155
=cut
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 365-367 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ( Link Here
365
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacBrowseResults','1','Disable/enable browsing and paging search results from the OPAC detail page.',NULL,'YesNo');
365
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacBrowseResults','1','Disable/enable browsing and paging search results from the OPAC detail page.',NULL,'YesNo');
366
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('SvcMaxReportRows','10','Maximum number of rows to return via the report web service.',NULL,'Integer');
366
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('SvcMaxReportRows','10','Maximum number of rows to return via the report web service.',NULL,'Integer');
367
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('ReservesControlBranch','PatronLibrary','ItemHomeLibrary|PatronLibrary','Branch checked for members reservations rights','Choice');
367
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('ReservesControlBranch','PatronLibrary','ItemHomeLibrary|PatronLibrary','Branch checked for members reservations rights','Choice');
368
INSERT INTO systempreferences (variable,value,explanation,type) VALUES('EnableBorrowerFiles','0','If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo');
(-)a/installer/data/mysql/updatedatabase.pl (+22 lines)
Lines 5307-5312 if (C4::Context->preference("Version") < TransformToNum($DBversion)) { Link Here
5307
    SetVersion ($DBversion);
5307
    SetVersion ($DBversion);
5308
}
5308
}
5309
5309
5310
$DBversion = "3.09.00.XXX";
5311
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
5312
    $dbh->do("INSERT INTO systempreferences (variable,value,explanation,type) VALUES('EnableBorrowerFiles','0','If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo')");
5313
    $dbh->do("
5314
CREATE TABLE IF NOT EXISTS borrower_files (
5315
  file_id int(11) NOT NULL AUTO_INCREMENT,
5316
  borrowernumber int(11) NOT NULL,
5317
  file_name varchar(255) NOT NULL,
5318
  file_type varchar(255) NOT NULL,
5319
  file_description varchar(255) DEFAULT NULL,
5320
  file_content longblob NOT NULL,
5321
  date_uploaded timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
5322
  PRIMARY KEY (file_id),
5323
  KEY borrowernumber (borrowernumber)
5324
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
5325
    ");
5326
    $dbh->do("ALTER TABLE borrower_files ADD CONSTRAINT borrower_files_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE");
5327
5328
    print "Upgrade to $DBversion done (Added borrow_files table, EnableBorrowerFiles syspref)\n";
5329
    SetVersion($DBversion);
5330
}
5331
5310
=head1 FUNCTIONS
5332
=head1 FUNCTIONS
5311
5333
5312
=head2 TableExists($table)
5334
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc (-9 / +7 lines)
Lines 63-79 Link Here
63
<div id="menu">
63
<div id="menu">
64
<ul>
64
<ul>
65
    [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li>
65
    [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li>
66
	[% IF ( CAN_user_borrowers ) %]
66
    [% IF ( CAN_user_borrowers ) %][% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>[% END %]
67
	[% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
67
    [% IF ( CAN_user_updatecharges ) %][% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>[% END %]
68
	[% END %]
69
	 [% IF ( CAN_user_updatecharges ) %]
70
	[% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>
71
	[% END %]
72
    [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li>[% END %]
68
    [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li>[% END %]
73
    [% IF ( CAN_user_parameters ) %][% IF ( logview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/tools/viewlog.pl?do_it=1&amp;modules=MEMBERS&amp;modules=circulation&amp;object=[% borrowernumber %]&amp;src=circ">Modification log</a></li>[% END %]
69
    [% IF ( CAN_user_parameters ) %][% IF ( logview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/tools/viewlog.pl?do_it=1&amp;modules=MEMBERS&amp;modules=circulation&amp;object=[% borrowernumber %]&amp;src=circ">Modification log</a></li>[% END %]
74
    [% IF ( EnhancedMessagingPreferences ) %]
70
    [% IF ( EnhancedMessagingPreferences ) %][% END %]
75
    [% END %]	
71
    [% IF ( sentnotices ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/notices.pl?borrowernumber=[% borrowernumber %]">Notices</a></li>
76
	[% IF ( sentnotices ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/notices.pl?borrowernumber=[% borrowernumber %]">Notices</a></li>
72
    [% IF EnableBorrowerFiles %]
73
        [% IF ( borrower_files ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/files.pl?borrowernumber=[% borrowernumber %]">Files</a></li>
74
    [% END %]
77
</ul></div>
75
</ul></div>
78
[% END %]
76
[% END %]
79
77
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/members-menu.inc (-9 / +9 lines)
Lines 1-14 Link Here
1
[% IF ( borrowernumber ) %]
1
[% IF ( borrowernumber ) %]
2
<div id="menu">
2
<div id="menu">
3
<ul>	[% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li>
3
  <ul>
4
	[% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
4
    [% IF ( circview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% borrowernumber %]">Check out</a></li>
5
	[% IF ( CAN_user_updatecharges ) %]
5
    [% IF ( detailview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Details</a></li>
6
	[% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>
6
    [% IF ( CAN_user_updatecharges ) %][% IF ( finesview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/boraccount.pl?borrowernumber=[% borrowernumber %]">Fines</a></li>[% END %]
7
	[% END %]
8
    [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li>[% END %]
7
    [% IF ( intranetreadinghistory ) %][% IF ( readingrecordview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/readingrec.pl?borrowernumber=[% borrowernumber %]">Circulation history</a></li>[% END %]
9
    [% IF ( CAN_user_parameters ) %][% IF ( logview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/tools/viewlog.pl?do_it=1&amp;modules=MEMBERS&amp;action=MODIFY&amp;object=[% borrowernumber %]">Modification log</a></li>[% END %]
8
    [% IF ( CAN_user_parameters ) %][% IF ( logview ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/tools/viewlog.pl?do_it=1&amp;modules=MEMBERS&amp;action=MODIFY&amp;object=[% borrowernumber %]">Modification log</a></li>[% END %]
10
    [% IF ( EnhancedMessagingPreferences ) %]
9
    [% IF ( EnhancedMessagingPreferences ) %][% END %]
11
    [% END %]
10
    [% IF ( sentnotices ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/notices.pl?borrowernumber=[% borrowernumber %]">Notices</a></li>
12
	[% IF ( sentnotices ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/notices.pl?borrowernumber=[% borrowernumber %]">Notices</a></li>
11
    [% IF EnableBorrowerFiles %] [% IF ( borrower_files ) %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/files.pl?borrowernumber=[% borrowernumber %]">Files</a></li> [% END %]
13
</ul></div>
12
  </ul>
13
</div>
14
[% END %]
14
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (+6 lines)
Lines 121-123 Patrons: Link Here
121
           choices:
121
           choices:
122
               now: current date.
122
               now: current date.
123
               dateexpiry: current membership expiry date.
123
               dateexpiry: current membership expiry date.
124
     -
125
         - pref: EnableBorrowerFiles
126
           choices:
127
               yes: Do
128
               no: "Don't"
129
         - enable the ability to upload and attach arbitrary files to a borrower record.
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/files.tt (+74 lines)
Line 0 Link Here
1
[% USE KohaDates %]
2
[% INCLUDE 'doc-head-open.inc' %]
3
<title>Files for [% INCLUDE 'patron-title.inc' %]</title>
4
[% INCLUDE 'doc-head-close.inc' %]
5
</head>
6
<body>
7
[% INCLUDE 'header.inc' %]
8
[% INCLUDE 'patron-search.inc' %]
9
10
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Files for [% INCLUDE 'patron-title.inc' %]</div>
11
12
<div id="doc3" class="yui-t2">
13
    <div id="bd">
14
        <div id="yui-main">
15
            <div class="yui-b">
16
                [% INCLUDE 'circ-toolbar.inc' %]
17
18
                <h1>Files</h1>
19
20
                <table>
21
                    <thead>
22
                        <th>Name</th>
23
                        <th>Type</th>
24
                        <th>Description</th>
25
                        <th>Uploaded</th>
26
                        [% IF CAN_user_borrowers_files_modify %]<th>&nbsp;</th>[% END %]
27
                    </thead>
28
29
                    <tbody>
30
                        [% IF errors %]
31
                            <div class="error warn">
32
                                [% IF errors.empty_upload %]The file you are attempting to upload has no contents.[% END %]
33
                                [% IF errors.no_file %]You did not select a file to upload.[% END %]
34
                            </div>
35
                        [% END %]
36
37
                        [% FOREACH f IN files %]
38
                            <tr>
39
                                 <td><a href="?borrowernumber=[% borrowernumber %]&op=download&file_id=[% f.file_id %]">[% f.file_name %]</a></td>
40
                                 <td>[% f.file_type %]</td>
41
                                 <td>[% f.file_description %]</td>
42
                                 <td>[% f.date_uploaded | $KohaDates %]</td>
43
                                 [% IF CAN_user_borrowers_files_modify %]<td><a href="?borrowernumber=[% borrowernumber %]&op=delete&file_id=[% f.file_id %]">Delete</a></td>[% END %]
44
                            </tr>
45
                        [% END %]
46
                    </tbody>
47
                </table>
48
49
                <form method="post" enctype="multipart/form-data">
50
                    <fieldset>
51
                        <legend>Upload New File</legend>
52
53
                        <input type="hidden" name="op" value="upload" />
54
                        <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
55
                        <input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
56
57
                        <label for="description">Description:</label>
58
                        <input name="description" type="text" />
59
60
                        <input name="uploadfile" type="file" id="uploadfile" />
61
62
                        <input name="upload" type="submit" id="upload" value="Upload File" />
63
                    </fieldset>
64
                </form>
65
66
            </div>
67
        </div>
68
69
        <div class="yui-b">
70
            [% INCLUDE 'circ-menu.inc' %]
71
        </div>
72
    </div>
73
</div>
74
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/members/files.pl (-1 / +115 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2012 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
use CGI;
24
25
use C4::Auth;
26
use C4::Output;
27
use C4::Members;
28
use C4::Debug;
29
30
use Koha::DateUtils;
31
use Koha::Borrower::Files;
32
33
my $cgi = CGI->new;
34
35
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
36
    {
37
        template_name   => "members/files.tmpl",
38
        query           => $cgi,
39
        type            => "intranet",
40
        authnotrequired => 0,
41
        flagsrequired   => { borrowers => 1 },
42
        debug           => 1,
43
    }
44
);
45
$template->param( 'borrower_files' => 1 );
46
47
my $borrowernumber = $cgi->param('borrowernumber');
48
my $bf = Koha::Borrower::Files->new( borrowernumber => $borrowernumber );
49
50
my $op = $cgi->param('op') || '';
51
52
if ( $op eq 'download' ) {
53
    my $file_id = $cgi->param('file_id');
54
    my $file = $bf->GetFile( id => $file_id );
55
56
    print $cgi->header(
57
        -type       => $file->{'file_type'},
58
        -charset    => 'utf-8',
59
        -attachment => $file->{'file_name'}
60
    );
61
    print $file->{'file_content'};
62
}
63
else {
64
    my $data = GetMember( borrowernumber => $borrowernumber );
65
    $template->param(%$data);
66
67
    my %errors;
68
69
    if ( $op eq 'upload' ) {
70
        my $uploaded_file = $cgi->upload('uploadfile');
71
72
        if ($uploaded_file) {
73
            my $filename = $cgi->param('uploadfile');
74
            my $mimetype = $cgi->uploadInfo($filename)->{'Content-Type'};
75
76
            $errors{'empty_upload'} = 1 unless ( length($uploaded_file) > 0 );
77
78
            if (%errors) {
79
                $template->param( errors => %errors );
80
            }
81
            else {
82
                my $file_content;
83
                while (<$uploaded_file>) {
84
                    $file_content .= $_;
85
                }
86
87
                $bf->AddFile(
88
                    name    => $filename,
89
                    type    => $mimetype,
90
                    content => $file_content,
91
                    description => $cgi->param('description'),
92
                );
93
            }
94
        }
95
        else {
96
            $errors{'no_file'} = 1;
97
        }
98
    } elsif ( $op eq 'delete' ) {
99
        $bf->DelFile( id => $cgi->param('file_id') );
100
    }
101
102
    $template->param(
103
        files => Koha::Borrower::Files->new( borrowernumber => $borrowernumber )
104
          ->GetFilesInfo(),
105
106
        errors => %errors
107
    );
108
    output_html_with_http_headers $cgi, $cookie, $template->output;
109
}
110
111
=head1 AUTHOR
112
113
Kyle M Hall <kyle@bywatersolutions.com>
114
115
=cut

Return to bug 8130