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::Modules::AdminGenericInterfaceDebugger; 10 11use strict; 12use warnings; 13 14use utf8; 15 16use Kernel::System::VariableCheck qw(:all); 17use Kernel::Language qw(Translatable); 18 19our $ObjectManagerDisabled = 1; 20 21sub new { 22 my ( $Type, %Param ) = @_; 23 24 my $Self = {%Param}; 25 bless( $Self, $Type ); 26 27 return $Self; 28} 29 30sub Run { 31 my ( $Self, %Param ) = @_; 32 33 my $WebserviceID = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'WebserviceID' ); 34 35 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 36 37 if ( !$WebserviceID ) { 38 return $LayoutObject->ErrorScreen( 39 Message => Translatable('Need WebserviceID!'), 40 ); 41 } 42 43 my $WebserviceData = $Kernel::OM->Get('Kernel::System::GenericInterface::Webservice')->WebserviceGet( 44 ID => $WebserviceID, 45 ); 46 47 if ( !IsHashRefWithData($WebserviceData) ) { 48 return $LayoutObject->ErrorScreen( 49 Message => 50 $LayoutObject->{LanguageObject}->Translate( 'Could not get data for WebserviceID %s', $WebserviceID ), 51 ); 52 } 53 54 # Send value to JS. 55 $LayoutObject->AddJSData( 56 Key => 'WebserviceID', 57 Value => $WebserviceID, 58 ); 59 60 if ( $Self->{Subaction} eq 'GetRequestList' ) { 61 return $Self->_GetRequestList( 62 %Param, 63 WebserviceID => $WebserviceID, 64 WebserviceData => $WebserviceData, 65 ); 66 } 67 elsif ( $Self->{Subaction} eq 'GetCommunicationDetails' ) { 68 return $Self->_GetCommunicationDetails( 69 %Param, 70 WebserviceID => $WebserviceID, 71 WebserviceData => $WebserviceData, 72 ); 73 } 74 elsif ( $Self->{Subaction} eq 'ClearDebugLog' ) { 75 return $Self->_ClearDebugLog( 76 %Param, 77 WebserviceID => $WebserviceID, 78 WebserviceData => $WebserviceData, 79 ); 80 } 81 82 # Default: show start screen. 83 return $Self->_ShowScreen( 84 %Param, 85 WebserviceID => $WebserviceID, 86 WebserviceData => $WebserviceData, 87 ); 88} 89 90sub _ShowScreen { 91 my ( $Self, %Param ) = @_; 92 93 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 94 95 my $Output = $LayoutObject->Header(); 96 $Output .= $LayoutObject->NavigationBar(); 97 98 my $FilterLimitStrg = $LayoutObject->BuildSelection( 99 Data => [ 100 '10', 101 '25', 102 '50', 103 '100', 104 '250', 105 '500', 106 '1000', 107 '10000', 108 ], 109 Name => 'FilterLimit', 110 SelectedValue => '10', 111 Translate => 0, 112 Class => 'Modernize', 113 ); 114 115 my $FilterSortStrg = $LayoutObject->BuildSelection( 116 Data => { 117 'ASC' => Translatable('ascending'), 118 'DESC' => Translatable('descending'), 119 }, 120 Name => 'FilterSort', 121 PossibleNone => 0, 122 SelectedID => 'DESC', 123 Translate => 0, 124 Class => 'Modernize', 125 ); 126 127 my $FilterTypeStrg = $LayoutObject->BuildSelection( 128 Data => [ 129 'Provider', 130 'Requester', 131 ], 132 Name => 'FilterType', 133 PossibleNone => 1, 134 Translate => 0, 135 Class => 'Modernize', 136 ); 137 138 my $FilterFromStrg = $LayoutObject->BuildDateSelection( 139 Prefix => 'FilterFrom', 140 DiffTime => -60 * 60 * 24 * 356, 141 ); 142 143 my $FilterToStrg = $LayoutObject->BuildDateSelection( 144 Prefix => 'FilterTo', 145 ); 146 147 $Output .= $LayoutObject->Output( 148 TemplateFile => 'AdminGenericInterfaceDebugger', 149 Data => { 150 %Param, 151 WebserviceName => $Param{WebserviceData}->{Name}, 152 FilterLimitStrg => $FilterLimitStrg, 153 FilterSortStrg => $FilterSortStrg, 154 FilterTypeStrg => $FilterTypeStrg, 155 FilterFromStrg => $FilterFromStrg, 156 FilterToStrg => $FilterToStrg, 157 }, 158 ); 159 160 $Output .= $LayoutObject->Footer(); 161 return $Output; 162} 163 164sub _GetRequestList { 165 my ( $Self, %Param ) = @_; 166 167 my %LogSearchParam = ( 168 WebserviceID => $Param{WebserviceID}, 169 ); 170 171 my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); 172 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 173 174 my $FilterType = $ParamObject->GetParam( Param => 'FilterType' ); 175 $LogSearchParam{CommunicationType} = $FilterType if ($FilterType); 176 177 my $FilterRemoteIP = $ParamObject->GetParam( Param => 'FilterRemoteIP' ); 178 179 if ( $FilterRemoteIP && IsIPv4Address($FilterRemoteIP) ) { 180 $LogSearchParam{RemoteIP} = $FilterRemoteIP; 181 } 182 183 $LogSearchParam{CreatedAtOrAfter} = $ParamObject->GetParam( Param => 'FilterFrom' ); 184 $LogSearchParam{CreatedAtOrBefore} = $ParamObject->GetParam( Param => 'FilterTo' ); 185 $LogSearchParam{Limit} = $ParamObject->GetParam( Param => 'FilterLimit' ) || 10; 186 $LogSearchParam{Sort} = $ParamObject->GetParam( Param => 'FilterSort' ) || 'DESC'; 187 188 my $LogData = $Kernel::OM->Get('Kernel::System::GenericInterface::DebugLog')->LogSearch(%LogSearchParam); 189 190 # Get current user time zone. 191 my $TimeZone = $Self->{UserTimeZone} || $Kernel::OM->Create('Kernel::System::DateTime')->UserDefaultTimeZoneGet(); 192 193 # Set date time format and values for 'Time' column. 194 for my $Log ( @{$LogData} ) { 195 my $DateTimeObject = $Kernel::OM->Create( 196 'Kernel::System::DateTime', 197 ObjectParams => { 198 String => $Log->{Created}, 199 }, 200 ); 201 202 $DateTimeObject->ToTimeZone( 203 TimeZone => $TimeZone, 204 ); 205 206 $Log->{Created} = $LayoutObject->{LanguageObject}->FormatTimeString( 207 $Log->{Created}, 208 'DateFormat', 209 ); 210 } 211 212 # Fail gracefully. 213 $LogData ||= []; 214 215 # Build JSON output. 216 my $JSON = $LayoutObject->JSONEncode( 217 Data => { 218 LogData => $LogData, 219 }, 220 ); 221 222 # Send JSON response. 223 return $LayoutObject->Attachment( 224 ContentType => 'application/json; charset=' . $LayoutObject->{Charset}, 225 Content => $JSON, 226 Type => 'inline', 227 NoCache => 1, 228 ); 229} 230 231sub _GetCommunicationDetails { 232 my ( $Self, %Param ) = @_; 233 234 my $CommunicationID = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'CommunicationID' ); 235 236 if ( !$CommunicationID ) { 237 $Kernel::OM->Get('Kernel::System::Log')->Log( 238 Priority => 'error', 239 Message => 'Got no CommunicationID', 240 ); 241 242 return; # return empty response 243 } 244 245 my $LogData = $Kernel::OM->Get('Kernel::System::GenericInterface::DebugLog')->LogGetWithData( 246 CommunicationID => $CommunicationID, 247 ); 248 249 # Get current user time zone. 250 my $TimeZone = $Self->{UserTimeZone} || $Kernel::OM->Create('Kernel::System::DateTime')->UserDefaultTimeZoneGet(); 251 252 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 253 254 # Duplicate widgets containing xml data and format the new version for better readability. 255 if ( IsArrayRefWithData( $LogData->{Data} ) ) { 256 $Kernel::OM->Get('Kernel::System::Main')->Require('XML::LibXML'); 257 my $XML = XML::LibXML->new(); 258 259 INDEX: 260 for my $Index ( 0 .. scalar( @{ $LogData->{Data} } ) + 1 ) { 261 262 my $Data = $LogData->{Data}->[$Index]->{Data}; 263 264 # remove entries with empty data hashes before JSON encoding 265 if ( !IsHashRefWithData( $LogData->{Data}->[$Index] ) ) { 266 delete $LogData->{Data}->[$Index]; 267 next INDEX; 268 } 269 270 # Set date time format and values for created log time. 271 my $CreatedTime = $LogData->{Data}->[$Index]->{Created}; 272 if ( $LogData->{Data}->[$Index]->{Created} ) { 273 my $DateTimeObject = $Kernel::OM->Create( 274 'Kernel::System::DateTime', 275 ObjectParams => { 276 String => $LogData->{Data}->[$Index]->{Created}, 277 }, 278 ); 279 280 $DateTimeObject->ToTimeZone( 281 TimeZone => $TimeZone, 282 ); 283 284 $LogData->{Data}->[$Index]->{Created} = $LayoutObject->{LanguageObject}->FormatTimeString( 285 $LogData->{Data}->[$Index]->{Created}, 286 'DateFormat', 287 ); 288 } 289 290 next INDEX if !IsStringWithData($Data); 291 next INDEX if substr( $Data, 0, 5 ) ne '<?xml'; 292 293 # Safely attempt to format xml. 294 my $LintedXML; 295 eval { 296 $LintedXML = $XML->parse_string($Data)->serialize(1); 297 }; 298 299 next INDEX if !$LintedXML; 300 301 # Prevent double encoding of utf8 data. 302 utf8::decode($LintedXML); 303 304 next INDEX if $LintedXML eq $Data; 305 306 # If formatted xml differs from original version, add it to data. 307 splice @{ $LogData->{Data} }, $Index + 1, 0, { 308 Created => $CreatedTime, 309 Data => $LintedXML, 310 DebugLevel => $LogData->{Data}->[$Index]->{DebugLevel}, 311 Summary => $LogData->{Data}->[$Index]->{Summary} 312 . ' (auto-formatted XML, not part of original transmission)', 313 }; 314 } 315 } 316 317 # Build JSON output. 318 my $JSON = $LayoutObject->JSONEncode( 319 Data => { 320 LogData => $LogData, 321 }, 322 ); 323 324 # Send JSON response. 325 return $LayoutObject->Attachment( 326 ContentType => 'application/json; charset=' . $LayoutObject->{Charset}, 327 Content => $JSON, 328 Type => 'inline', 329 NoCache => 1, 330 ); 331} 332 333sub _ClearDebugLog { 334 my ( $Self, %Param ) = @_; 335 336 my $Success = $Kernel::OM->Get('Kernel::System::GenericInterface::DebugLog')->LogDelete( 337 WebserviceID => $Param{WebserviceID}, 338 ); 339 340 my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); 341 342 # Build JSON output. 343 my $JSON = $LayoutObject->JSONEncode( 344 Data => { 345 Success => $Success, 346 }, 347 ); 348 349 # Send JSON response. 350 return $LayoutObject->Attachment( 351 ContentType => 'application/json; charset=' . $LayoutObject->{Charset}, 352 Content => $JSON, 353 Type => 'inline', 354 NoCache => 1, 355 ); 356} 357 3581; 359