<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  _____         _             _
// |_   _|_ _  __| |_ __   ___ | | ___
//   | |/ _` |/ _` | '_ \ / _ \| |/ _ \
//   | | (_| | (_| | |_) | (_) | |  __/
//   |_|\__,_|\__,_| .__/ \___/|_|\___|
//                 |_|
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "common.hh"
#if defined(TADPOLE_GNUC)
# include <unistd.h>
#else
# include <io.h>
# include <windows.h>
#endif
#include "colorful.hh"

namespace tadpole::colorful {

inline FILE* get_standard_stream(const std::ostream& stream) noexcept {
  if (&stream == &std::cout)
    return stdout;
  else if ((&stream == &std::cerr) || (&stream == &std::clog))
    return stderr;
  return nullptr;
}

inline bool is_atty(std::ostream& stream) noexcept {
  FILE* std_stream = get_standard_stream(stream);
  if (!std_stream)
    return false;

#if defined(TADPOLE_GNUC)
  return ::isatty(::fileno(std_stream));
#else
  return ::_isatty(::_fileno(std_stream));
#endif
}

#if defined(TADPOLE_GNUC)
inline const char* get_colorful(Colorful c) noexcept {
  switch (c) {
  case Colorful::RESET: return "\033[00m";
  case Colorful::FG_BLACK: return "\033[30m";
  case Colorful::FG_RED: return "\033[31m";
  case Colorful::FG_GREEN: return "\033[32m";
  case Colorful::FG_YELLOW: return "\033[33m";
  case Colorful::FG_BLUE: return "\033[34m";
  case Colorful::FG_MAGENTA: return "\033[35m";
  case Colorful::FG_CYAN: return "\033[36m";
  case Colorful::FG_WHITE: return "\033[37m";
  case Colorful::FG_GRAY: return "\033[90m";
  case Colorful::FG_LIGHTRED: return "\033[91m";
  case Colorful::FG_LIGHTGREEN: return "\033[92m";
  case Colorful::FG_LIGHTYELLOW: return "\033[93m";
  case Colorful::FG_LIGHTBLUE: return "\033[94m";
  case Colorful::FG_LIGHTMAGENTA: return "\033[95m";
  case Colorful::FG_LIGHTCYAN: return "\033[96m";
  case Colorful::FG_LIGHTWHITE: return "\033[97m";
  case Colorful::BG_BLACK: return "\033[40m";
  case Colorful::BG_RED: return "\033[41m";
  case Colorful::BG_GREEN: return "\033[42m";
  case Colorful::BG_YELLOW: return "\033[43m";
  case Colorful::BG_BLUE: return "\033[44m";
  case Colorful::BG_MAGENTA: return "\033[45m";
  case Colorful::BG_CYAN: return "\033[46m";
  case Colorful::BG_WHITE: return "\033[47m";
  case Colorful::BG_GRAY: return "\033[100m";
  case Colorful::BG_LIGHTRED: return "\033[101m";
  case Colorful::BG_LIGHTGREEN: return "\033[102m";
  case Colorful::BG_LIGHTYELLOW: return "\033[103m";
  case Colorful::BG_LIGHTBLUE: return "\033[104m";
  case Colorful::BG_LIGHTMAGENTA: return "\033[105m";
  case Colorful::BG_LIGHTCYAN: return "\033[106m";
  case Colorful::BG_LIGHTWHITE: return "\033[107m";
  }
  return "\033[00m";
}
#else
inline int get_colorful(Colorful c) noexcept {
  switch (c) {
  case Colorful::RESET: return -1;
  case Colorful::FG_BLACK: return FOREGROUND_RED & FOREGROUND_GREEN & FOREGROUND_BLUE;
  case Colorful::FG_RED: return FOREGROUND_RED;
  case Colorful::FG_GREEN: return FOREGROUND_GREEN;
  case Colorful::FG_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
  case Colorful::FG_BLUE: return FOREGROUND_BLUE;
  case Colorful::FG_MAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE;
  case Colorful::FG_CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Colorful::FG_WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Colorful::FG_GRAY: return FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTRED: return FOREGROUND_RED | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTGREEN: return FOREGROUND_GREEN | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTYELLOW: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTBLUE: return FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTMAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTCYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTWHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  }
  return -1;
}

inline std::ostream& set_colorful(
    std::ostream& stream, int foreground = -1, int background = -1) noexcept {
  static WORD wDefaultAttributes = 0;

  if (!is_atty(stream))
    return stream;

  HANDLE hTerminal = INVALID_HANDLE_VALUE;
  if (&stream == &std::cout)
    hTerminal = ::GetStdHandle(STD_OUTPUT_HANDLE);
  else if (&stream == &std::cerr)
    hTerminal = ::GetStdHandle(STD_ERROR_HANDLE);

  if (!wDefaultAttributes) {
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (!::GetConsoleScreenBufferInfo(hTerminal, &info))
      return stream;
    wDefaultAttributes = info.wAttributes;
  }
  if (foreground == -1 && background == -1) {
    ::SetConsoleTextAttribute(hTerminal, wDefaultAttributes);
    return stream;
  }

  CONSOLE_SCREEN_BUFFER_INFO info;
  if (!::GetConsoleScreenBufferInfo(hTerminal, &info))
    return stream;

  if (foreground != -1) {
    info.wAttributes &= ~(info.wAttributes & 0x0F);
    info.wAttributes |= as_type<WORD>(foreground);
  }
  if (background != -1) {
    info.wAttributes &= ~(info.wAttributes & 0xF0);
    info.wAttributes |= as_type<WORD>(background);
  }

  ::SetConsoleTextAttribute(hTerminal, info.wAttributes);
  return stream;
}
#endif

std::ostream& set_foreground_colorful(std::ostream& stream, Colorful c) noexcept {
#if defined(TADPOLE_GNUC)
  return stream << get_colorful(c);
#else
  return set_colorful(stream, get_colorful(c));
#endif
}

std::ostream& set_background_colorful(std::ostream& stream, Colorful c) noexcept {
#if defined(TADPOLE_GNUC)
  return stream << get_colorful(c);
#else
  return set_colorful(stream, -1, get_colorful(c));
#endif
}

}
<commit_msg>:construction: chore(colorful): updated the colorful with WINDOWS color<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  _____         _             _
// |_   _|_ _  __| |_ __   ___ | | ___
//   | |/ _` |/ _` | '_ \ / _ \| |/ _ \
//   | | (_| | (_| | |_) | (_) | |  __/
//   |_|\__,_|\__,_| .__/ \___/|_|\___|
//                 |_|
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "common.hh"
#if defined(TADPOLE_GNUC)
# include <unistd.h>
#else
# include <io.h>
# include <windows.h>
#endif
#include "colorful.hh"

namespace tadpole::colorful {

inline FILE* get_standard_stream(const std::ostream& stream) noexcept {
  if (&stream == &std::cout)
    return stdout;
  else if ((&stream == &std::cerr) || (&stream == &std::clog))
    return stderr;
  return nullptr;
}

inline bool is_atty(std::ostream& stream) noexcept {
  FILE* std_stream = get_standard_stream(stream);
  if (!std_stream)
    return false;

#if defined(TADPOLE_GNUC)
  return ::isatty(::fileno(std_stream));
#else
  return ::_isatty(::_fileno(std_stream));
#endif
}

#if defined(TADPOLE_GNUC)
inline const char* get_colorful(Colorful c) noexcept {
  switch (c) {
  case Colorful::RESET: return "\033[00m";
  case Colorful::FG_BLACK: return "\033[30m";
  case Colorful::FG_RED: return "\033[31m";
  case Colorful::FG_GREEN: return "\033[32m";
  case Colorful::FG_YELLOW: return "\033[33m";
  case Colorful::FG_BLUE: return "\033[34m";
  case Colorful::FG_MAGENTA: return "\033[35m";
  case Colorful::FG_CYAN: return "\033[36m";
  case Colorful::FG_WHITE: return "\033[37m";
  case Colorful::FG_GRAY: return "\033[90m";
  case Colorful::FG_LIGHTRED: return "\033[91m";
  case Colorful::FG_LIGHTGREEN: return "\033[92m";
  case Colorful::FG_LIGHTYELLOW: return "\033[93m";
  case Colorful::FG_LIGHTBLUE: return "\033[94m";
  case Colorful::FG_LIGHTMAGENTA: return "\033[95m";
  case Colorful::FG_LIGHTCYAN: return "\033[96m";
  case Colorful::FG_LIGHTWHITE: return "\033[97m";
  case Colorful::BG_BLACK: return "\033[40m";
  case Colorful::BG_RED: return "\033[41m";
  case Colorful::BG_GREEN: return "\033[42m";
  case Colorful::BG_YELLOW: return "\033[43m";
  case Colorful::BG_BLUE: return "\033[44m";
  case Colorful::BG_MAGENTA: return "\033[45m";
  case Colorful::BG_CYAN: return "\033[46m";
  case Colorful::BG_WHITE: return "\033[47m";
  case Colorful::BG_GRAY: return "\033[100m";
  case Colorful::BG_LIGHTRED: return "\033[101m";
  case Colorful::BG_LIGHTGREEN: return "\033[102m";
  case Colorful::BG_LIGHTYELLOW: return "\033[103m";
  case Colorful::BG_LIGHTBLUE: return "\033[104m";
  case Colorful::BG_LIGHTMAGENTA: return "\033[105m";
  case Colorful::BG_LIGHTCYAN: return "\033[106m";
  case Colorful::BG_LIGHTWHITE: return "\033[107m";
  }
  return "\033[00m";
}
#else
inline int get_colorful(Colorful c) noexcept {
  switch (c) {
  case Colorful::RESET: return -1;
  case Colorful::FG_BLACK: return FOREGROUND_RED & FOREGROUND_GREEN & FOREGROUND_BLUE;
  case Colorful::FG_RED: return FOREGROUND_RED;
  case Colorful::FG_GREEN: return FOREGROUND_GREEN;
  case Colorful::FG_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
  case Colorful::FG_BLUE: return FOREGROUND_BLUE;
  case Colorful::FG_MAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE;
  case Colorful::FG_CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Colorful::FG_WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  case Colorful::FG_GRAY: return FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTRED: return FOREGROUND_RED | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTGREEN: return FOREGROUND_GREEN | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTYELLOW: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTBLUE: return FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTMAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTCYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::FG_LIGHTWHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  case Colorful::BG_BLACK: return BACKGROUND_RED & BACKGROUND_GREEN & BACKGROUND_BLUE;
  case Colorful::BG_RED: return BACKGROUND_RED;
  case Colorful::BG_GREEN: return BACKGROUND_GREEN;
  case Colorful::BG_YELLOW: return BACKGROUND_RED | BACKGROUND_GREEN;
  case Colorful::BG_BLUE: return BACKGROUND_BLUE;
  case Colorful::BG_MAGENTA: return BACKGROUND_RED | BACKGROUND_BLUE;
  case Colorful::BG_CYAN: return BACKGROUND_GREEN | BACKGROUND_BLUE;
  case Colorful::BG_WHITE: return BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
  case Colorful::BG_GRAY: return BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTRED: return BACKGROUND_RED | BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTGREEN: return BACKGROUND_GREEN | BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTYELLOW: return BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTBLUE: return BACKGROUND_BLUE | BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTMAGENTA: return BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTCYAN: return BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
  case Colorful::BG_LIGHTWHITE: return BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
  }
  return -1;
}

inline std::ostream& set_colorful(
    std::ostream& stream, int foreground = -1, int background = -1) noexcept {
  static WORD wDefaultAttributes = 0;

  if (!is_atty(stream))
    return stream;

  HANDLE hTerminal = INVALID_HANDLE_VALUE;
  if (&stream == &std::cout)
    hTerminal = ::GetStdHandle(STD_OUTPUT_HANDLE);
  else if (&stream == &std::cerr)
    hTerminal = ::GetStdHandle(STD_ERROR_HANDLE);

  if (!wDefaultAttributes) {
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (!::GetConsoleScreenBufferInfo(hTerminal, &info))
      return stream;
    wDefaultAttributes = info.wAttributes;
  }
  if (foreground == -1 && background == -1) {
    ::SetConsoleTextAttribute(hTerminal, wDefaultAttributes);
    return stream;
  }

  CONSOLE_SCREEN_BUFFER_INFO info;
  if (!::GetConsoleScreenBufferInfo(hTerminal, &info))
    return stream;

  if (foreground != -1) {
    info.wAttributes &= ~(info.wAttributes & 0x0F);
    info.wAttributes |= as_type<WORD>(foreground);
  }
  if (background != -1) {
    info.wAttributes &= ~(info.wAttributes & 0xF0);
    info.wAttributes |= as_type<WORD>(background);
  }

  ::SetConsoleTextAttribute(hTerminal, info.wAttributes);
  return stream;
}
#endif

std::ostream& set_foreground_colorful(std::ostream& stream, Colorful c) noexcept {
#if defined(TADPOLE_GNUC)
  return stream << get_colorful(c);
#else
  return set_colorful(stream, get_colorful(c));
#endif
}

std::ostream& set_background_colorful(std::ostream& stream, Colorful c) noexcept {
#if defined(TADPOLE_GNUC)
  return stream << get_colorful(c);
#else
  return set_colorful(stream, -1, get_colorful(c));
#endif
}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: implcustomsprite.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 08:27:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <implcustomsprite.hxx>
#include <implcanvas.hxx>

using namespace ::com::sun::star;

namespace cppcanvas
{
    namespace internal
    {
        ImplCustomSprite::ImplCustomSprite( const uno::Reference< rendering::XSpriteCanvas >&       rParentCanvas,
                                            const uno::Reference< rendering::XCustomSprite >&       rSprite,
                                            const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
            ImplSprite( rParentCanvas,
                        uno::Reference< rendering::XSprite >(rSprite,
                                                             uno::UNO_QUERY),
                        rTransformArbiter ),
            mpLastCanvas(),
            mxCustomSprite( rSprite )
        {
            OSL_ENSURE( rParentCanvas.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid canvas" );
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid sprite" );
        }

        ImplCustomSprite::~ImplCustomSprite()
        {
        }

        CanvasSharedPtr ImplCustomSprite::getContentCanvas() const
        {
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::getContentCanvas(): Invalid sprite" );

            if( !mxCustomSprite.is() )
                return CanvasSharedPtr();

            uno::Reference< rendering::XCanvas > xCanvas( mxCustomSprite->getContentCanvas() );

            if( !xCanvas.is() )
                return CanvasSharedPtr();

            // cache content canvas C++ wrapper
            if( mpLastCanvas.get() == NULL ||
                mpLastCanvas->getUNOCanvas() != xCanvas )
            {
                mpLastCanvas = CanvasSharedPtr( new ImplCanvas( xCanvas ) );
            }

            return mpLastCanvas;
        }
    }
}
<commit_msg>INTEGRATION: CWS canvas02 (1.5.8); FILE MERGED 2005/10/09 09:20:43 thb 1.5.8.2: RESYNC: (1.5-1.6); FILE MERGED 2005/08/19 11:08:34 thb 1.5.8.1: #i53538# Changed clip setting to use basegfx polygon (cppcanvas::PolyPolygon contains reference back to canvas); changed direct access to base class member to getter method, thus, providing the actual XCanvas clip polygon lazily.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: implcustomsprite.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2005-11-02 13:43:38 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX
#include <basegfx/polygon/b2dpolypolygon.hxx>
#endif

#include <implcustomsprite.hxx>
#include <implcanvas.hxx>

using namespace ::com::sun::star;

namespace cppcanvas
{
    namespace internal
    {
        ImplCustomSprite::ImplCustomSprite( const uno::Reference< rendering::XSpriteCanvas >&       rParentCanvas,
                                            const uno::Reference< rendering::XCustomSprite >&       rSprite,
                                            const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
            ImplSprite( rParentCanvas,
                        uno::Reference< rendering::XSprite >(rSprite,
                                                             uno::UNO_QUERY),
                        rTransformArbiter ),
            mpLastCanvas(),
            mxCustomSprite( rSprite )
        {
            OSL_ENSURE( rParentCanvas.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid canvas" );
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid sprite" );
        }

        ImplCustomSprite::~ImplCustomSprite()
        {
        }

        CanvasSharedPtr ImplCustomSprite::getContentCanvas() const
        {
            OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::getContentCanvas(): Invalid sprite" );

            if( !mxCustomSprite.is() )
                return CanvasSharedPtr();

            uno::Reference< rendering::XCanvas > xCanvas( mxCustomSprite->getContentCanvas() );

            if( !xCanvas.is() )
                return CanvasSharedPtr();

            // cache content canvas C++ wrapper
            if( mpLastCanvas.get() == NULL ||
                mpLastCanvas->getUNOCanvas() != xCanvas )
            {
                mpLastCanvas = CanvasSharedPtr( new ImplCanvas( xCanvas ) );
            }

            return mpLastCanvas;
        }
    }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Oreste Costa-Panaia
////////////////////////////////////////////////////////////////////////////////

#include "SslInterface.h"

#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>

#include "Basics/StringUtils.h"
#include "Random/UniformCharacter.h"

#ifdef OPENSSL_NO_SSL2 // OpenSSL > 1.1.0 deprecates RAND_pseudo_bytes
#define RAND_BYTES RAND_bytes
#else
#define RAND_BYTES RAND_pseudo_bytes
#endif

using namespace arangodb;
using namespace arangodb::basics;

// -----------------------------------------------------------------------------
// helper
// -----------------------------------------------------------------------------

namespace {
static UniformCharacter SaltGenerator(
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(){}"
    "[]:;<>,.?/|");
}

namespace arangodb {
namespace rest {
namespace SslInterface {

// -----------------------------------------------------------------------------
// public methods
// -----------------------------------------------------------------------------

std::string sslMD5(std::string const& inputStr) {
  char hash[17];
  char* p = &hash[0];
  size_t length;

  sslMD5(inputStr.c_str(), inputStr.size(), p, length);

  char hex[33];
  p = &hex[0];

  SslInterface::sslHEX(hash, 16, p, length);

  return std::string(hex, 32);
}

void sslMD5(char const* inputStr, size_t length, char*& outputStr,
            size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[MD5_DIGEST_LENGTH];
    outputLen = MD5_DIGEST_LENGTH;
  }

  MD5((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslMD5(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslMD5(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslMD5(char const* input1, size_t length1, char const* input2,
            size_t length2, char*& outputStr, size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[MD5_DIGEST_LENGTH];
    outputLen = MD5_DIGEST_LENGTH;
  }

  MD5_CTX ctx;

  MD5_Init(&ctx);
  MD5_Update(&ctx, input1, length1);
  MD5_Update(&ctx, input2, length2);
  MD5_Final((unsigned char*)outputStr, &ctx);
}

void sslSHA1(char const* inputStr, size_t length, char*& outputStr,
             size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA_DIGEST_LENGTH];
    outputLen = SHA_DIGEST_LENGTH;
  }

  SHA1((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA1(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA1(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA224(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA224_DIGEST_LENGTH];
    outputLen = SHA224_DIGEST_LENGTH;
  }

  SHA224((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA224(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA224(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA256(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA256_DIGEST_LENGTH];
    outputLen = SHA256_DIGEST_LENGTH;
  }

  SHA256((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA256(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA256(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA384(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA384_DIGEST_LENGTH];
    outputLen = SHA384_DIGEST_LENGTH;
  }

  SHA384((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA384(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA384(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA512(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA512_DIGEST_LENGTH];
    outputLen = SHA512_DIGEST_LENGTH;
  }

  SHA512((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA512(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA512(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslHEX(char const* inputStr, size_t length, char*& outputStr,
            size_t& outputLen) {
  static char const hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
                                  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

  if (outputStr == nullptr) {
    outputStr = new char[length * 2 + 1];
    outputLen = length * 2;
  }

  char const* e = inputStr + length;
  char* p = outputStr;

  for (char const* q = inputStr; q < e; ++q) {
    *p++ = hexval[(*q >> 4) & 0xF];
    *p++ = hexval[*q & 0x0F];
  }

  *p = '\0';
}

void sslHEX(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslHEX(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslBASE64(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  std::string b = StringUtils::encodeBase64(std::string(inputStr, length));

  if (outputStr == nullptr) {
    outputStr = new char[b.size() + 1];
    outputLen = length * 2;
  }

  memcpy(outputStr, b.c_str(), outputLen);
}

void sslBASE64(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslBASE64(inputStr, strlen(inputStr), outputStr, outputLen);
}

std::string sslPBKDF2HS1(char const* salt, size_t saltLength, char const* pass,
                      size_t passLength, int iter, int keyLength) {
  unsigned char* dk =
      (unsigned char*)TRI_SystemAllocate(EVP_MAX_MD_SIZE + 1, false);

  PKCS5_PBKDF2_HMAC_SHA1(pass, (int)passLength, (const unsigned char*)salt,
                         (int)saltLength, iter, keyLength, dk);

  // return value as hex
  std::string result =
      StringUtils::encodeHex(std::string((char*)dk, keyLength));
  TRI_SystemFree(dk);

  return result;
}

std::string sslPBKDF2(char const* salt, size_t saltLength, char const* pass,
                      size_t passLength, int iter, int keyLength, Algorithm algorithm) {
  EVP_MD* evp_md = nullptr;

  if (algorithm == Algorithm::ALGORITHM_SHA1) {
    evp_md = const_cast<EVP_MD*>(EVP_sha1());
  } else if (algorithm == Algorithm::ALGORITHM_SHA224) {
    evp_md = const_cast<EVP_MD*>(EVP_sha224());
  } else if (algorithm == Algorithm::ALGORITHM_MD5) {
    evp_md = const_cast<EVP_MD*>(EVP_md5());
  } else if (algorithm == Algorithm::ALGORITHM_SHA384) {
    evp_md = const_cast<EVP_MD*>(EVP_sha384());
  } else if (algorithm == Algorithm::ALGORITHM_SHA512) {
    evp_md = const_cast<EVP_MD*>(EVP_sha512());
  } else {
    // default
    evp_md = const_cast<EVP_MD*>(EVP_sha256());
  }

  unsigned char* dk =
      (unsigned char*)TRI_SystemAllocate(EVP_MAX_MD_SIZE + 1, false);

  PKCS5_PBKDF2_HMAC(pass, (int)passLength, (const unsigned char*)salt,
                         (int)saltLength, iter, evp_md, keyLength, dk);

  // return value as hex
  std::string result =
      StringUtils::encodeHex(std::string((char*)dk, keyLength));
  TRI_SystemFree(dk);

  return result;
}

std::string sslHMAC(char const* key, size_t keyLength, char const* message,
                    size_t messageLen, Algorithm algorithm) {
  EVP_MD* evp_md = nullptr;

  if (algorithm == Algorithm::ALGORITHM_SHA1) {
    evp_md = const_cast<EVP_MD*>(EVP_sha1());
  } else if (algorithm == Algorithm::ALGORITHM_SHA224) {
    evp_md = const_cast<EVP_MD*>(EVP_sha224());
  } else if (algorithm == Algorithm::ALGORITHM_MD5) {
    evp_md = const_cast<EVP_MD*>(EVP_md5());
  } else if (algorithm == Algorithm::ALGORITHM_SHA384) {
    evp_md = const_cast<EVP_MD*>(EVP_sha384());
  } else if (algorithm == Algorithm::ALGORITHM_SHA512) {
    evp_md = const_cast<EVP_MD*>(EVP_sha512());
  } else {
    // default
    evp_md = const_cast<EVP_MD*>(EVP_sha256());
  }

  unsigned char* md =
      (unsigned char*)TRI_SystemAllocate(EVP_MAX_MD_SIZE + 1, false);
  unsigned int md_len;

  HMAC(evp_md, key, (int)keyLength, (const unsigned char*)message, messageLen,
       md, &md_len);

  std::string result = std::string((char*)md, md_len);
  TRI_SystemFree(md);

  return result;
}

bool verifyHMAC(char const* challenge, size_t challengeLength,
                char const* secret, size_t secretLen, char const* response,
                size_t responseLen, Algorithm algorithm) {
  // challenge = key
  // secret, secretLen = message
  // result must == BASE64(response, responseLen)

  std::string s =
      sslHMAC(challenge, challengeLength, secret, secretLen, algorithm);

  if (s.length() == responseLen &&
      s.compare(std::string(response, responseLen)) == 0) {
    return true;
  }

  return false;
}

int sslRand(uint64_t* value) {
  if (!RAND_BYTES((unsigned char*)value, sizeof(uint64_t))) {
    return 1;
  }

  return 0;
}

int sslRand(int64_t* value) {
  if (!RAND_BYTES((unsigned char*)value, sizeof(int64_t))) {
    return 1;
  }

  return 0;
}

int sslRand(int32_t* value) {
  if (!RAND_BYTES((unsigned char*)value, sizeof(int32_t))) {
    return 1;
  }

  return 0;
}

void salt64(uint64_t& result) {
  std::string salt = SaltGenerator.random(8);
  char* saltChar = const_cast<char*>(salt.c_str());
  uint64_t* saltInt = reinterpret_cast<uint64_t*>(saltChar);
  result = *saltInt;
}

void saltChar(char*& result, size_t length) {
  if (length == 0) {
    result = 0;
    return;
  }

  std::string salt = SaltGenerator.random(length);
  result = StringUtils::duplicate(salt);
}
}
}
}
<commit_msg>fixed memory allocation which resulted in an out of bounds read<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Oreste Costa-Panaia
////////////////////////////////////////////////////////////////////////////////

#include "SslInterface.h"

#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>

#include "Basics/StringUtils.h"
#include "Random/UniformCharacter.h"

#ifdef OPENSSL_NO_SSL2 // OpenSSL > 1.1.0 deprecates RAND_pseudo_bytes
#define RAND_BYTES RAND_bytes
#else
#define RAND_BYTES RAND_pseudo_bytes
#endif

using namespace arangodb;
using namespace arangodb::basics;

// -----------------------------------------------------------------------------
// helper
// -----------------------------------------------------------------------------

namespace {
static UniformCharacter SaltGenerator(
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(){}"
    "[]:;<>,.?/|");
}

namespace arangodb {
namespace rest {
namespace SslInterface {

// -----------------------------------------------------------------------------
// public methods
// -----------------------------------------------------------------------------

std::string sslMD5(std::string const& inputStr) {
  char hash[17];
  char* p = &hash[0];
  size_t length;

  sslMD5(inputStr.c_str(), inputStr.size(), p, length);

  char hex[33];
  p = &hex[0];

  SslInterface::sslHEX(hash, 16, p, length);

  return std::string(hex, 32);
}

void sslMD5(char const* inputStr, size_t length, char*& outputStr,
            size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[MD5_DIGEST_LENGTH];
    outputLen = MD5_DIGEST_LENGTH;
  }

  MD5((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslMD5(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslMD5(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslMD5(char const* input1, size_t length1, char const* input2,
            size_t length2, char*& outputStr, size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[MD5_DIGEST_LENGTH];
    outputLen = MD5_DIGEST_LENGTH;
  }

  MD5_CTX ctx;

  MD5_Init(&ctx);
  MD5_Update(&ctx, input1, length1);
  MD5_Update(&ctx, input2, length2);
  MD5_Final((unsigned char*)outputStr, &ctx);
}

void sslSHA1(char const* inputStr, size_t length, char*& outputStr,
             size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA_DIGEST_LENGTH];
    outputLen = SHA_DIGEST_LENGTH;
  }

  SHA1((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA1(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA1(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA224(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA224_DIGEST_LENGTH];
    outputLen = SHA224_DIGEST_LENGTH;
  }

  SHA224((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA224(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA224(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA256(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA256_DIGEST_LENGTH];
    outputLen = SHA256_DIGEST_LENGTH;
  }

  SHA256((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA256(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA256(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA384(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA384_DIGEST_LENGTH];
    outputLen = SHA384_DIGEST_LENGTH;
  }

  SHA384((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA384(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA384(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslSHA512(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  if (outputStr == nullptr) {
    outputStr = new char[SHA512_DIGEST_LENGTH];
    outputLen = SHA512_DIGEST_LENGTH;
  }

  SHA512((const unsigned char*)inputStr, length, (unsigned char*)outputStr);
}

void sslSHA512(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslSHA512(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslHEX(char const* inputStr, size_t length, char*& outputStr,
            size_t& outputLen) {
  static char const hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
                                  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

  if (outputStr == nullptr) {
    outputStr = new char[length * 2 + 1];
    outputLen = length * 2;
  }

  char const* e = inputStr + length;
  char* p = outputStr;

  for (char const* q = inputStr; q < e; ++q) {
    *p++ = hexval[(*q >> 4) & 0xF];
    *p++ = hexval[*q & 0x0F];
  }

  *p = '\0';
}

void sslHEX(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslHEX(inputStr, strlen(inputStr), outputStr, outputLen);
}

void sslBASE64(char const* inputStr, size_t length, char*& outputStr,
               size_t& outputLen) {
  std::string b = StringUtils::encodeBase64(std::string(inputStr, length));

  if (outputStr == nullptr) {
    outputStr = new char[b.size() + 1];
    outputLen = length * 2;
  }

  memcpy(outputStr, b.c_str(), outputLen);
}

void sslBASE64(char const* inputStr, char*& outputStr, size_t& outputLen) {
  sslBASE64(inputStr, strlen(inputStr), outputStr, outputLen);
}

std::string sslPBKDF2HS1(char const* salt, size_t saltLength, char const* pass,
                      size_t passLength, int iter, int keyLength) {
  unsigned char* dk =
      (unsigned char*)TRI_SystemAllocate(keyLength + 1, false);

  PKCS5_PBKDF2_HMAC_SHA1(pass, (int)passLength, (const unsigned char*)salt,
                         (int)saltLength, iter, keyLength, dk);

  // return value as hex
  std::string result =
      StringUtils::encodeHex(std::string((char*)dk, keyLength));
  TRI_SystemFree(dk);

  return result;
}

std::string sslPBKDF2(char const* salt, size_t saltLength, char const* pass,
                      size_t passLength, int iter, int keyLength, Algorithm algorithm) {
  EVP_MD* evp_md = nullptr;

  if (algorithm == Algorithm::ALGORITHM_SHA1) {
    evp_md = const_cast<EVP_MD*>(EVP_sha1());
  } else if (algorithm == Algorithm::ALGORITHM_SHA224) {
    evp_md = const_cast<EVP_MD*>(EVP_sha224());
  } else if (algorithm == Algorithm::ALGORITHM_MD5) {
    evp_md = const_cast<EVP_MD*>(EVP_md5());
  } else if (algorithm == Algorithm::ALGORITHM_SHA384) {
    evp_md = const_cast<EVP_MD*>(EVP_sha384());
  } else if (algorithm == Algorithm::ALGORITHM_SHA512) {
    evp_md = const_cast<EVP_MD*>(EVP_sha512());
  } else {
    // default
    evp_md = const_cast<EVP_MD*>(EVP_sha256());
  }

  unsigned char* dk =
      (unsigned char*)TRI_SystemAllocate(keyLength + 1, false);

  PKCS5_PBKDF2_HMAC(pass, (int)passLength, (const unsigned char*)salt,
                         (int)saltLength, iter, evp_md, keyLength, dk);

  // return value as hex
  std::string result =
      StringUtils::encodeHex(std::string((char*)dk, keyLength));
  TRI_SystemFree(dk);

  return result;
}

std::string sslHMAC(char const* key, size_t keyLength, char const* message,
                    size_t messageLen, Algorithm algorithm) {
  EVP_MD* evp_md = nullptr;

  if (algorithm == Algorithm::ALGORITHM_SHA1) {
    evp_md = const_cast<EVP_MD*>(EVP_sha1());
  } else if (algorithm == Algorithm::ALGORITHM_SHA224) {
    evp_md = const_cast<EVP_MD*>(EVP_sha224());
  } else if (algorithm == Algorithm::ALGORITHM_MD5) {
    evp_md = const_cast<EVP_MD*>(EVP_md5());
  } else if (algorithm == Algorithm::ALGORITHM_SHA384) {
    evp_md = const_cast<EVP_MD*>(EVP_sha384());
  } else if (algorithm == Algorithm::ALGORITHM_SHA512) {
    evp_md = const_cast<EVP_MD*>(EVP_sha512());
  } else {
    // default
    evp_md = const_cast<EVP_MD*>(EVP_sha256());
  }

  unsigned char* md =
      (unsigned char*)TRI_SystemAllocate(EVP_MAX_MD_SIZE + 1, false);
  unsigned int md_len;

  HMAC(evp_md, key, (int)keyLength, (const unsigned char*)message, messageLen,
       md, &md_len);

  std::string result = std::string((char*)md, md_len);
  TRI_SystemFree(md);

  return result;
}

bool verifyHMAC(char const* challenge, size_t challengeLength,
                char const* secret, size_t secretLen, char const* response,
                size_t responseLen, Algorithm algorithm) {
  // challenge = key
  // secret, secretLen = message
  // result must == BASE64(response, responseLen)

  std::string s =
      sslHMAC(challenge, challengeLength, secret, secretLen, algorithm);

  if (s.length() == responseLen &&
      s.compare(std::string(response, responseLen)) == 0) {
    return true;
  }

  return false;
}

int sslRand(uint64_t* value) {
  if (!RAND_BYTES((unsigned char*)value, sizeof(uint64_t))) {
    return 1;
  }

  return 0;
}

int sslRand(int64_t* value) {
  if (!RAND_BYTES((unsigned char*)value, sizeof(int64_t))) {
    return 1;
  }

  return 0;
}

int sslRand(int32_t* value) {
  if (!RAND_BYTES((unsigned char*)value, sizeof(int32_t))) {
    return 1;
  }

  return 0;
}

void salt64(uint64_t& result) {
  std::string salt = SaltGenerator.random(8);
  char* saltChar = const_cast<char*>(salt.c_str());
  uint64_t* saltInt = reinterpret_cast<uint64_t*>(saltChar);
  result = *saltInt;
}

void saltChar(char*& result, size_t length) {
  if (length == 0) {
    result = 0;
    return;
  }

  std::string salt = SaltGenerator.random(length);
  result = StringUtils::duplicate(salt);
}
}
}
}
<|endoftext|>


<commit_before>// KMail Account

#include "kmaccount.h"

#include "accountmanager.h"
using KMail::AccountManager;
#include "kmacctfolder.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include "messagesender.h"
#include "kmmessage.h"
#include "broadcaststatus.h"
using KPIM::BroadcastStatus;
#include "kmfoldercachedimap.h"

#include "progressmanager.h"
using KPIM::ProgressItem;
using KPIM::ProgressManager;

#include <kpimidentities/identitymanager.h>
#include <kpimidentities/identity.h>

using KMail::FolderJob;

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kstringhandler.h>

#include <QList>
#include <QEventLoop>
#include <QByteArray>

#include <cstdlib>
#include <unistd.h>
#include <cerrno>

#include <cassert>

//----------------------
#include "kmaccount.moc"

//-----------------------------------------------------------------------------
KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
  : QObject( parent ), mPrecommand( precommand )
{
  BroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1", precommand ));

  mPrecommandProcess.setShellCommand(precommand);

  connect(&mPrecommandProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
          SLOT(precommandExited(int, QProcess::ExitStatus)));
}

//-----------------------------------------------------------------------------
KMPrecommand::~KMPrecommand()
{
}

//-----------------------------------------------------------------------------
bool KMPrecommand::start()
{
  mPrecommandProcess.start();
  const bool ok = mPrecommandProcess.waitForStarted();
  if ( !ok )
    KMessageBox::error( 0, i18n("Could not execute precommand '%1'.",
                        mPrecommand) );
  return ok;
}

//-----------------------------------------------------------------------------
void KMPrecommand::precommandExited(int exitCode, QProcess::ExitStatus)
{
  if (exitCode != 0)
    KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2",
       exitCode, strerror(exitCode)));
  emit finished(exitCode == 0);
}

//-----------------------------------------------------------------------------
KMAccount::KMAccount(AccountManager* aOwner, const QString& aName, uint id)
  : KAccount( id, aName ),
    mTrash(KMKernel::self()->trashFolder()->idString()),
    mOwner(aOwner),
    mFolder(0),
    mTimer(0),
    mInterval(0),
    mExclude(false),
    mCheckingMail(false),
    mPrecommandSuccess(true),
    mUseDefaultIdentity(true),
    mHasInbox(false),
    mMailCheckProgressItem(0),
    mPrecommandEventLoop( 0 )
{
  assert(aOwner != 0);
  mIdentityId = kmkernel->identityManager()->defaultIdentity().uoid();

  connect( kmkernel->identityManager(), SIGNAL( changed() ),
           this, SLOT( slotIdentitiesChanged() ) );
}

void KMAccount::init() {
  mTrash = kmkernel->trashFolder()->idString();
  mExclude = false;
  mInterval = 0;
  mNewInFolder.clear();
}

//-----------------------------------------------------------------------------
KMAccount::~KMAccount()
{
  if ( (kmkernel && !kmkernel->shuttingDown()) && mFolder ) mFolder->removeAccount(this);
  if (mTimer) deinstallTimer();
}

//-----------------------------------------------------------------------------
void KMAccount::setName(const QString& aName)
{
  mName = aName;
}

//-----------------------------------------------------------------------------
void KMAccount::clearPasswd()
{
}

//-----------------------------------------------------------------------------
void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
{
  if(!aFolder) {
    //kDebug(5006) << "aFolder == 0";
    mFolder = 0;
    return;
  }
  mFolder = (KMAcctFolder*)aFolder;
  if (addAccount) mFolder->addAccount(this);
}

//-----------------------------------------------------------------------------
void KMAccount::readConfig(KConfigGroup& config)
{
  QString folderName;
  mFolder = 0;
  folderName = config.readEntry("Folder");
  setCheckInterval(config.readEntry("check-interval", 0 ) );
  setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
  setCheckExclude(config.readEntry("check-exclude", false ) );
  setPrecommand(config.readPathEntry("precommand", QString()));

  uint defaultIdentity = kmkernel->identityManager()->defaultIdentity().uoid();
  setIdentityId( config.readEntry( "identity-id", defaultIdentity ) );
  mUseDefaultIdentity = config.readEntry( "use-default-identity", true );
  slotIdentitiesChanged();

  if ( !folderName.isEmpty() ) {
    setFolder (kmkernel->folderMgr()->findIdString( folderName ), true );
  }

  if (mInterval == 0)
    deinstallTimer();
  else
    installTimer();
}

//-----------------------------------------------------------------------------
void KMAccount::writeConfig(KConfigGroup& config)
{
  // ID, Name
  KAccount::writeConfig(config);

  config.writeEntry("Type", KAccount::nameForType( type() ) );
  config.writeEntry("Folder", mFolder ? mFolder->idString() : QString());
  config.writeEntry("check-interval", mInterval);
  config.writeEntry("check-exclude", mExclude);
  config.writePathEntry("precommand", mPrecommand);
  config.writeEntry("trash", mTrash);
  config.writeEntry( "use-default-identity", mUseDefaultIdentity );
  config.writeEntry( "identity-id", mIdentityId );
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipt(KMMessage* aMsg)
{
  bool sendReceipts;

  KConfigGroup cfg( KMKernel::config(), "General" );

  sendReceipts = cfg.readEntry("send-receipts", false );
  if (!sendReceipts) return;

  KMMessage *newMsg = aMsg->createDeliveryReceipt();
  if (newMsg) {
    mReceipts.append(newMsg);
    QTimer::singleShot( 0, this, SLOT( sendReceipts() ) );
  }
}

//-----------------------------------------------------------------------------
bool KMAccount::processNewMsg(KMMessage* aMsg)
{
  int rc, processResult;

  assert(aMsg != 0);

  // Save this one for readding
  KMFolderCachedImap* parent = 0;
  if( type() == KAccount::DImap )
    parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );

  // checks whether we should send delivery receipts
  // and sends them.
  sendReceipt(aMsg);

  // Set status of new messages that are marked as old to read, otherwise
  // the user won't see which messages newly arrived.
  // This is only valid for pop accounts and produces wrong stati for imap.
  if ( type() != KAccount::DImap && type() != KAccount::Imap ) {
    if ( aMsg->status().isOld() )
      aMsg->setStatus( MessageStatus::statusUnread() );  // -sanders
    //    aMsg->setStatus( MessageStatus::statusRead() );
    else
      aMsg->setStatus( MessageStatus::statusNew() );
  }
/*
QFile fileD0( "testdat_xx-kmaccount-0" );
if( fileD0.open( QIODevice::WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawData( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
  // 0==message moved; 1==processing ok, no move; 2==critical error, abort!

  processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound,true,id());
  if (processResult == 2) {
    perror("Critical error: Unable to collect mail (out of space?)");
    KMessageBox::information(0,(i18n("Critical error: "
      "Unable to collect mail: ")) + QString::fromLocal8Bit(strerror(errno)));
    return false;
  }
  else if (processResult == 1)
  {
    if( type() == KAccount::DImap )
      ; // already done by caller: parent->addMsgInternal( aMsg, false );
    else {
      // TODO: Perhaps it would be best, if this if was handled by a virtual
      // method, so the if( !dimap ) above could die?
      kmkernel->filterMgr()->tempOpenFolder(mFolder);
      rc = mFolder->addMsg(aMsg);
/*
QFile fileD0( "testdat_xx-kmaccount-1" );
if( fileD0.open( QIODevice::WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawData( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
      if (rc) {
        perror("failed to add message");
        KMessageBox::information(0, i18n("Failed to add message:\n") +
                                 QString(strerror(rc)));
        return false;
      }
      int count = mFolder->count();
      // If count == 1, the message is immediately displayed
      if (count != 1) mFolder->unGetMsg(count - 1);
    }
  }

  // Count number of new messages for each folder
  QString folderId;
  if ( processResult == 1 ) {
    folderId = ( type() == KAccount::DImap ) ? parent->folder()->idString()
                                             : mFolder->idString();
  }
  else {
    folderId = aMsg->parent()->idString();
  }
  addToNewInFolder( folderId, 1 );

  return true; //Everything's fine - message has been added by filter  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckInterval(int aInterval)
{
  if (aInterval <= 0)
    mInterval = 0;
  else
    mInterval = aInterval;
  // Don't call installTimer from here! See #117935.
}

int KMAccount::checkInterval() const
{
  if ( mInterval <= 0 )
    return mInterval;
  return qMax( mInterval, GlobalSettings::self()->minimumCheckInterval() );
}

//----------------------------------------------------------------------------
void KMAccount::deleteFolderJobs()
{
  qDeleteAll( mJobList );
  mJobList.clear();
}

//----------------------------------------------------------------------------
void KMAccount::ignoreJobsForMessage( KMMessage* msg )
{
  //FIXME: remove, make folders handle those
  QList<FolderJob*>::iterator it;
  for( it = mJobList.begin(); it != mJobList.end(); ++it ) {
    if ( (*it)->msgList().first() == msg) {
      FolderJob *job = (*it);
      it = mJobList.erase( it );
      delete job;
      break;
    }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckExclude(bool aExclude)
{
  mExclude = aExclude;
}

//-----------------------------------------------------------------------------
void KMAccount::installTimer()
{
  if (mInterval <= 0) return;
  if(!mTimer)
  {
    mTimer = new QTimer();
    connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
  }
  else
  {
    mTimer->stop();
  }
  mTimer->start( checkInterval() * 60000 );
}

//-----------------------------------------------------------------------------
void KMAccount::deinstallTimer()
{
  delete mTimer;
  mTimer = 0;
}

//-----------------------------------------------------------------------------
bool KMAccount::runPrecommand(const QString &precommand)
{
  // Run the pre command if there is one
  if ( precommand.isEmpty() )
    return true;

  // Don't do anything if there is a running pre-command
  if ( mPrecommandEventLoop != 0 )
    return true;

  KMPrecommand precommandProcess(precommand, this);

  BroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1", precommand ));

  connect(&precommandProcess, SIGNAL(finished(bool)),
          SLOT(precommandExited(bool)));

  kDebug(5006) <<"Running precommand" << precommand;
  if ( !precommandProcess.start() )
    return false;

  // Start an event loop. This makes sure GUI events are still processed while
  // the precommand is running (which may take a while).
  // The exec call will block until the event loop is exited, which happens in
  // precommandExited().
  mPrecommandEventLoop = new QEventLoop();
  mPrecommandEventLoop->exec();

  return mPrecommandSuccess;
}

//-----------------------------------------------------------------------------
void KMAccount::precommandExited(bool success)
{
  Q_ASSERT( mPrecommandEventLoop != 0 );
  mPrecommandSuccess = success;

  // Exit and delete the event loop. This makes sure the execution continues
  // in runPrecommand(), where the event loop was entered.
  mPrecommandEventLoop->exit();
  delete mPrecommandEventLoop;
  mPrecommandEventLoop = 0;
}

void KMAccount::slotIdentitiesChanged()
{
  // Fall back to the default identity if the one used currently is invalid
  if ( kmkernel->identityManager()->identityForUoid( mIdentityId ).isNull() ) {
    mIdentityId = kmkernel->identityManager()->defaultIdentity().uoid();
  }
}

//-----------------------------------------------------------------------------
void KMAccount::mailCheck()
{
  if (mTimer)
    mTimer->stop();

  if ( kmkernel ) {
    AccountManager *acctmgr = kmkernel->acctMgr();
    if ( acctmgr ) {
      acctmgr->singleCheckMail( this, false );
    }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipts()
{
  QList<KMMessage*>::Iterator it;
  for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
    kmkernel->msgSender()->send(*it); //might process events
  mReceipts.clear();
}

//-----------------------------------------------------------------------------
QString KMAccount::importPassword(const QString &aStr)
{
  unsigned int i, val;
  unsigned int len = aStr.length();
  QByteArray result;
  result.resize(len);

  for (i=0; i<len; i++)
  {
    val = aStr[i].toLatin1() - ' ';
    val = (255-' ') - val;
    result[i] = (char)(val + ' ');
  }
  result[i] = '\0';

  return KStringHandler::obscure(result);
}

void KMAccount::invalidateIMAPFolders()
{
  // Default: Don't do anything. The IMAP account will handle it
}

void KMAccount::pseudoAssign( const KMAccount * a ) {
  if ( !a ) return;

  setName( a->name() );
  setId( a->id() );
  setCheckInterval( a->checkInterval() );
  setCheckExclude( a->checkExclude() );
  setFolder( a->folder() );
  setPrecommand( a->precommand() );
  setTrash( a->trash() );
  setIdentityId( a->identityId() );
  setUseDefaultIdentity( a->useDefaultIdentity() );
}

//-----------------------------------------------------------------------------
void KMAccount::checkDone( bool newmail, CheckStatus status )
{
    setCheckingMail( false );
  // Reset the timeout for automatic mailchecking. The user might have
  // triggered the check manually.
  if (mTimer)
    mTimer->start( checkInterval() * 60000 );
  if ( mMailCheckProgressItem ) {
    mMailCheckProgressItem->setComplete(); // that will delete it
    mMailCheckProgressItem = 0;
  }

  emit newMailsProcessed( mNewInFolder );
  emit finishedCheck( newmail, status );
  mNewInFolder.clear();
}

uint KMAccount::identityId() const
{
  if ( mUseDefaultIdentity )
    return kmkernel->identityManager()->defaultIdentity().uoid();
  else
    return mIdentityId;
}

//-----------------------------------------------------------------------------
void KMAccount::addToNewInFolder( const QString &folderId, int num )
{
  if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
    mNewInFolder[folderId] = num;
  else
    mNewInFolder[folderId] += num;
}
<commit_msg>Backport r837489 by tmcguire to the 4.1 branch:<commit_after>// KMail Account

#include "kmaccount.h"

#include "accountmanager.h"
using KMail::AccountManager;
#include "kmacctfolder.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include "messagesender.h"
#include "kmmessage.h"
#include "broadcaststatus.h"
using KPIM::BroadcastStatus;
#include "kmfoldercachedimap.h"

#include "progressmanager.h"
using KPIM::ProgressItem;
using KPIM::ProgressManager;

#include <kpimidentities/identitymanager.h>
#include <kpimidentities/identity.h>

using KMail::FolderJob;

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kstringhandler.h>

#include <QList>
#include <QEventLoop>
#include <QByteArray>

#include <cstdlib>
#include <unistd.h>
#include <cerrno>

#include <cassert>

//----------------------
#include "kmaccount.moc"

//-----------------------------------------------------------------------------
KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
  : QObject( parent ), mPrecommand( precommand )
{
  BroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1", precommand ));

  mPrecommandProcess.setShellCommand(precommand);

  connect(&mPrecommandProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
          SLOT(precommandExited(int, QProcess::ExitStatus)));
}

//-----------------------------------------------------------------------------
KMPrecommand::~KMPrecommand()
{
}

//-----------------------------------------------------------------------------
bool KMPrecommand::start()
{
  mPrecommandProcess.start();
  const bool ok = mPrecommandProcess.waitForStarted();
  if ( !ok )
    KMessageBox::error( 0, i18n("Could not execute precommand '%1'.",
                        mPrecommand) );
  return ok;
}

//-----------------------------------------------------------------------------
void KMPrecommand::precommandExited(int exitCode, QProcess::ExitStatus)
{
  if (exitCode != 0)
    KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2",
       exitCode, strerror(exitCode)));
  emit finished(exitCode == 0);
}

//-----------------------------------------------------------------------------
KMAccount::KMAccount(AccountManager* aOwner, const QString& aName, uint id)
  : KAccount( id, aName ),
    mTrash(KMKernel::self()->trashFolder()->idString()),
    mOwner(aOwner),
    mFolder(0),
    mTimer(0),
    mInterval(0),
    mExclude(false),
    mCheckingMail(false),
    mPrecommandSuccess(true),
    mUseDefaultIdentity(true),
    mHasInbox(false),
    mMailCheckProgressItem(0),
    mPrecommandEventLoop( 0 )
{
  assert(aOwner != 0);
  mIdentityId = kmkernel->identityManager()->defaultIdentity().uoid();

  connect( kmkernel->identityManager(), SIGNAL( changed() ),
           this, SLOT( slotIdentitiesChanged() ) );
}

void KMAccount::init() {
  mTrash = kmkernel->trashFolder()->idString();
  mExclude = false;
  mInterval = 0;
  mNewInFolder.clear();
}

//-----------------------------------------------------------------------------
KMAccount::~KMAccount()
{
  if ( (kmkernel && !kmkernel->shuttingDown()) && mFolder ) mFolder->removeAccount(this);
  if (mTimer) deinstallTimer();
}

//-----------------------------------------------------------------------------
void KMAccount::setName(const QString& aName)
{
  mName = aName;
}

//-----------------------------------------------------------------------------
void KMAccount::clearPasswd()
{
}

//-----------------------------------------------------------------------------
void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
{
  if(!aFolder) {
    //kDebug(5006) << "aFolder == 0";
    mFolder = 0;
    return;
  }
  mFolder = (KMAcctFolder*)aFolder;
  if (addAccount) mFolder->addAccount(this);
}

//-----------------------------------------------------------------------------
void KMAccount::readConfig(KConfigGroup& config)
{
  QString folderName;
  mFolder = 0;
  folderName = config.readEntry("Folder");
  setCheckInterval(config.readEntry("check-interval", 0 ) );
  setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
  setCheckExclude(config.readEntry("check-exclude", false ) );
  setPrecommand(config.readPathEntry("precommand", QString()));

  uint defaultIdentity = kmkernel->identityManager()->defaultIdentity().uoid();
  setIdentityId( config.readEntry( "identity-id", defaultIdentity ) );
  mUseDefaultIdentity = config.readEntry( "use-default-identity", true );
  slotIdentitiesChanged();

  if ( !folderName.isEmpty() ) {
    setFolder (kmkernel->folderMgr()->findIdString( folderName ), true );
  }

  if (mInterval == 0)
    deinstallTimer();
  else
    installTimer();
}

//-----------------------------------------------------------------------------
void KMAccount::writeConfig(KConfigGroup& config)
{
  // ID, Name
  KAccount::writeConfig(config);

  config.writeEntry("Type", KAccount::nameForType( type() ) );
  config.writeEntry("Folder", mFolder ? mFolder->idString() : QString());
  config.writeEntry("check-interval", mInterval);
  config.writeEntry("check-exclude", mExclude);
  config.writePathEntry("precommand", mPrecommand);
  config.writeEntry("trash", mTrash);
  config.writeEntry( "use-default-identity", mUseDefaultIdentity );
  config.writeEntry( "identity-id", mIdentityId );
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipt(KMMessage* aMsg)
{
  bool sendReceipts;

  KConfigGroup cfg( KMKernel::config(), "General" );

  sendReceipts = cfg.readEntry("send-receipts", false );
  if (!sendReceipts) return;

  KMMessage *newMsg = aMsg->createDeliveryReceipt();
  if (newMsg) {
    mReceipts.append(newMsg);
    QTimer::singleShot( 0, this, SLOT( sendReceipts() ) );
  }
}

//-----------------------------------------------------------------------------
bool KMAccount::processNewMsg(KMMessage* aMsg)
{
  int rc, processResult;

  assert(aMsg != 0);

  // Save this one for readding
  KMFolderCachedImap* parent = 0;
  if( type() == KAccount::DImap )
    parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );

  // checks whether we should send delivery receipts
  // and sends them.
  sendReceipt(aMsg);

  // Set status of new messages that are marked as old to read, otherwise
  // the user won't see which messages newly arrived.
  // This is only valid for pop accounts and produces wrong stati for imap.
  if ( type() != KAccount::DImap && type() != KAccount::Imap ) {
    if ( aMsg->status().isOld() )
      aMsg->setStatus( MessageStatus::statusUnread() );  // -sanders
    //    aMsg->setStatus( MessageStatus::statusRead() );
    else
      aMsg->setStatus( MessageStatus::statusNew() );
  }
/*
QFile fileD0( "testdat_xx-kmaccount-0" );
if( fileD0.open( QIODevice::WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawData( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
  // 0==message moved; 1==processing ok, no move; 2==critical error, abort!

  processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound,true,id());
  if (processResult == 2) {
    perror("Critical error: Unable to collect mail (out of space?)");
    KMessageBox::information(0,(i18n("Critical error: "
      "Unable to collect mail: ")) + QString::fromLocal8Bit(strerror(errno)));
    return false;
  }
  else if (processResult == 1)
  {
    if( type() == KAccount::DImap )
      ; // already done by caller: parent->addMsgInternal( aMsg, false );
    else {
      // TODO: Perhaps it would be best, if this if was handled by a virtual
      // method, so the if( !dimap ) above could die?
      kmkernel->filterMgr()->tempOpenFolder(mFolder);
      rc = mFolder->addMsg(aMsg);
/*
QFile fileD0( "testdat_xx-kmaccount-1" );
if( fileD0.open( QIODevice::WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawData( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
      if (rc) {
        perror("failed to add message");
        KMessageBox::information(0, i18n("Failed to add message:\n") +
                                 QString(strerror(rc)));
        return false;
      }
      int count = mFolder->count();
      // If count == 1, the message is immediately displayed
      if (count != 1) mFolder->unGetMsg(count - 1);
    }
  }

  // Count number of new messages for each folder
  QString folderId;
  if ( processResult == 1 ) {
    folderId = ( type() == KAccount::DImap ) ? parent->folder()->idString()
                                             : mFolder->idString();
  }
  else {
    folderId = aMsg->parent()->idString();
  }
  addToNewInFolder( folderId, 1 );

  return true; //Everything's fine - message has been added by filter  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckInterval(int aInterval)
{
  if (aInterval <= 0)
    mInterval = 0;
  else
    mInterval = aInterval;
  // Don't call installTimer from here! See #117935.
}

int KMAccount::checkInterval() const
{
  if ( mInterval <= 0 )
    return mInterval;
  return qMax( mInterval, GlobalSettings::self()->minimumCheckInterval() );
}

//----------------------------------------------------------------------------
void KMAccount::deleteFolderJobs()
{
  qDeleteAll( mJobList );
  mJobList.clear();
}

//----------------------------------------------------------------------------
void KMAccount::ignoreJobsForMessage( KMMessage* msg )
{
  //FIXME: remove, make folders handle those
  QList<FolderJob*>::iterator it;
  for( it = mJobList.begin(); it != mJobList.end(); ++it ) {
    if ( (*it)->msgList().first() == msg) {
      FolderJob *job = (*it);
      it = mJobList.erase( it );
      delete job;
      break;
    }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckExclude(bool aExclude)
{
  mExclude = aExclude;
}

//-----------------------------------------------------------------------------
void KMAccount::installTimer()
{
  if (mInterval <= 0) return;
  if(!mTimer)
  {
    mTimer = new QTimer();
    connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
  }
  else
  {
    mTimer->stop();
  }
  mTimer->start( checkInterval() * 60000 );
}

//-----------------------------------------------------------------------------
void KMAccount::deinstallTimer()
{
  delete mTimer;
  mTimer = 0;
}

//-----------------------------------------------------------------------------
bool KMAccount::runPrecommand(const QString &precommand)
{
  // Run the pre command if there is one
  if ( precommand.isEmpty() )
    return true;

  // Don't do anything if there is a running pre-command
  if ( mPrecommandEventLoop != 0 )
    return true;

  KMPrecommand precommandProcess(precommand, this);

  BroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1", precommand ));

  connect(&precommandProcess, SIGNAL(finished(bool)),
          SLOT(precommandExited(bool)));

  kDebug(5006) << "Running precommand" << precommand;
  mPrecommandEventLoop = new QEventLoop();
  if ( !precommandProcess.start() )
    return false;

  // Start an event loop. This makes sure GUI events are still processed while
  // the precommand is running (which may take a while).
  // The exec call will block until the event loop is exited, which happens in
  // precommandExited().
  if ( mPrecommandEventLoop ) { // yes it can be 0 due to races with precommandProcess.start()
    mPrecommandEventLoop->exec();
  }

  return mPrecommandSuccess;
}

//-----------------------------------------------------------------------------
void KMAccount::precommandExited(bool success)
{
  Q_ASSERT( mPrecommandEventLoop != 0 );
  mPrecommandSuccess = success;

  // Exit and delete the event loop. This makes sure the execution continues
  // in runPrecommand(), where the event loop was entered.
  mPrecommandEventLoop->exit();

  // Use deleteLater, because we are called inside of this very eventloop
  mPrecommandEventLoop->deleteLater();
  mPrecommandEventLoop = 0;
}

void KMAccount::slotIdentitiesChanged()
{
  // Fall back to the default identity if the one used currently is invalid
  if ( kmkernel->identityManager()->identityForUoid( mIdentityId ).isNull() ) {
    mIdentityId = kmkernel->identityManager()->defaultIdentity().uoid();
  }
}

//-----------------------------------------------------------------------------
void KMAccount::mailCheck()
{
  if (mTimer)
    mTimer->stop();

  if ( kmkernel ) {
    AccountManager *acctmgr = kmkernel->acctMgr();
    if ( acctmgr ) {
      acctmgr->singleCheckMail( this, false );
    }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipts()
{
  QList<KMMessage*>::Iterator it;
  for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
    kmkernel->msgSender()->send(*it); //might process events
  mReceipts.clear();
}

//-----------------------------------------------------------------------------
QString KMAccount::importPassword(const QString &aStr)
{
  unsigned int i, val;
  unsigned int len = aStr.length();
  QByteArray result;
  result.resize(len);

  for (i=0; i<len; i++)
  {
    val = aStr[i].toLatin1() - ' ';
    val = (255-' ') - val;
    result[i] = (char)(val + ' ');
  }
  result[i] = '\0';

  return KStringHandler::obscure(result);
}

void KMAccount::invalidateIMAPFolders()
{
  // Default: Don't do anything. The IMAP account will handle it
}

void KMAccount::pseudoAssign( const KMAccount * a ) {
  if ( !a ) return;

  setName( a->name() );
  setId( a->id() );
  setCheckInterval( a->checkInterval() );
  setCheckExclude( a->checkExclude() );
  setFolder( a->folder() );
  setPrecommand( a->precommand() );
  setTrash( a->trash() );
  setIdentityId( a->identityId() );
  setUseDefaultIdentity( a->useDefaultIdentity() );
}

//-----------------------------------------------------------------------------
void KMAccount::checkDone( bool newmail, CheckStatus status )
{
    setCheckingMail( false );
  // Reset the timeout for automatic mailchecking. The user might have
  // triggered the check manually.
  if (mTimer)
    mTimer->start( checkInterval() * 60000 );
  if ( mMailCheckProgressItem ) {
    mMailCheckProgressItem->setComplete(); // that will delete it
    mMailCheckProgressItem = 0;
  }

  emit newMailsProcessed( mNewInFolder );
  emit finishedCheck( newmail, status );
  mNewInFolder.clear();
}

uint KMAccount::identityId() const
{
  if ( mUseDefaultIdentity )
    return kmkernel->identityManager()->defaultIdentity().uoid();
  else
    return mIdentityId;
}

//-----------------------------------------------------------------------------
void KMAccount::addToNewInFolder( const QString &folderId, int num )
{
  if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
    mNewInFolder[folderId] = num;
  else
    mNewInFolder[folderId] += num;
}
<|endoftext|>


<commit_before>// kmheaders.cpp

#include "kmfolder.h"
#include "kmheaders.h"
#include "kmcomposewin.h"
#include "kmmessage.h"
#include "kbusyptr.h"
#include "kmdragdata.h"
#include "kmglobal.h"
#include "kmmainwin.h"

#include <drag.h>
#include <qstrlist.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kapp.h>

//-----------------------------------------------------------------------------
KMHeaders::KMHeaders(KMMainWin *aOwner, QWidget *parent=0,
		     const char *name=0) :
  KMHeadersInherited(parent, name, 4)
{
  QString kdir = app->kdedir();
  KIconLoader* loader = app->getIconLoader();
  static QPixmap pixNew, pixUns, pixDel, pixOld, pixRep;

  mOwner  = aOwner;
  mFolder = NULL;
  getMsgIndex = -1;

  //setNumCols(4);
  setColumn(0, nls->translate("F"), 16, KMHeadersInherited::PixmapColumn);
  setColumn(1, nls->translate("Sender"), 200);
  setColumn(2, nls->translate("Subject"), 250);
  setColumn(3, nls->translate("Date"), 100);
  readConfig();

  pixNew = loader->loadIcon("kmmsgnew.xpm");
  pixUns = loader->loadIcon("kmmsgunseen.xpm");
  pixDel = loader->loadIcon("kmmsgdel.xpm");
  pixOld = loader->loadIcon("kmmsgold.xpm");
  pixRep = loader->loadIcon("kmmsgreplied.xpm");

  dict().insert(KMMessage::statusToStr(KMMessage::stNew), &pixNew);
  dict().insert(KMMessage::statusToStr(KMMessage::stUnread), &pixUns);
  dict().insert(KMMessage::statusToStr(KMMessage::stDeleted), &pixDel);
  dict().insert(KMMessage::statusToStr(KMMessage::stOld), &pixOld);
  dict().insert(KMMessage::statusToStr(KMMessage::stReplied), &pixRep);

  connect(this,SIGNAL(selected(int,int)),
	  this,SLOT(selectMessage(int,int)));
  connect(this,SIGNAL(highlighted(int,int)),
	  this,SLOT(highlightMessage(int,int)));
  connect(this,SIGNAL(headerClicked(int)),
	  this,SLOT(headerClicked(int)));
}

//-----------------------------------------------------------------------------
KMHeaders::~KMHeaders ()
{
  if (mFolder) mFolder->close(TRUE);
}

//-----------------------------------------------------------------------------
void KMHeaders::setFolder (KMFolder *aFolder)
{
  if (mFolder)
  {
    mFolder->close();
    disconnect(mFolder, SIGNAL(msgHeaderChanged(int)),
	       this, SLOT(msgHeaderChanged(int)));
    disconnect(mFolder, SIGNAL(msgAdded(int)),
	       this, SLOT(msgAdded(int)));
    disconnect(mFolder, SIGNAL(msgRemoved(int)),
	       this, SLOT(msgRemoved(int)));
    disconnect(mFolder, SIGNAL(changed()),
	       this, SLOT(msgChanged()));
    disconnect(mFolder, SIGNAL(statusMsg(const char*)),
	       mOwner, SLOT(statusMsg(const char*)));
  }

  mFolder = aFolder;

  if (mFolder)
  {
    connect(mFolder, SIGNAL(msgHeaderChanged(int)),
	    this, SLOT(msgHeaderChanged(int)));
    connect(mFolder, SIGNAL(msgAdded(int)),
	    this, SLOT(msgAdded(int)));
    connect(mFolder, SIGNAL(msgRemoved(int)),
	    this, SLOT(msgRemoved(int)));
    connect(mFolder, SIGNAL(changed()),
	    this, SLOT(msgChanged()));
    connect(mFolder, SIGNAL(statusMsg(const char*)),
	    mOwner, SLOT(statusMsg(const char*)));
    mFolder->open();
  }

  updateMessageList();
  //if (mFolder) setCurrentItem(0);
}

//-----------------------------------------------------------------------------
void KMHeaders::msgChanged()
{
  updateMessageList();
}

//-----------------------------------------------------------------------------
void KMHeaders::msgAdded(int id)
{
  insertItem("", id-1);
  msgHeaderChanged(id);
}

//-----------------------------------------------------------------------------
void KMHeaders::msgRemoved(int id)
{
  removeItem(id-1);
}

//-----------------------------------------------------------------------------
void KMHeaders::msgHeaderChanged(int msgId)
{
  char hdr[256];
  KMMessage::Status flag;

  flag = mFolder->msgStatus(msgId);
  sprintf(hdr, "%c\n%s\n %s\n%s", (char)flag, mFolder->msgFrom(msgId),
	  mFolder->msgSubject(msgId), mFolder->msgDate(msgId));
  changeItem(hdr, msgId-1);

  if (flag==KMMessage::stNew) changeItemColor(darkRed, msgId-1);
  else if(flag==KMMessage::stUnread) changeItemColor(darkBlue, msgId-1);
}

//-----------------------------------------------------------------------------
void KMHeaders::headerClicked(int column)
{
  KMFolder::SortField sortField;

  if (column==1)      sortField = KMFolder::sfFrom;
  else if (column==2) sortField = KMFolder::sfSubject;
  else if (column==3) sortField = KMFolder::sfDate;
  else return;

  kbp->busy();
  mFolder->sort(sortField);
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::setMsgRead (int msgId)
{
  KMMessage* msg;

  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    debug("setMsgRead(%d)", getMsgIndex);
    msg->touch();
    //changeItemPart(msg->status(), getMsgIndex, 0);
    //changeItemColor(black, getMsgIndex);
  }
}

//-----------------------------------------------------------------------------
void KMHeaders::deleteMsg (int msgId)
{
  QList<KMMessage> msgList;
  KMMessage* msg;
  int rc, num;
  int cur = currentItem();
  bool curDeleted = (cur>=0 ? isMarked(cur) : FALSE);

  kbp->busy();

  // getMsg gets confused when messages are removed while calling
  // it repeatedly. To avoid this we create a temporary list of
  // the messages that will be moved.
  for (num=0,msg=getMsg(msgId); msg; msg=getMsg(),num++)
    msgList.append(msg);

  if (num > 3)
  {
    mFolder->quiet(TRUE);
    setAutoUpdate(FALSE);
  }

  unmarkAll();

  // now it is safe to move the messages.
  for (msg=msgList.first(); msg; msg=msgList.next())
    rc = trashFolder->moveMsg(msg);

  if (num > 3)
  {
    setAutoUpdate(TRUE);
    mFolder->quiet(FALSE);
    // repaint();
  }

  // display proper message if current message was deleted.
  if (curDeleted)
  {
    if (cur >= mFolder->numMsgs()) cur = mFolder->numMsgs() - 1;
    setCurrentItem(cur, -1);
  }

  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::undeleteMsg (int msgId)
{
  KMMessage* msg;

  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    msg->undel();
    //changeItemPart(msg->status(), getMsgIndex, 0);
  }
}

//-----------------------------------------------------------------------------
void KMHeaders::toggleDeleteMsg (int msgId)
{
  KMMessage* msg;

  if (!(msg=getMsg(msgId))) return;

  if (msg->status()==KMMessage::stDeleted) undeleteMsg(msgId);
  else deleteMsg(msgId);
}

//-----------------------------------------------------------------------------
void KMHeaders::forwardMsg (int msgId)
{
  KMComposeWin *w;
  KMMessage *msg = new KMMessage();

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    w = new KMComposeWin(0, 0, 0, msg, actForward);
    w->show();
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::replyToMsg (int msgId)
{
  KMComposeWin *w;
  KMMessage *msg = new KMMessage();

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    w = new KMComposeWin(0, 0, 0, msg, actReply);
    w->show();
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::replyAllToMsg (int msgId)
{
  KMComposeWin *w;
  KMMessage *msg = new KMMessage();

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    w = new KMComposeWin(0, 0, 0, msg, actReplyAll);
    w->show();
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::moveMsgToFolder (KMFolder* destFolder, int msgId)
{
  KMMessage *msg = new KMMessage();
  int cur = currentItem();
  bool curMoved = (cur>=0 ? isMarked(cur) : FALSE);

  assert(destFolder != NULL);

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
    destFolder->moveMsg(msg);

  // display proper message if current message was deleted.
  if (curMoved)
  {
    if (cur >= mFolder->numMsgs()) cur = mFolder->numMsgs() - 1;
    setCurrentItem(cur, -1);
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
KMMessage* KMHeaders::getMsg (int msgId)
{
  int i, high;

  if (!mFolder || msgId < -2)
  {
    getMsgIndex = -1;
    return NULL;
  }
  if (msgId >= 0)
  {
    getMsgIndex = msgId;
    getMsgMulti = FALSE;
    return mFolder->getMsg(msgId+1);
  }

  if (msgId == -1)
  {
    getMsgMulti = TRUE;
    getMsgIndex = currentItem();
    for (i=0,high=numRows(); i<high; i++)
    {
      if (itemList[i]->isMarked())
      {
	getMsgIndex = i;
	break;
      }
    }

    return (getMsgIndex>=0 ? mFolder->getMsg(getMsgIndex+1) : (KMMessage*)NULL);
  }

  if (getMsgIndex < 0) return NULL;

  if (getMsgMulti) for (getMsgIndex++; getMsgIndex < numRows(); getMsgIndex++)
  {
    if (itemList[getMsgIndex]->isMarked())
      return mFolder->getMsg(getMsgIndex+1);
  }

  getMsgIndex = -1;
  return NULL;
}

//-----------------------------------------------------------------------------
void KMHeaders::nextMsg()
{
  int idx;

  kbp->busy();
  idx = indexOfGetMsg();
  if(idx < mFolder->numMsgs()-1)
  {
    emit messageSelected(mFolder->getMsg(idx+2));
    if (idx >= 0) setMsgRead(idx+1);
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::previousMsg()
{
  int idx;

  kbp->busy();
  if((idx = indexOfGetMsg()) != 0)
  {
    emit messageSelected(mFolder->getMsg(idx));
    if (idx >= 0) setMsgRead(idx);
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::changeItemPart (char c, int itemIndex, int column)
{
  char str[2];

  str[0] = c;
  str[1] = '\0';

  KMHeadersInherited::changeItemPart((const char*)str, itemIndex, column);
}

//-----------------------------------------------------------------------------
void KMHeaders::highlightMessage(int idx, int/*colId*/)
{
  if (idx >= numRows()) return;

  kbp->busy();
  mOwner->statusMsg("");
  emit messageSelected(mFolder->getMsg(idx+1));
  if (idx >= 0) setMsgRead(idx);
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::selectMessage(int idx, int/*colId*/)
{
}

//-----------------------------------------------------------------------------
void KMHeaders::updateMessageList(void)
{
  long i;
  QString hdr;
  KMMessage::Status flag;

  clear();
  if (!mFolder) return;

  kbp->busy();
  setAutoUpdate(FALSE);

  for (i=1; i<=mFolder->numMsgs(); i++)
  {
    flag = mFolder->msgStatus(i);
    hdr.sprintf("%c\n%s\n %s\n%s", (char)flag, mFolder->msgFrom(i),
	    mFolder->msgSubject(i), mFolder->msgDate(i));
    insertItem(hdr);

    if (flag==KMMessage::stNew) changeItemColor(darkRed);
    else if(flag==KMMessage::stUnread) changeItemColor(darkBlue);
  }

  setAutoUpdate(TRUE);
  repaint();

  hdr.sprintf(nls->translate("%d Messages, %d unread."),
	      mFolder->numMsgs(), mFolder->numUnreadMsgs());
  if (mFolder->isReadOnly()) hdr += nls->translate("Folder is read-only.");

  mOwner->statusMsg(hdr);
  kbp->idle();
}

//-----------------------------------------------------------------------------
bool KMHeaders :: prepareForDrag (int /*aCol*/, int /*aRow*/, char** data,
				  int* size, int* type)
{
  static KMDragData dd;
  int i, from, to, high;

  high = numRows()-1;
  for (i=0, from=-1; i<=high; i++)
  {
    if (itemList[i]->isMarked())
    {
      from = i;
      break;
    }
  }
  for (i=high-1, to=-1; i>=0; i--)
  {
    if (itemList[i]->isMarked())
    {
      to = i;
      break;
    }
  }
  if (from < 0 || to < 0) return FALSE;

  dd.init(mFolder, from, to);
  *data = (char*)ⅆ
  *size = sizeof(dd);
  *type = DndRawData;

  return TRUE;
}

//-----------------------------------------------------------------------------
#include "kmheaders.moc"
<commit_msg>Found the problem in the headers :-)) Sending has still some flaws but seems to work again somehow.<commit_after>// kmheaders.cpp

#include "kmfolder.h"
#include "kmheaders.h"
#include "kmcomposewin.h"
#include "kmmessage.h"
#include "kbusyptr.h"
#include "kmdragdata.h"
#include "kmglobal.h"
#include "kmmainwin.h"

#include <drag.h>
#include <qstrlist.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kapp.h>

//-----------------------------------------------------------------------------
KMHeaders::KMHeaders(KMMainWin *aOwner, QWidget *parent=0,
		     const char *name=0) :
  KMHeadersInherited(parent, name, 4)
{
  QString kdir = app->kdedir();
  KIconLoader* loader = app->getIconLoader();
  static QPixmap pixNew, pixUns, pixDel, pixOld, pixRep;

  mOwner  = aOwner;
  mFolder = NULL;
  getMsgIndex = -1;

  //setNumCols(4);
  setColumn(0, nls->translate("F"), 16, KMHeadersInherited::PixmapColumn);
  setColumn(1, nls->translate("Sender"), 220);
  setColumn(2, nls->translate("Subject"), 270);
  setColumn(3, nls->translate("Date"), 250);
  readConfig();

  pixNew = loader->loadIcon("kmmsgnew.xpm");
  pixUns = loader->loadIcon("kmmsgunseen.xpm");
  pixDel = loader->loadIcon("kmmsgdel.xpm");
  pixOld = loader->loadIcon("kmmsgold.xpm");
  pixRep = loader->loadIcon("kmmsgreplied.xpm");

  dict().insert(KMMessage::statusToStr(KMMessage::stNew), &pixNew);
  dict().insert(KMMessage::statusToStr(KMMessage::stUnread), &pixUns);
  dict().insert(KMMessage::statusToStr(KMMessage::stDeleted), &pixDel);
  dict().insert(KMMessage::statusToStr(KMMessage::stOld), &pixOld);
  dict().insert(KMMessage::statusToStr(KMMessage::stReplied), &pixRep);

  connect(this,SIGNAL(selected(int,int)),
	  this,SLOT(selectMessage(int,int)));
  connect(this,SIGNAL(highlighted(int,int)),
	  this,SLOT(highlightMessage(int,int)));
  connect(this,SIGNAL(headerClicked(int)),
	  this,SLOT(headerClicked(int)));
}

//-----------------------------------------------------------------------------
KMHeaders::~KMHeaders ()
{
  if (mFolder) mFolder->close(TRUE);
}

//-----------------------------------------------------------------------------
void KMHeaders::setFolder (KMFolder *aFolder)
{
  if (mFolder)
  {
    mFolder->close();
    disconnect(mFolder, SIGNAL(msgHeaderChanged(int)),
	       this, SLOT(msgHeaderChanged(int)));
    disconnect(mFolder, SIGNAL(msgAdded(int)),
	       this, SLOT(msgAdded(int)));
    disconnect(mFolder, SIGNAL(msgRemoved(int)),
	       this, SLOT(msgRemoved(int)));
    disconnect(mFolder, SIGNAL(changed()),
	       this, SLOT(msgChanged()));
    disconnect(mFolder, SIGNAL(statusMsg(const char*)),
	       mOwner, SLOT(statusMsg(const char*)));
  }

  mFolder = aFolder;

  if (mFolder)
  {
    connect(mFolder, SIGNAL(msgHeaderChanged(int)),
	    this, SLOT(msgHeaderChanged(int)));
    connect(mFolder, SIGNAL(msgAdded(int)),
	    this, SLOT(msgAdded(int)));
    connect(mFolder, SIGNAL(msgRemoved(int)),
	    this, SLOT(msgRemoved(int)));
    connect(mFolder, SIGNAL(changed()),
	    this, SLOT(msgChanged()));
    connect(mFolder, SIGNAL(statusMsg(const char*)),
	    mOwner, SLOT(statusMsg(const char*)));
    mFolder->open();
  }

  updateMessageList();
  //if (mFolder) setCurrentItem(0);
}

//-----------------------------------------------------------------------------
void KMHeaders::msgChanged()
{
  updateMessageList();
}

//-----------------------------------------------------------------------------
void KMHeaders::msgAdded(int id)
{
  insertItem("", id-1);
  msgHeaderChanged(id);
}

//-----------------------------------------------------------------------------
void KMHeaders::msgRemoved(int id)
{
  removeItem(id-1);
}

//-----------------------------------------------------------------------------
void KMHeaders::msgHeaderChanged(int msgId)
{
  char hdr[256];
  KMMessage::Status flag;

  flag = mFolder->msgStatus(msgId);
  sprintf(hdr, "%c\n%s\n %s\n%s", (char)flag, mFolder->msgFrom(msgId),
	  mFolder->msgSubject(msgId), mFolder->msgDate(msgId));
  changeItem(hdr, msgId-1);

  if (flag==KMMessage::stNew) changeItemColor(darkRed, msgId-1);
  else if(flag==KMMessage::stUnread) changeItemColor(darkBlue, msgId-1);
}

//-----------------------------------------------------------------------------
void KMHeaders::headerClicked(int column)
{
  KMFolder::SortField sortField;

  if (column==1)      sortField = KMFolder::sfFrom;
  else if (column==2) sortField = KMFolder::sfSubject;
  else if (column==3) sortField = KMFolder::sfDate;
  else return;

  kbp->busy();
  mFolder->sort(sortField);
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::setMsgRead (int msgId)
{
  KMMessage* msg;

  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    debug("setMsgRead(%d)", getMsgIndex);
    msg->touch();
    //changeItemPart(msg->status(), getMsgIndex, 0);
    //changeItemColor(black, getMsgIndex);
  }
}

//-----------------------------------------------------------------------------
void KMHeaders::deleteMsg (int msgId)
{
  moveMsgToFolder(trashFolder, msgId);
}

//-----------------------------------------------------------------------------
void KMHeaders::undeleteMsg (int msgId)
{
  KMMessage* msg;

  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    msg->undel();
    //changeItemPart(msg->status(), getMsgIndex, 0);
  }
}

//-----------------------------------------------------------------------------
void KMHeaders::toggleDeleteMsg (int msgId)
{
  KMMessage* msg;

  if (!(msg=getMsg(msgId))) return;

  if (msg->status()==KMMessage::stDeleted) undeleteMsg(msgId);
  else deleteMsg(msgId);
}

//-----------------------------------------------------------------------------
void KMHeaders::forwardMsg (int msgId)
{
  KMComposeWin *w;
  KMMessage *msg = new KMMessage();

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    w = new KMComposeWin(0, 0, 0, msg, actForward);
    w->show();
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::replyToMsg (int msgId)
{
  KMComposeWin *w;
  KMMessage *msg = new KMMessage();

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    w = new KMComposeWin(0, 0, 0, msg, actReply);
    w->show();
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::replyAllToMsg (int msgId)
{
  KMComposeWin *w;
  KMMessage *msg = new KMMessage();

  kbp->busy();
  for (msg=getMsg(msgId); msg; msg=getMsg())
  {
    w = new KMComposeWin(0, 0, 0, msg, actReplyAll);
    w->show();
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::moveMsgToFolder (KMFolder* destFolder, int msgId)
{
  QList<KMMessage> msgList;
  KMMessage* msg;
  int rc, num;
  int cur = currentItem();
  bool curMoved = (cur>=0 ? isMarked(cur) : FALSE);

  assert(destFolder != NULL);

  kbp->busy();
  // getMsg gets confused when messages are removed while calling
  // it repeatedly. To avoid this we create a temporary list of
  // the messages that will be moved.
  for (num=0,msg=getMsg(msgId); msg; msg=getMsg(),num++)
    msgList.append(msg);

  mFolder->quiet(TRUE);
  setAutoUpdate(FALSE);
  unmarkAll();

  // now it is safe to move the messages.
  for (msg=msgList.first(); msg; msg=msgList.next())
    rc = destFolder->moveMsg(msg);

  setAutoUpdate(TRUE);
  mFolder->quiet(FALSE);

  // display proper message if current message was moved.
  if (curMoved)
  {
    if (cur >= mFolder->numMsgs()) cur = mFolder->numMsgs() - 1;
    setCurrentItem(cur, -1);
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
KMMessage* KMHeaders::getMsg (int msgId)
{
  int i, high;

  if (!mFolder || msgId < -2)
  {
    getMsgIndex = -1;
    return NULL;
  }
  if (msgId >= 0)
  {
    getMsgIndex = msgId;
    getMsgMulti = FALSE;
    return mFolder->getMsg(msgId+1);
  }

  if (msgId == -1)
  {
    getMsgMulti = TRUE;
    getMsgIndex = currentItem();
    for (i=0,high=numRows(); i<high; i++)
    {
      if (itemList[i]->isMarked())
      {
	getMsgIndex = i;
	break;
      }
    }

    return (getMsgIndex>=0 ? mFolder->getMsg(getMsgIndex+1) : (KMMessage*)NULL);
  }

  if (getMsgIndex < 0) return NULL;

  if (getMsgMulti) for (getMsgIndex++; getMsgIndex < numRows(); getMsgIndex++)
  {
    if (itemList[getMsgIndex]->isMarked())
      return mFolder->getMsg(getMsgIndex+1);
  }

  getMsgIndex = -1;
  return NULL;
}

//-----------------------------------------------------------------------------
void KMHeaders::nextMsg()
{
  int idx;

  kbp->busy();
  idx = indexOfGetMsg();
  if(idx < mFolder->numMsgs()-1)
  {
    emit messageSelected(mFolder->getMsg(idx+2));
    if (idx >= 0) setMsgRead(idx+1);
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::previousMsg()
{
  int idx;

  kbp->busy();
  if((idx = indexOfGetMsg()) != 0)
  {
    emit messageSelected(mFolder->getMsg(idx));
    if (idx >= 0) setMsgRead(idx);
  }
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::changeItemPart (char c, int itemIndex, int column)
{
  char str[2];

  str[0] = c;
  str[1] = '\0';

  KMHeadersInherited::changeItemPart((const char*)str, itemIndex, column);
}

//-----------------------------------------------------------------------------
void KMHeaders::highlightMessage(int idx, int/*colId*/)
{
  if (idx >= numRows()) return;

  kbp->busy();
  mOwner->statusMsg("");
  emit messageSelected(mFolder->getMsg(idx+1));
  if (idx >= 0) setMsgRead(idx);
  kbp->idle();
}

//-----------------------------------------------------------------------------
void KMHeaders::selectMessage(int idx, int/*colId*/)
{
}

//-----------------------------------------------------------------------------
void KMHeaders::updateMessageList(void)
{
  long i;
  QString hdr;
  KMMessage::Status flag;

  clear();
  if (!mFolder) return;

  kbp->busy();
  setAutoUpdate(FALSE);

  for (i=1; i<=mFolder->numMsgs(); i++)
  {
    flag = mFolder->msgStatus(i);
    hdr.sprintf("%c\n%s\n %s\n%s", (char)flag, mFolder->msgFrom(i),
	    mFolder->msgSubject(i), mFolder->msgDate(i));
    insertItem(hdr);

    if (flag==KMMessage::stNew) changeItemColor(darkRed);
    else if(flag==KMMessage::stUnread) changeItemColor(darkBlue);
  }

  setAutoUpdate(TRUE);
  repaint();

  hdr.sprintf(nls->translate("%d Messages, %d unread."),
	      mFolder->numMsgs(), mFolder->numUnreadMsgs());
  if (mFolder->isReadOnly()) hdr += nls->translate("Folder is read-only.");

  mOwner->statusMsg(hdr);
  kbp->idle();
}

//-----------------------------------------------------------------------------
bool KMHeaders :: prepareForDrag (int /*aCol*/, int /*aRow*/, char** data,
				  int* size, int* type)
{
  static KMDragData dd;
  int i, from, to, high;

  high = numRows()-1;
  for (i=0, from=-1; i<=high; i++)
  {
    if (itemList[i]->isMarked())
    {
      from = i;
      break;
    }
  }
  for (i=high-1, to=-1; i>=0; i--)
  {
    if (itemList[i]->isMarked())
    {
      to = i;
      break;
    }
  }
  if (from < 0 || to < 0) return FALSE;

  dd.init(mFolder, from, to);
  *data = (char*)ⅆ
  *size = sizeof(dd);
  *type = DndRawData;

  return TRUE;
}

//-----------------------------------------------------------------------------
#include "kmheaders.moc"
<|endoftext|>