<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># --
# Kernel/System/StdAttachment.pm - lib for std attachment
# Copyright (C) 2001-2014 OTRS AG, http://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --

package Kernel::System::StdAttachment;

use strict;
use warnings;

use MIME::Base64;

use Kernel::System::CacheInternal;
use Kernel::System::Valid;

=head1 NAME

Kernel::System::StdAttachment - std. attachment lib

=head1 SYNOPSIS

All std. attachment functions.

=head1 PUBLIC INTERFACE

=over 4

=cut

=item new()

create std. attachment object

    use Kernel::Config;
    use Kernel::System::Encode;
    use Kernel::System::Log;
    use Kernel::System::Main;
    use Kernel::System::DB;
    use Kernel::System::StdAttachment;

    my $ConfigObject = Kernel::Config-&gt;new();
    my $EncodeObject = Kernel::System::Encode-&gt;new(
        ConfigObject =&gt; $ConfigObject,
    );
    my $LogObject = Kernel::System::Log-&gt;new(
        ConfigObject =&gt; $ConfigObject,
        EncodeObject =&gt; $EncodeObject,
    );
    my $MainObject = Kernel::System::Main-&gt;new(
        ConfigObject =&gt; $ConfigObject,
        EncodeObject =&gt; $EncodeObject,
        LogObject    =&gt; $LogObject,
    );
    my $DBObject = Kernel::System::DB-&gt;new(
        ConfigObject =&gt; $ConfigObject,
        EncodeObject =&gt; $EncodeObject,
        LogObject    =&gt; $LogObject,
        MainObject   =&gt; $MainObject,
    );
    my $StdAttachmentObject = Kernel::System::StdAttachment-&gt;new(
        ConfigObject =&gt; $ConfigObject,
        DBObject     =&gt; $DBObject,
        EncodeObject =&gt; $EncodeObject,
        LogObject    =&gt; $LogObject,
    );

=cut

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # get needed objects
    for (qw(ConfigObject LogObject DBObject EncodeObject MainObject)) {
        if ( $Param{$_} ) {
            $Self-&gt;{$_} = $Param{$_};
        }
        else {
            die "Got no $_!";
        }
    }

    # create additional objects
    $Self-&gt;{ValidObject}         = Kernel::System::Valid-&gt;new( %{$Self} );
    $Self-&gt;{CacheInternalObject} = Kernel::System::CacheInternal-&gt;new(
        %{$Self},
        Type =&gt; 'StdAttachment',
        TTL  =&gt; 60 * 60 * 24 * 20,
    );

    return $Self;
}

=item StdAttachmentAdd()

create a new std. attachment

    my $ID = $StdAttachmentObject-&gt;StdAttachmentAdd(
        Name        =&gt; 'Some Name',
        ValidID     =&gt; 1,
        Content     =&gt; $Content,
        ContentType =&gt; 'text/xml',
        Filename    =&gt; 'SomeFile.xml',
        UserID      =&gt; 123,
    );

=cut

sub StdAttachmentAdd {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(Name ValidID Content ContentType Filename UserID)) {
        if ( !$Param{$_} ) {
            $Self-&gt;{LogObject}-&gt;Log( Priority =&gt; 'error', Message =&gt; "Need $_!" );
            return;
        }
    }

    # encode attachment if it's a postgresql backend!!!
    if ( !$Self-&gt;{DBObject}-&gt;GetDatabaseFunction('DirectBlob') ) {
        $Self-&gt;{EncodeObject}-&gt;EncodeOutput( \$Param{Content} );
        $Param{Content} = encode_base64( $Param{Content} );
    }

    # sql
    return if !$Self-&gt;{DBObject}-&gt;Do(
        SQL =&gt; 'INSERT INTO standard_attachment '
            . ' (name, content_type, content, filename, valid_id, comments, '
            . ' create_time, create_by, change_time, change_by) VALUES '
            . ' (?, ?, ?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
        Bind =&gt; [
            \$Param{Name},    \$Param{ContentType}, \$Param{Content}, \$Param{Filename},
            \$Param{ValidID}, \$Param{Comment},     \$Param{UserID},  \$Param{UserID},
        ],
    );

    $Self-&gt;{DBObject}-&gt;Prepare(
        SQL =&gt; 'SELECT id FROM standard_attachment WHERE name = ? AND content_type = ?',
        Bind =&gt; [ \$Param{Name}, \$Param{ContentType}, ],
    );
    my $ID;
    while ( my @Row = $Self-&gt;{DBObject}-&gt;FetchrowArray() ) {
        $ID = $Row[0];
    }
    return $ID;
}

=item StdAttachmentGet()

get a std. attachment

    my %Data = $StdAttachmentObject-&gt;StdAttachmentGet(
        ID =&gt; $ID,
    );

=cut

sub StdAttachmentGet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{ID} ) {
        $Self-&gt;{LogObject}-&gt;Log( Priority =&gt; 'error', Message =&gt; 'Need ID!' );
        return;
    }

    # sql
    return if !$Self-&gt;{DBObject}-&gt;Prepare(
        SQL =&gt; 'SELECT name, content_type, content, filename, valid_id, comments, '
            . 'create_time, create_by, change_time, change_by '
            . 'FROM standard_attachment WHERE id = ?',
        Bind   =&gt; [ \$Param{ID} ],
        Encode =&gt; [ 1, 1, 0, 1, 1, 1 ],
        Limit  =&gt; 1,
    );
    my %Data;
    while ( my @Row = $Self-&gt;{DBObject}-&gt;FetchrowArray() ) {

        # decode attachment if it's a postgresql backend!!!
        if ( !$Self-&gt;{DBObject}-&gt;GetDatabaseFunction('DirectBlob') ) {
            $Row[2] = decode_base64( $Row[2] );
        }
        %Data = (
            ID          =&gt; $Param{ID},
            Name        =&gt; $Row[0],
            ContentType =&gt; $Row[1],
            Content     =&gt; $Row[2],
            Filename    =&gt; $Row[3],
            ValidID     =&gt; $Row[4],
            Comment     =&gt; $Row[5],
            CreateTime  =&gt; $Row[6],
            CreateBy    =&gt; $Row[7],
            ChangeTime  =&gt; $Row[8],
            ChangeBy    =&gt; $Row[9],
        );
    }
    return %Data;
}

=item StdAttachmentUpdate()

update a new std. attachment

    my $ID = $StdAttachmentObject-&gt;StdAttachmentUpdate(
        ID          =&gt; $ID,
        Name        =&gt; 'Some Name',
        ValidID     =&gt; 1,
        Content     =&gt; $Content,
        ContentType =&gt; 'text/xml',
        Filename    =&gt; 'SomeFile.xml',
        UserID      =&gt; 123,
    );

=cut

sub StdAttachmentUpdate {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(ID Name ValidID UserID)) {
        if ( !$Param{$_} ) {
            $Self-&gt;{LogObject}-&gt;Log( Priority =&gt; 'error', Message =&gt; "Need $_!" );
            return;
        }
    }

    # reset cache
    my %Data = $Self-&gt;StdAttachmentGet(
        ID =&gt; $Param{ID},
    );
    $Self-&gt;{ 'StdAttachmentLookupID::' . $Data{ID} }      = 0;
    $Self-&gt;{ 'StdAttachmentLookupName::' . $Data{Name} }  = 0;
    $Self-&gt;{ 'StdAttachmentLookupID::' . $Param{ID} }     = 0;
    $Self-&gt;{ 'StdAttachmentLookupName::' . $Param{Name} } = 0;

    # sql
    return if !$Self-&gt;{DBObject}-&gt;Do(
        SQL =&gt; 'UPDATE standard_attachment SET name = ?, comments = ?, valid_id = ?, '
            . 'change_time = current_timestamp, change_by = ? WHERE id = ?',
        Bind =&gt; [
            \$Param{Name}, \$Param{Comment},
            \$Param{ValidID}, \$Param{UserID}, \$Param{ID},
        ],
    );
    if ( $Param{Content} ) {

        # encode attachment if it's a postgresql backend!!!
        if ( !$Self-&gt;{DBObject}-&gt;GetDatabaseFunction('DirectBlob') ) {
            $Self-&gt;{EncodeObject}-&gt;EncodeOutput( \$Param{Content} );
            $Param{Content} = encode_base64( $Param{Content} );
        }

        return if !$Self-&gt;{DBObject}-&gt;Do(
            SQL =&gt; 'UPDATE standard_attachment SET content = ?, content_type = ?, '
                . ' filename = ? WHERE id = ?',
            Bind =&gt; [
                \$Param{Content}, \$Param{ContentType}, \$Param{Filename}, \$Param{ID},
            ],
        );
    }
    return 1;
}

=item StdAttachmentDelete()

delete a std. attachment

    $StdAttachmentObject-&gt;StdAttachmentDelete(
        ID =&gt; $ID,
    );

=cut

sub StdAttachmentDelete {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(ID)) {
        if ( !$Param{$_} ) {
            $Self-&gt;{LogObject}-&gt;Log( Priority =&gt; 'error', Message =&gt; "Need $_!" );
            return;
        }
    }

    # reset cache
    my %Data = $Self-&gt;StdAttachmentGet(
        ID =&gt; $Param{ID},
    );
    $Self-&gt;{ 'StdAttachmentLookupID::' . $Param{ID} }    = 0;
    $Self-&gt;{ 'StdAttachmentLookupName::' . $Data{Name} } = 0;

    # delete attachment&lt;-&gt;std template relation
    return if !$Self-&gt;{DBObject}-&gt;Do(
        SQL  =&gt; 'DELETE FROM standard_template_attachment WHERE standard_attachment_id = ?',
        Bind =&gt; [ \$Param{ID} ],
    );

    # sql
    return if !$Self-&gt;{DBObject}-&gt;Do(
        SQL  =&gt; 'DELETE FROM standard_attachment WHERE ID = ?',
        Bind =&gt; [ \$Param{ID} ],
    );
    return 1;
}

=item StdAttachmentLookup()

lookup for a std. attachment

    my $ID = $StdAttachmentObject-&gt;StdAttachmentLookup(
        StdAttachment =&gt; 'Some Name',
    );

    my $Name = $StdAttachmentObject-&gt;StdAttachmentLookup(
        StdAttachmentID =&gt; $ID,
    );

=cut

sub StdAttachmentLookup {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{StdAttachment} &amp;&amp; !$Param{StdAttachmentID} ) {
        $Self-&gt;{LogObject}-&gt;Log(
            Priority =&gt; 'error',
            Message  =&gt; 'Got no StdAttachment or StdAttachment!',
        );
        return;
    }

    # check if we ask the same request?
    my $CacheKey;
    my $Key;
    my $Value;
    if ( $Param{StdAttachmentID} ) {
        $CacheKey = 'StdAttachmentLookupID::' . $Param{StdAttachmentID};
        $Key      = 'StdAttachmentID';
        $Value    = $Param{StdAttachmentID};
    }
    else {
        $CacheKey = 'StdAttachmentLookupName::' . $Param{StdAttachment};
        $Key      = 'StdAttachment';
        $Value    = $Param{StdAttachment};
    }
    if ( $Self-&gt;{$CacheKey} ) {
        return $Self-&gt;{$CacheKey};
    }

    # get data
    my $SQL;
    my @Bind;
    if ( $Param{StdAttachment} ) {
        $SQL = 'SELECT id FROM standard_attachment WHERE name = ?';
        push @Bind, \$Param{StdAttachment};
    }
    else {
        $SQL = 'SELECT name FROM standard_attachment WHERE id = ?';
        push @Bind, \$Param{StdAttachmentID};
    }
    $Self-&gt;{DBObject}-&gt;Prepare( SQL =&gt; $SQL, Bind =&gt; \@Bind );
    while ( my @Row = $Self-&gt;{DBObject}-&gt;FetchrowArray() ) {
        $Self-&gt;{$CacheKey} = $Row[0];
    }

    # check if data exists
    if ( !$Self-&gt;{$CacheKey} ) {
        $Self-&gt;{LogObject}-&gt;Log(
            Priority =&gt; 'error',
            Message  =&gt; "Found no $Key found for $Value!",
        );
        return;
    }

    return $Self-&gt;{$CacheKey};
}

=item StdAttachmentsByResponseID()

DEPRECATED: This function will be removed in further versions of OTRS

return a hash (ID =&gt; Name) of std. attachment by response id

    my %StdAttachment = $StdAttachmentObject-&gt;StdAttachmentsByResponseID(
        ID =&gt; 4711,
    );

=cut

sub StdAttachmentsByResponseID {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{ID} ) {
        $Self-&gt;{LogObject}-&gt;Log( Priority =&gt; 'error', Message =&gt; 'Got no ID!' );
        return;
    }

    # db quote
    for (qw(ID)) {
        $Param{$_} = $Self-&gt;{DBObject}-&gt;Quote( $Param{$_}, 'Integer' );
    }

    # return data
    my %Relation = $Self-&gt;{DBObject}-&gt;GetTableData(
        Table =&gt; 'standard_template_attachment',
        What  =&gt; 'standard_attachment_id, standard_template_id',
        Where =&gt; "standard_template_id = $Param{ID}",
    );
    my %AllStdAttachments = $Self-&gt;StdAttachmentList( Valid =&gt; 1 );
    my %Data;
    for ( sort keys %Relation ) {
        if ( $AllStdAttachments{$_} ) {
            $Data{$_} = $AllStdAttachments{$_};
        }
        else {
            delete $Data{$_};
        }
    }
    return %Data;
}

=item StdAttachmentList()

return a hash (ID =&gt; Name) of std. attachment

    my %List = $StdAttachmentObject-&gt;StdAttachmentList();

    my %List = $StdAttachmentObject-&gt;StdAttachmentList( Valid =&gt; 1 );

=cut

sub StdAttachmentList {
    my ( $Self, %Param ) = @_;

    if ( !defined $Param{Valid} ) {
        $Param{Valid} = 1;
    }

    # return data
    return $Self-&gt;{DBObject}-&gt;GetTableData(
        Table =&gt; 'standard_attachment',
        What  =&gt; 'id, name, filename',
        Clamp =&gt; 1,
        Valid =&gt; $Param{Valid},
    );
}

=item StdAttachmentSetResponses()

DEPRECATED: This function will be removed in further versions of OTRS

set std responses of response id

    $StdAttachmentObject-&gt;StdAttachmentSetResponses(
        ID               =&gt; 123,
        AttachmentIDsRef =&gt; [1, 2, 3],
        UserID           =&gt; 1,
    );

=cut

sub StdAttachmentSetResponses {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(ID AttachmentIDsRef UserID)) {
        if ( !$Param{$_} ) {
            $Self-&gt;{LogObject}-&gt;Log( Priority =&gt; 'error', Message =&gt; "Need $_!" );
            return;
        }
    }

    # add attachments to response
    return if !$Self-&gt;{DBObject}-&gt;Do(
        SQL  =&gt; 'DELETE FROM standard_template_attachment WHERE standard_template_id = ?',
        Bind =&gt; [ \$Param{ID} ],
    );
    for my $ID ( @{ $Param{AttachmentIDsRef} } ) {
        next if !$ID;
        $Self-&gt;{DBObject}-&gt;Do(
            SQL =&gt; 'INSERT INTO standard_template_attachment (standard_attachment_id, '
                . 'standard_template_id, create_time, create_by, change_time, change_by)'
                . ' VALUES ( ?, ?, current_timestamp, ?, current_timestamp, ?)',
            Bind =&gt; [
                \$ID, \$Param{ID}, \$Param{UserID}, \$Param{UserID},
            ],
        );
    }

    $Self-&gt;{CacheInternalObject}-&gt;CleanUp();
    return 1;
}

=item StdAttachmentStandardTemplateMemberAdd()

to add an attachment to a template

    my $Success = $StdAttachmentObject-&gt;StdAttachmentStandardTemplateMemberAdd(
        AttachmentID       =&gt; 123,
        StandardTemplateID =&gt; 123,
        Active             =&gt; 1,        # optional
        UserID             =&gt; 123,
    );

=cut

sub StdAttachmentStandardTemplateMemberAdd {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for my $Argument (qw(AttachmentID StandardTemplateID UserID)) {
        if ( !$Param{$Argument} ) {
            $Self-&gt;{LogObject}-&gt;Log(
                Priority =&gt; 'error',
                Message  =&gt; "Need $Argument!",
            );
            return;
        }
    }

    # delete existing relation
    return if !$Self-&gt;{DBObject}-&gt;Do(
        SQL =&gt; 'DELETE FROM standard_template_attachment
            WHERE standard_attachment_id = ?
            AND standard_template_id = ?',
        Bind =&gt; [ \$Param{AttachmentID}, \$Param{StandardTemplateID} ],
    );

    # return if relation is not active
    if ( !$Param{Active} ) {
        $Self-&gt;{CacheInternalObject}-&gt;CleanUp();
        return 1;
    }

    # insert new relation
    my $Success = $Self-&gt;{DBObject}-&gt;Do(
        SQL =&gt; '
            INSERT INTO standard_template_attachment (standard_attachment_id, standard_template_id,
                create_time, create_by, change_time, change_by)
            VALUES (?, ?, current_timestamp, ?, current_timestamp, ?)',
        Bind =&gt; [
            \$Param{AttachmentID}, \$Param{StandardTemplateID}, \$Param{UserID},
            \$Param{UserID}
        ],
    );

    $Self-&gt;{CacheInternalObject}-&gt;CleanUp();
    return $Success;
}

=item StdAttachmentStandardTemplateMemberList()

returns a list of Standard Attachment / Standard Template members

    my %List = $StdAttachmentObject-&gt;StdAttachmentStandardTemplateMemberList(
        AttachmentID =&gt; 123,
    );

    or
    my %List = $StdAttachmentObject-&gt;StdAttachmentStandardTemplateMemberList(
        StandardTemplateID =&gt; 123,
    );

Returns:
    %List = (
        1 =&gt; 'Some Name',
        2 =&gt; 'Some Name',
    );

=cut

sub StdAttachmentStandardTemplateMemberList {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{AttachmentID} &amp;&amp; !$Param{StandardTemplateID} ) {
        $Self-&gt;{LogObject}-&gt;Log(
            Priority =&gt; 'error',
            Message  =&gt; 'Need AttachmentID or StandardTemplateID!',
        );
        return;
    }

    if ( $Param{AttachmentID} &amp;&amp; $Param{StandardTemplateID} ) {
        $Self-&gt;{LogObject}-&gt;Log(
            Priority =&gt; 'error',
            Message  =&gt; 'Need AttachmentID or StandardTemplateID, but not both!',
        );
        return;
    }

    # create cache key
    my $CacheKey = 'StdAttachmentStandardTemplateMemberList::';
    if ( $Param{AttachmentID} ) {
        $CacheKey .= 'AttachmentID::' . $Param{AttachmentID};
    }
    elsif ( $Param{StandardTemplateID} ) {
        $CacheKey .= 'StandardTemplateID::' . $Param{StandardTemplateID};
    }

    # check cache
    my $Cache = $Self-&gt;{CacheInternalObject}-&gt;Get( Key =&gt; $CacheKey );
    return %{$Cache} if ref $Cache eq 'HASH';

    # sql
    my %Data;
    my @Bind;
    my $SQL = '
        SELECT sta.standard_attachment_id, sa.name, sta.standard_template_id, st.name
        FROM standard_template_attachment sta, standard_attachment sa, standard_template st
        WHERE';

    if ( $Param{AttachmentID} ) {
        $SQL .= ' st.valid_id IN (' . join ', ', $Self-&gt;{ValidObject}-&gt;ValidIDsGet() . ')';
    }
    elsif ( $Param{StandardTemplateID} ) {
        $SQL .= ' sa.valid_id IN (' . join ', ', $Self-&gt;{ValidObject}-&gt;ValidIDsGet() . ')';
    }

    $SQL .= '
            AND sta.standard_attachment_id = sa.id
            AND sta.standard_template_id = st.id';

    if ( $Param{AttachmentID} ) {
        $SQL .= ' AND sta.standard_attachment_id = ?';
        push @Bind, \$Param{AttachmentID};
    }
    elsif ( $Param{StandardTemplateID} ) {
        $SQL .= ' AND sta.standard_template_id = ?';
        push @Bind, \$Param{StandardTemplateID};
    }

    $Self-&gt;{DBObject}-&gt;Prepare(
        SQL  =&gt; $SQL,
        Bind =&gt; \@Bind,
    );

    while ( my @Row = $Self-&gt;{DBObject}-&gt;FetchrowArray() ) {
        if ( $Param{StandardTemplateID} ) {
            $Data{ $Row[0] } = $Row[1];
        }
        else {
            $Data{ $Row[2] } = $Row[3];
        }
    }

    # return result
    $Self-&gt;{CacheInternalObject}-&gt;Set( Key =&gt; $CacheKey, Value =&gt; \%Data );
    return %Data;
}

1;

=back

=head1 TERMS AND CONDITIONS

This software is part of the OTRS project (L&lt;http://otrs.org/&gt;).

This software comes with ABSOLUTELY NO WARRANTY. For details, see
the enclosed file COPYING for license information (AGPL). If you
did not receive this file, see L&lt;http://www.gnu.org/licenses/agpl.txt&gt;.

=cut
</pre></body></html>