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