1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9package Kernel::System::VirtualFS::DB;
10
11use strict;
12use warnings;
13
14use MIME::Base64;
15
16our @ObjectDependencies = (
17    'Kernel::System::DB',
18    'Kernel::System::Encode',
19    'Kernel::System::Log',
20);
21
22sub new {
23    my ( $Type, %Param ) = @_;
24
25    # allocate new hash for object
26    my $Self = {};
27    bless( $Self, $Type );
28
29    # config (not used right now)
30    $Self->{Compress} = 0;
31    $Self->{Crypt}    = 0;
32
33    return $Self;
34}
35
36sub Read {
37    my ( $Self, %Param ) = @_;
38
39    # check needed stuff
40    for (qw(BackendKey Mode)) {
41        if ( !$Param{$_} ) {
42            $Kernel::OM->Get('Kernel::System::Log')->Log(
43                Priority => 'error',
44                Message  => "Need $_!"
45            );
46            return;
47        }
48    }
49
50    my $Attributes = $Self->_BackendKeyParse(%Param);
51
52    my $Encode = 1;
53    if ( lc $Param{Mode} eq 'binary' ) {
54        $Encode = 0;
55    }
56
57    # get database object
58    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
59
60    return if !$DBObject->Prepare(
61        SQL    => 'SELECT content FROM virtual_fs_db WHERE id = ?',
62        Bind   => [ \$Attributes->{FileID} ],
63        Encode => [$Encode],
64    );
65
66    # get encode object
67    my $EncodeObject = $Kernel::OM->Get('Kernel::System::Encode');
68
69    my $Content;
70    while ( my @Row = $DBObject->FetchrowArray() ) {
71
72        # decode attachment if it's e. g. a postgresql backend!!!
73        if ( !$DBObject->GetDatabaseFunction('DirectBlob') ) {
74            $Content = decode_base64( $Row[0] );
75            if ($Encode) {
76                $EncodeObject->EncodeInput( \$Content );
77            }
78        }
79        else {
80            $Content = $Row[0];
81        }
82    }
83
84    return if !$Content;
85
86    # uncompress (in case)
87    if ( $Attributes->{Compress} ) {
88
89        # $Content = ...
90    }
91
92    # decrypt (in case)
93    if ( $Attributes->{Crypt} ) {
94
95        # $Content = ...
96    }
97
98    return \$Content;
99}
100
101sub Write {
102    my ( $Self, %Param ) = @_;
103
104    # check needed stuff
105    for (qw(Content Filename Mode)) {
106        if ( !$Param{$_} ) {
107            $Kernel::OM->Get('Kernel::System::Log')->Log(
108                Priority => 'error',
109                Message  => "Need $_!"
110            );
111            return;
112        }
113    }
114
115    # check if already exists
116    my $Exists = $Self->_FileLookup( $Param{Filename} );
117    return if $Exists;
118
119    # compress (in case)
120    if ( $Self->{Compress} ) {
121
122        # $Param{Content} = ...
123    }
124
125    # crypt (in case)
126    if ( $Self->{Crypt} ) {
127
128        # $Param{Content} = ...
129    }
130
131    # get database object
132    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
133
134    # encode attachment if it's a postgresql backend!!!
135    if ( !$DBObject->GetDatabaseFunction('DirectBlob') ) {
136
137        $Kernel::OM->Get('Kernel::System::Encode')->EncodeOutput( $Param{Content} );
138
139        my $Content = encode_base64( ${ $Param{Content} } );
140        $Param{Content} = \$Content;
141    }
142
143    my $Encode = 1;
144    if ( lc $Param{Mode} eq 'binary' ) {
145        $Encode = 0;
146    }
147
148    return if !$DBObject->Do(
149        SQL => 'INSERT INTO virtual_fs_db (filename, content, create_time) '
150            . 'VALUES ( ?, ?, current_timestamp )',
151        Bind => [ \$Param{Filename}, $Param{Content} ],
152    );
153
154    my $FileID = $Self->_FileLookup( $Param{Filename} );
155    return if !$FileID;
156
157    my $BackendKey = $Self->_BackendKeyGenerate(
158        FileID   => $FileID,
159        Compress => $Self->{Compress},
160        Crypt    => $Self->{Crypt},
161        Mode     => $Param{Mode},
162    );
163
164    return $BackendKey;
165}
166
167sub Delete {
168    my ( $Self, %Param ) = @_;
169
170    # check needed stuff
171    for (qw(BackendKey)) {
172        if ( !$Param{$_} ) {
173            $Kernel::OM->Get('Kernel::System::Log')->Log(
174                Priority => 'error',
175                Message  => "Need $_!"
176            );
177            return;
178        }
179    }
180
181    my $Attributes = $Self->_BackendKeyParse(%Param);
182
183    return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
184        SQL  => 'DELETE FROM virtual_fs_db WHERE id = ?',
185        Bind => [ \$Attributes->{FileID} ],
186    );
187
188    return 1;
189}
190
191sub _FileLookup {
192    my ( $Self, $Filename ) = @_;
193
194    # get database object
195    my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
196
197    # lookup
198    return if !$DBObject->Prepare(
199        SQL  => 'SELECT id FROM virtual_fs_db WHERE filename = ?',
200        Bind => [ \$Filename ],
201    );
202
203    my $FileID;
204    while ( my @Row = $DBObject->FetchrowArray() ) {
205        $FileID = $Row[0];
206    }
207
208    return $FileID;
209}
210
211sub _BackendKeyGenerate {
212    my ( $Self, %Param ) = @_;
213
214    my $BackendKey = '';
215    for my $Key ( sort keys %Param ) {
216        $BackendKey .= "$Key=$Param{$Key};";
217    }
218    return $BackendKey;
219}
220
221sub _BackendKeyParse {
222    my ( $Self, %Param ) = @_;
223
224    # check needed stuff
225    for (qw(BackendKey)) {
226        if ( !$Param{$_} ) {
227            $Kernel::OM->Get('Kernel::System::Log')->Log(
228                Priority => 'error',
229                Message  => "Need $_!"
230            );
231            return;
232        }
233    }
234
235    my %Attributes;
236    my @Pairs = split /;/, $Param{BackendKey};
237    for my $Pair (@Pairs) {
238        my ( $Key, $Value ) = split /=/, $Pair;
239        $Attributes{$Key} = $Value;
240    }
241    return \%Attributes;
242}
243
2441;
245