<commit_before>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Contributor: Lionel Duchateau, kurtnoise@free.fr
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_LA_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Audio/File_La.h"
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_La::File_La()
:File__Analyze(), File__Tags_Helper()
{
    //File__Tags_Helper
    Base=this;
}

//***************************************************************************
// Streams management
//***************************************************************************

//---------------------------------------------------------------------------
void File_La::Streams_Finish()
{
    //Filling
    int64u CompressedSize=File_Size-TagsSize;
    float32 CompressionRatio=((float32)UncompressedSize)/CompressedSize;

    Fill(Stream_Audio, 0, Audio_StreamSize, CompressedSize);
    Fill(Stream_Audio, 0, Audio_Compression_Ratio, CompressionRatio);

    File__Tags_Helper::Streams_Finish();
}

//***************************************************************************
// Buffer - File header
//***************************************************************************

//---------------------------------------------------------------------------
bool File_La::FileHeader_Begin()
{
    if (!File__Tags_Helper::FileHeader_Begin())
        return false;

    //Synchro
    if (Buffer_Offset+2>Buffer_Size)
        return false;
    if (CC3(Buffer+Buffer_Offset)!=0x4C4130) //"LA0"
    {
        File__Tags_Helper::Reject("LA");
        return false;
    }

    return true;
}

//---------------------------------------------------------------------------
void File_La::FileHeader_Parse()
{
    //Parsing
    Ztring Major, Minor;
    int32u SampleRate, Samples, BytesPerSecond, UnCompSize, WAVEChunk, FmtSize, FmtChunk, CRC32;
    int16u RawFormat, Channels, BytesPerSample, BitsPerSample;

    Skip_Local(2,                                               "signature");
    Get_Local (1, Major,                                        "major_version");
    Get_Local (1, Minor,                                        "minor_version");
    Get_L4 (UnCompSize,                                         "uncompressed_size");
    Get_L4 (WAVEChunk,                                          "chunk");
    Skip_L4(                                                    "fmt_size");
    Get_L4 (FmtChunk,                                           "fmt_chunk");
    Get_L4 (FmtSize,                                            "fmt_size");
    Get_L2 (RawFormat,                                          "raw_format");
    Get_L2 (Channels,                                           "channels"); Param_Info2(Channels, " channel(s)");
    Get_L4 (SampleRate,                                         "sample_rate");
    Get_L4 (BytesPerSecond,                                     "bytes_per_second");
    Get_L2 (BytesPerSample,                                     "bytes_per_sample");
    Get_L2 (BitsPerSample,                                      "bits_per_sample");
    Get_L4 (Samples,                                            "samples");
    Skip_L1(                                                    "flags");
    Get_L4 (CRC32,                                              "crc");

    FILLING_BEGIN();
        if (SampleRate==0)
            return;
        Duration=((int64u)Samples/Channels)*1000/SampleRate; // Seems that it's samples per channels otherwise Duration is doubled ??!!
        if (Duration==0)
            return;
        UncompressedSize=((int64u)Samples)*Channels*(BitsPerSample/8);
        if (UncompressedSize==0)
            return;

        File__Tags_Helper::Accept("LA");
        Fill(Stream_General, 0, General_Format_Version, Major+__T('.')+Minor);

        File__Tags_Helper::Stream_Prepare(Stream_Audio);
        Fill(Stream_Audio, 0, Audio_Format, "LA");
        Fill(Stream_Audio, 0, Audio_Codec, "LA");
        Fill(Stream_Audio, 0, Audio_Format_Version, Major+__T('.')+Minor);
        Fill(Stream_Audio, 0, Audio_BitDepth, BitsPerSample);
        Fill(Stream_Audio, 0, Audio_Channel_s_, Channels);
        Fill(Stream_Audio, 0, Audio_SamplingRate, SampleRate);
        Fill(Stream_Audio, 0, Audio_Duration, Duration);

        //No more need data
        File__Tags_Helper::Finish("LA");
    FILLING_END();
}

//***************************************************************************
// C++
//***************************************************************************

} //NameSpace

#endif //MEDIAINFO_LA_YES

<commit_msg>Fix floating point exception in File_La::FileHeader_Parse (SF#1151)<commit_after>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Contributor: Lionel Duchateau, kurtnoise@free.fr
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_LA_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Audio/File_La.h"
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_La::File_La()
:File__Analyze(), File__Tags_Helper()
{
    //File__Tags_Helper
    Base=this;
}

//***************************************************************************
// Streams management
//***************************************************************************

//---------------------------------------------------------------------------
void File_La::Streams_Finish()
{
    //Filling
    int64u CompressedSize=File_Size-TagsSize;
    float32 CompressionRatio=((float32)UncompressedSize)/CompressedSize;

    Fill(Stream_Audio, 0, Audio_StreamSize, CompressedSize);
    Fill(Stream_Audio, 0, Audio_Compression_Ratio, CompressionRatio);

    File__Tags_Helper::Streams_Finish();
}

//***************************************************************************
// Buffer - File header
//***************************************************************************

//---------------------------------------------------------------------------
bool File_La::FileHeader_Begin()
{
    if (!File__Tags_Helper::FileHeader_Begin())
        return false;

    //Synchro
    if (Buffer_Offset+2>Buffer_Size)
        return false;
    if (CC3(Buffer+Buffer_Offset)!=0x4C4130) //"LA0"
    {
        File__Tags_Helper::Reject("LA");
        return false;
    }

    return true;
}

//---------------------------------------------------------------------------
void File_La::FileHeader_Parse()
{
    //Parsing
    Ztring Major, Minor;
    int32u SampleRate, Samples, BytesPerSecond, UnCompSize, WAVEChunk, FmtSize, FmtChunk, CRC32;
    int16u RawFormat, Channels, BytesPerSample, BitsPerSample;

    Skip_Local(2,                                               "signature");
    Get_Local (1, Major,                                        "major_version");
    Get_Local (1, Minor,                                        "minor_version");
    Get_L4 (UnCompSize,                                         "uncompressed_size");
    Get_L4 (WAVEChunk,                                          "chunk");
    Skip_L4(                                                    "fmt_size");
    Get_L4 (FmtChunk,                                           "fmt_chunk");
    Get_L4 (FmtSize,                                            "fmt_size");
    Get_L2 (RawFormat,                                          "raw_format");
    Get_L2 (Channels,                                           "channels"); Param_Info2(Channels, " channel(s)");
    Get_L4 (SampleRate,                                         "sample_rate");
    Get_L4 (BytesPerSecond,                                     "bytes_per_second");
    Get_L2 (BytesPerSample,                                     "bytes_per_sample");
    Get_L2 (BitsPerSample,                                      "bits_per_sample");
    Get_L4 (Samples,                                            "samples");
    Skip_L1(                                                    "flags");
    Get_L4 (CRC32,                                              "crc");

    FILLING_BEGIN();
        if (SampleRate==0 || Channels==0)
            return;
        Duration=((int64u)Samples/Channels)*1000/SampleRate; // Seems that it's samples per channels otherwise Duration is doubled ??!!
        if (Duration==0)
            return;
        UncompressedSize=((int64u)Samples)*Channels*(BitsPerSample/8);
        if (UncompressedSize==0)
            return;

        File__Tags_Helper::Accept("LA");
        Fill(Stream_General, 0, General_Format_Version, Major+__T('.')+Minor);

        File__Tags_Helper::Stream_Prepare(Stream_Audio);
        Fill(Stream_Audio, 0, Audio_Format, "LA");
        Fill(Stream_Audio, 0, Audio_Codec, "LA");
        Fill(Stream_Audio, 0, Audio_Format_Version, Major+__T('.')+Minor);
        Fill(Stream_Audio, 0, Audio_BitDepth, BitsPerSample);
        Fill(Stream_Audio, 0, Audio_Channel_s_, Channels);
        Fill(Stream_Audio, 0, Audio_SamplingRate, SampleRate);
        Fill(Stream_Audio, 0, Audio_Duration, Duration);

        //No more need data
        File__Tags_Helper::Finish("LA");
    FILLING_END();
}

//***************************************************************************
// C++
//***************************************************************************

} //NameSpace

#endif //MEDIAINFO_LA_YES

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Compositor.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 of conditions 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 materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** 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
** OWNER 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."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandinputpanel.h"

#include <private/qobject_p.h>

#include "qwlinputpanel_p.h"
#include "qwlsurface_p.h"

QT_BEGIN_NAMESPACE

class QWaylandInputPanelPrivate : public QObjectPrivate
{
public:
    QWaylandInputPanelPrivate(QtWayland::InputPanel *panel)
        : inputPanel(panel)
    {
    }

    QtWayland::InputPanel *inputPanel;
};

QWaylandInputPanel::QWaylandInputPanel(QtWayland::InputPanel *inputPanel)
    : QObject(*new QWaylandInputPanelPrivate(inputPanel))
{
}

QtWayland::InputPanel *QWaylandInputPanel::handle() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel;
}

QWaylandSurface *QWaylandInputPanel::focus() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel->focus()->waylandSurface();
}

bool QWaylandInputPanel::visible() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel->inputPanelVisible();
}

QRect QWaylandInputPanel::cursorRectangle() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel->cursorRectangle();
}

QT_END_NAMESPACE
<commit_msg>QtCompositor: fix null pointer reference<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Compositor.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 of conditions 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 materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** 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
** OWNER 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."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandinputpanel.h"

#include <private/qobject_p.h>

#include "qwlinputpanel_p.h"
#include "qwlsurface_p.h"

QT_BEGIN_NAMESPACE

class QWaylandInputPanelPrivate : public QObjectPrivate
{
public:
    QWaylandInputPanelPrivate(QtWayland::InputPanel *panel)
        : inputPanel(panel)
    {
    }

    QtWayland::InputPanel *inputPanel;
};

QWaylandInputPanel::QWaylandInputPanel(QtWayland::InputPanel *inputPanel)
    : QObject(*new QWaylandInputPanelPrivate(inputPanel))
{
}

QtWayland::InputPanel *QWaylandInputPanel::handle() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel;
}

QWaylandSurface *QWaylandInputPanel::focus() const
{
    Q_D(const QWaylandInputPanel);

    QtWayland::Surface *surface = d->inputPanel->focus();
    if (surface)
        return surface->waylandSurface();
    return 0;
}

bool QWaylandInputPanel::visible() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel->inputPanelVisible();
}

QRect QWaylandInputPanel::cursorRectangle() const
{
    Q_D(const QWaylandInputPanel);

    return d->inputPanel->cursorRectangle();
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/* scraper_net.cpp */
#include <memory>
#include "net.h"
#include "rpcserver.h"
#include "rpcprotocol.h"
#include "scraper_net.h"

//Globals
std::map<uint256,CSplitBlob::CPart> CSplitBlob::mapParts;
std::map< uint256, std::unique_ptr<CScraperManifest> > CScraperManifest::mapManifest;

bool CSplitBlob::RecvPart(CNode* pfrom, CDataStream& vRecv)
{
  /* Part of larger hashed blob. Currently only used for scraper data sharing.
   * retrive parent object from mapBlobParts
   * notify object or ignore if no object found
   * erase from mapAlreadyAskedFor
  */
  auto& ss= vRecv;
  uint256 hash(Hash(ss.begin(), ss.end()));
  mapAlreadyAskedFor.erase(CInv(MSG_PART,hash));

  auto ipart= mapParts.find(hash);

  if(ipart!=mapParts.end())
  {
    CPart& part= ipart->second;
    assert(vRecv.size()>0);
    if(!part.present())
    {
      LogPrint("manifest", "received part %s %u refs", hash.GetHex(),(unsigned)part.refs.size());
      part.data= CSerializeData(vRecv.begin(),vRecv.end()); //TODO: replace with move constructor
      for( const auto& ref : part.refs )
      {
        CSplitBlob& split= *ref.first;
        ++split.cntPartsRcvd;
        assert(split.cntPartsRcvd <= split.vParts.size());
        if( split.cntPartsRcvd == split.vParts.size() )
        {
          split.Complete();
        }
      }
      return true;
    } else {
      LogPrint("manifest", "received duplicate part %s", hash.GetHex());
      return false;
    }
  } else {
    if(pfrom)  pfrom->Misbehaving(10);
    return error("Spurious part received!");
  }
}

void CSplitBlob::addPart(const uint256& ihash)
{
  assert( ihash != Hash(vParts.end(),vParts.end()) );
  unsigned n= vParts.size();
  auto rc= mapParts.emplace(ihash,CPart(ihash));
  CPart& part= rc.first->second;
  /* add to local vector */
  vParts.push_back(&part);
  if(part.present())
    cntPartsRcvd++;
  /* nature of set ensures no duplicates */
  part.refs.emplace(this, n);
}

bool CSplitBlob::addPartData(CDataStream&& vData)
{
  uint256 hash(Hash(vData.begin(), vData.end()));

  //maybe? mapAlreadyAskedFor.erase(CInv(MSG_PART,hash));

  auto it= mapParts.emplace(hash,CPart(hash));

  /* common part */
  CPart& part= it.first->second;
  unsigned n= vParts.size();
  vParts.push_back(&part);
  part.refs.emplace(this, n);

  /* check if the part already has data */
  if(!part.present())
  {
    /* missing data; use the supplied data */
    /* prevent calling the Complete callback FIXME: make this look better */
    cntPartsRcvd--;
    bool rc= CSplitBlob::RecvPart(0, vData);
    cntPartsRcvd++;
    return rc;
  }
  else return false;
}

CSplitBlob::~CSplitBlob()
{
  for(unsigned n= 0; n<vParts.size(); ++n)
  {
    CPart& part= *vParts[n];
    part.refs.erase(std::pair<CSplitBlob*,unsigned>(this,n));
    if(part.refs.empty())
      mapParts.erase(part.hash);
  }
}

void CSplitBlob::UseAsSource(CNode* pfrom)
{
  if(pfrom)
  {
    for ( const CPart* part : vParts )
    {
      if(!part->present())
      {
        /*Actually request the part. Inventory system will prevent redundant requests.*/
        pfrom->AskFor(CInv(MSG_PART, part->hash));
      }
    }
  }
}

bool CSplitBlob::SendPartTo(CNode* pto, const uint256& hash)
{
  auto ipart= mapParts.find(hash);

  if(ipart!=mapParts.end())
  {
    if(ipart->second.present())
    {
      pto->PushMessage("part",ipart->second.getReader());
      return true;
    }
  }
  return false;
}

bool CScraperManifest::AlreadyHave(CNode* pfrom, const CInv& inv)
{
  if( MSG_PART ==inv.type )
  {
    //TODO: move
    return false;
  }
  if( MSG_SCRAPERINDEX !=inv.type )
  {
    /* For any other objects, just say that we do not need it: */
    return true;
  }

  /* Inv-entory notification about scraper data index
   * see if we already have it
   * if yes, relay pfrom to Parts system as a fetch source and return true
   * else return false
  */
  auto found = mapManifest.find(inv.hash);
  if( found!=mapManifest.end() )
  {
    found->second->UseAsSource(pfrom);
    return true;
  }
  else
  {
    if(pfrom)  LogPrint("manifest", "new manifest %s from %s", inv.hash.GetHex(), pfrom->addrName);
    return false;
  }
}

void CScraperManifest::PushInvTo(CNode* pto)
{
  /* send all keys from the index map as inventory */
  /* FIXME: advertise only completed manifests */
  for (auto const& obj : mapManifest)
  {
    pto->PushInventory(CInv(MSG_SCRAPERINDEX, obj.first));
  }
}

bool CScraperManifest::SendManifestTo(CNode* pto, const uint256& hash)
{
  auto it= mapManifest.find(hash);
  if(it==mapManifest.end())
    return false;
  pto->PushMessage("scraperindex", *it->second);
  return true;
}

void CScraperManifest::Serialize(CDataStream& ss, int nType, int nVersion) const
{
  ss << testName;
  for( const CPart* part : vParts )
    ss << part->hash;
}

void CScraperManifest::UnserializeCheck(CReaderStream& ss)
{
  uint256 rh;
  ss >> testName;
  ss >> rh;
  addPart(rh);
  if(0==1)
    throw error("kek");
}

bool CScraperManifest::RecvManifest(CNode* pfrom, CDataStream& vRecv)
{
  /* Index object for scraper data.
   * deserialize message
   * hash
   * see if we do not already have it
   * validate the message
   * populate the maps
   * request parts
  */
  /* hash the object */
  uint256 hash(Hash(vRecv.begin(), vRecv.end()));
  /* see if we do not already have it */
  if( AlreadyHave(pfrom,CInv(MSG_SCRAPERINDEX, hash)) )
  {
    return error("Already have this ScraperManifest");
  }
  const auto it = mapManifest.emplace(hash,std::unique_ptr<CScraperManifest>(new CScraperManifest()));
  CScraperManifest& manifest = *it.first->second;
  manifest.phash= &it.first->first;
  try {
    //void Unserialize(Stream& s, int nType, int nVersion)
    manifest.UnserializeCheck(vRecv);
  } catch(bool& e) {
    mapManifest.erase(hash);
    LogPrint("manifest", "invalid manifest %s received", hash.GetHex());
    return false;
  } catch(std::ios_base::failure& e) {
    mapManifest.erase(hash);
    LogPrint("manifest", "invalid manifest %s received", hash.GetHex());
    return false;
  }
  LogPrint("manifest", "received manifest %s with %u / %u parts", hash.GetHex(),(unsigned)manifest.cntPartsRcvd,(unsigned)manifest.vParts.size());
  if( manifest.cntPartsRcvd == manifest.vParts.size() )
  {
    /* If we already got all the parts in memory, signal completition */
    manifest.Complete();
  } else {
    /* else request missing parts from the sender */
    manifest.UseAsSource(pfrom);
  }
  return true;
}

bool CScraperManifest::addManifest(std::unique_ptr<CScraperManifest>&& m)
{
  /* serialize and hash the object */
  CDataStream ss(SER_NETWORK,1);
  ss << *m;
#if 1
  LogPrint("manifest", "adding new local manifest");
  /* at this point it is easier to pretent like it was received from network */
  return CScraperManifest::RecvManifest(0, ss);
#else
  uint256 hash(Hash(ss.begin(),ss.end()));
  /* try inserting into map */
  const auto it = mapManifest.emplace(hash,m);
  /* Already exists, do nothing */
  if(it.second==false)
    return false;

  CScraperManifest& manifest = *it.first->second;
  /* set the hash pointer inside */
  manifest.phash= &it.first->first;

  /* TODO: call Complete or PushInventory, which is better? */
  return true;
#endif
}

void CScraperManifest::Complete()
{
  /* Notify peers that we have a new manifest */
  LogPrint("manifest", "manifest %s complete with %u parts", phash->GetHex(),(unsigned)vParts.size());
  {
    LOCK(cs_vNodes);
    for (auto const& pnode : vNodes)
      pnode->PushInventory(CInv{MSG_SCRAPERINDEX, *phash});
  }

  /* Do something with the complete manifest */
  std::string bodystr;
  vParts[0]->getReader() >> bodystr;
  printf("CScraperManifest::Complete(): %s %s\n",testName.c_str(),bodystr.c_str());
}

/* how?
 * Should we only request objects that we need?
 * Because nodes should only have valid data, download anything they send.
 * They should only send what we requested, but we do not know what it is,
 * until we have it, let it pass.
 * There is 32MiB message size limit. There is a chance we could hit it, so
 * splitting is necesssary. Index object with list of parts is needed.
 *
 * If inv about index is received, and we do not know about it yet, just
 * getdata it. If it turns out useless, just ban the node. Then getdata the
 * parts from the node.
*/

UniValue CScraperManifest::ToJson() const
{
  UniValue result(UniValue::VOBJ);
  result.pushKV("testName",testName);
  UniValue parts(UniValue::VARR);
  for( const CPart* part : vParts )
    parts.push_back(part->hash.GetHex());
  result.pushKV("parts",parts);
  return result;
}

UniValue listmanifests(const UniValue& params, bool fHelp)
{
  if(fHelp || params.size() != 0 )
    throw std::runtime_error(
        "listmanifests\n"
        "Show detailed list of known ScraperManifest objects.\n"
    );
  UniValue result1(UniValue::VOBJ);
  for(const auto& pair : CScraperManifest::mapManifest)
  {
    const uint256& hash= pair.first;
    const CScraperManifest& manifest= *pair.second;
    result1.pushKV(hash.GetHex(),manifest.ToJson());
  }
  return result1;
}

UniValue getmpart(const UniValue& params, bool fHelp)
{
  if(fHelp || params.size() != 1 )
    throw std::runtime_error(
        "getmpart <hash>\n"
        "Show content of CPart object.\n"
    );
  auto ipart= CSplitBlob::mapParts.find(uint256(params[0].get_str()));
  if(ipart == CSplitBlob::mapParts.end())
    throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Object not found");
  return UniValue(std::string(ipart->second.data.begin(),ipart->second.data.end()));
}

UniValue sendmanifest(const UniValue& params, bool fHelp)
{
  if(fHelp || params.size() != 1 )
    throw std::runtime_error(
        "sendmanifest <test>\n"
        "Send a new CScraperManifest object.\n"
    );
  auto manifest=  std::unique_ptr<CScraperManifest>(new CScraperManifest());
  manifest->testName= params[0].get_str();
  CDataStream part(SER_NETWORK,1);
  part << std::string("SampleText") << rand();
  manifest->addPartData(std::move(part));
  CScraperManifest::addManifest(std::move(manifest));
  return UniValue(true);
}
<commit_msg>Add misbehaving on invalid manifest.<commit_after>/* scraper_net.cpp */
#include <memory>
#include "net.h"
#include "rpcserver.h"
#include "rpcprotocol.h"
#include "scraper_net.h"

//Globals
std::map<uint256,CSplitBlob::CPart> CSplitBlob::mapParts;
std::map< uint256, std::unique_ptr<CScraperManifest> > CScraperManifest::mapManifest;

bool CSplitBlob::RecvPart(CNode* pfrom, CDataStream& vRecv)
{
  /* Part of larger hashed blob. Currently only used for scraper data sharing.
   * retrive parent object from mapBlobParts
   * notify object or ignore if no object found
   * erase from mapAlreadyAskedFor
  */
  auto& ss= vRecv;
  uint256 hash(Hash(ss.begin(), ss.end()));
  mapAlreadyAskedFor.erase(CInv(MSG_PART,hash));

  auto ipart= mapParts.find(hash);

  if(ipart!=mapParts.end())
  {
    CPart& part= ipart->second;
    assert(vRecv.size()>0);
    if(!part.present())
    {
      LogPrint("manifest", "received part %s %u refs", hash.GetHex(),(unsigned)part.refs.size());
      part.data= CSerializeData(vRecv.begin(),vRecv.end()); //TODO: replace with move constructor
      for( const auto& ref : part.refs )
      {
        CSplitBlob& split= *ref.first;
        ++split.cntPartsRcvd;
        assert(split.cntPartsRcvd <= split.vParts.size());
        if( split.cntPartsRcvd == split.vParts.size() )
        {
          split.Complete();
        }
      }
      return true;
    } else {
      LogPrint("manifest", "received duplicate part %s", hash.GetHex());
      return false;
    }
  } else {
    if(pfrom)  pfrom->Misbehaving(10);
    return error("Spurious part received!");
  }
}

void CSplitBlob::addPart(const uint256& ihash)
{
  assert( ihash != Hash(vParts.end(),vParts.end()) );
  unsigned n= vParts.size();
  auto rc= mapParts.emplace(ihash,CPart(ihash));
  CPart& part= rc.first->second;
  /* add to local vector */
  vParts.push_back(&part);
  if(part.present())
    cntPartsRcvd++;
  /* nature of set ensures no duplicates */
  part.refs.emplace(this, n);
}

bool CSplitBlob::addPartData(CDataStream&& vData)
{
  uint256 hash(Hash(vData.begin(), vData.end()));

  //maybe? mapAlreadyAskedFor.erase(CInv(MSG_PART,hash));

  auto it= mapParts.emplace(hash,CPart(hash));

  /* common part */
  CPart& part= it.first->second;
  unsigned n= vParts.size();
  vParts.push_back(&part);
  part.refs.emplace(this, n);

  /* check if the part already has data */
  if(!part.present())
  {
    /* missing data; use the supplied data */
    /* prevent calling the Complete callback FIXME: make this look better */
    cntPartsRcvd--;
    bool rc= CSplitBlob::RecvPart(0, vData);
    cntPartsRcvd++;
    return rc;
  }
  else return false;
}

CSplitBlob::~CSplitBlob()
{
  for(unsigned n= 0; n<vParts.size(); ++n)
  {
    CPart& part= *vParts[n];
    part.refs.erase(std::pair<CSplitBlob*,unsigned>(this,n));
    if(part.refs.empty())
      mapParts.erase(part.hash);
  }
}

void CSplitBlob::UseAsSource(CNode* pfrom)
{
  if(pfrom)
  {
    for ( const CPart* part : vParts )
    {
      if(!part->present())
      {
        /*Actually request the part. Inventory system will prevent redundant requests.*/
        pfrom->AskFor(CInv(MSG_PART, part->hash));
      }
    }
  }
}

bool CSplitBlob::SendPartTo(CNode* pto, const uint256& hash)
{
  auto ipart= mapParts.find(hash);

  if(ipart!=mapParts.end())
  {
    if(ipart->second.present())
    {
      pto->PushMessage("part",ipart->second.getReader());
      return true;
    }
  }
  return false;
}

bool CScraperManifest::AlreadyHave(CNode* pfrom, const CInv& inv)
{
  if( MSG_PART ==inv.type )
  {
    //TODO: move
    return false;
  }
  if( MSG_SCRAPERINDEX !=inv.type )
  {
    /* For any other objects, just say that we do not need it: */
    return true;
  }

  /* Inv-entory notification about scraper data index
   * see if we already have it
   * if yes, relay pfrom to Parts system as a fetch source and return true
   * else return false
  */
  auto found = mapManifest.find(inv.hash);
  if( found!=mapManifest.end() )
  {
    found->second->UseAsSource(pfrom);
    return true;
  }
  else
  {
    if(pfrom)  LogPrint("manifest", "new manifest %s from %s", inv.hash.GetHex(), pfrom->addrName);
    return false;
  }
}

void CScraperManifest::PushInvTo(CNode* pto)
{
  /* send all keys from the index map as inventory */
  /* FIXME: advertise only completed manifests */
  for (auto const& obj : mapManifest)
  {
    pto->PushInventory(CInv(MSG_SCRAPERINDEX, obj.first));
  }
}

bool CScraperManifest::SendManifestTo(CNode* pto, const uint256& hash)
{
  auto it= mapManifest.find(hash);
  if(it==mapManifest.end())
    return false;
  pto->PushMessage("scraperindex", *it->second);
  return true;
}

void CScraperManifest::Serialize(CDataStream& ss, int nType, int nVersion) const
{
  ss << testName;
  for( const CPart* part : vParts )
    ss << part->hash;
}

void CScraperManifest::UnserializeCheck(CReaderStream& ss)
{
  uint256 rh;
  ss >> testName;
  ss >> rh;
  addPart(rh);
  if(0==1)
    throw error("kek");
}

bool CScraperManifest::RecvManifest(CNode* pfrom, CDataStream& vRecv)
{
  /* Index object for scraper data.
   * deserialize message
   * hash
   * see if we do not already have it
   * validate the message
   * populate the maps
   * request parts
  */
  /* hash the object */
  uint256 hash(Hash(vRecv.begin(), vRecv.end()));
  /* see if we do not already have it */
  if( AlreadyHave(pfrom,CInv(MSG_SCRAPERINDEX, hash)) )
  {
    return error("Already have this ScraperManifest");
  }
  const auto it = mapManifest.emplace(hash,std::unique_ptr<CScraperManifest>(new CScraperManifest()));
  CScraperManifest& manifest = *it.first->second;
  manifest.phash= &it.first->first;
  try {
    //void Unserialize(Stream& s, int nType, int nVersion)
    manifest.UnserializeCheck(vRecv);
  } catch(bool& e) {
    mapManifest.erase(hash);
    LogPrint("manifest", "invalid manifest %s received", hash.GetHex());
    if(pfrom)  pfrom->Misbehaving(50);
    return false;
  } catch(std::ios_base::failure& e) {
    mapManifest.erase(hash);
    LogPrint("manifest", "invalid manifest %s received", hash.GetHex());
    if(pfrom)  pfrom->Misbehaving(50);
    return false;
  }
  LogPrint("manifest", "received manifest %s with %u / %u parts", hash.GetHex(),(unsigned)manifest.cntPartsRcvd,(unsigned)manifest.vParts.size());
  if( manifest.cntPartsRcvd == manifest.vParts.size() )
  {
    /* If we already got all the parts in memory, signal completition */
    manifest.Complete();
  } else {
    /* else request missing parts from the sender */
    manifest.UseAsSource(pfrom);
  }
  return true;
}

bool CScraperManifest::addManifest(std::unique_ptr<CScraperManifest>&& m)
{
  /* serialize and hash the object */
  CDataStream ss(SER_NETWORK,1);
  ss << *m;
#if 1
  LogPrint("manifest", "adding new local manifest");
  /* at this point it is easier to pretent like it was received from network */
  return CScraperManifest::RecvManifest(0, ss);
#else
  uint256 hash(Hash(ss.begin(),ss.end()));
  /* try inserting into map */
  const auto it = mapManifest.emplace(hash,m);
  /* Already exists, do nothing */
  if(it.second==false)
    return false;

  CScraperManifest& manifest = *it.first->second;
  /* set the hash pointer inside */
  manifest.phash= &it.first->first;

  /* TODO: call Complete or PushInventory, which is better? */
  return true;
#endif
}

void CScraperManifest::Complete()
{
  /* Notify peers that we have a new manifest */
  LogPrint("manifest", "manifest %s complete with %u parts", phash->GetHex(),(unsigned)vParts.size());
  {
    LOCK(cs_vNodes);
    for (auto const& pnode : vNodes)
      pnode->PushInventory(CInv{MSG_SCRAPERINDEX, *phash});
  }

  /* Do something with the complete manifest */
  std::string bodystr;
  vParts[0]->getReader() >> bodystr;
  printf("CScraperManifest::Complete(): %s %s\n",testName.c_str(),bodystr.c_str());
}

/* how?
 * Should we only request objects that we need?
 * Because nodes should only have valid data, download anything they send.
 * They should only send what we requested, but we do not know what it is,
 * until we have it, let it pass.
 * There is 32MiB message size limit. There is a chance we could hit it, so
 * splitting is necesssary. Index object with list of parts is needed.
 *
 * If inv about index is received, and we do not know about it yet, just
 * getdata it. If it turns out useless, just ban the node. Then getdata the
 * parts from the node.
*/

UniValue CScraperManifest::ToJson() const
{
  UniValue result(UniValue::VOBJ);
  result.pushKV("testName",testName);
  UniValue parts(UniValue::VARR);
  for( const CPart* part : vParts )
    parts.push_back(part->hash.GetHex());
  result.pushKV("parts",parts);
  return result;
}

UniValue listmanifests(const UniValue& params, bool fHelp)
{
  if(fHelp || params.size() != 0 )
    throw std::runtime_error(
        "listmanifests\n"
        "Show detailed list of known ScraperManifest objects.\n"
    );
  UniValue result1(UniValue::VOBJ);
  for(const auto& pair : CScraperManifest::mapManifest)
  {
    const uint256& hash= pair.first;
    const CScraperManifest& manifest= *pair.second;
    result1.pushKV(hash.GetHex(),manifest.ToJson());
  }
  return result1;
}

UniValue getmpart(const UniValue& params, bool fHelp)
{
  if(fHelp || params.size() != 1 )
    throw std::runtime_error(
        "getmpart <hash>\n"
        "Show content of CPart object.\n"
    );
  auto ipart= CSplitBlob::mapParts.find(uint256(params[0].get_str()));
  if(ipart == CSplitBlob::mapParts.end())
    throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Object not found");
  return UniValue(std::string(ipart->second.data.begin(),ipart->second.data.end()));
}

UniValue sendmanifest(const UniValue& params, bool fHelp)
{
  if(fHelp || params.size() != 1 )
    throw std::runtime_error(
        "sendmanifest <test>\n"
        "Send a new CScraperManifest object.\n"
    );
  auto manifest=  std::unique_ptr<CScraperManifest>(new CScraperManifest());
  manifest->testName= params[0].get_str();
  CDataStream part(SER_NETWORK,1);
  part << std::string("SampleText") << rand();
  manifest->addPartData(std::move(part));
  CScraperManifest::addManifest(std::move(manifest));
  return UniValue(true);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "script/sign.h"

#include "key.h"
#include "keystore.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "script/standard.h"
#include "uint256.h"

typedef std::vector<unsigned char> valtype;

TransactionSignatureCreator::TransactionSignatureCreator(
    const CKeyStore *keystoreIn, const CTransaction *txToIn, unsigned int nInIn,
    const CAmount &amountIn, uint32_t nHashTypeIn)
    : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn),
      amount(amountIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountIn) {}

bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char> &vchSig,
                                            const CKeyID &address,
                                            const CScript &scriptCode) const {
    CKey key;
    if (!keystore->GetKey(address, key)) return false;

    uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount);
    if (!key.Sign(hash, vchSig)) return false;
    vchSig.push_back((unsigned char)nHashType);
    return true;
}

static bool Sign1(const CKeyID &address, const BaseSignatureCreator &creator,
                  const CScript &scriptCode, std::vector<valtype> &ret) {
    std::vector<unsigned char> vchSig;
    if (!creator.CreateSig(vchSig, address, scriptCode)) return false;
    ret.push_back(vchSig);
    return true;
}

static bool SignN(const std::vector<valtype> &multisigdata,
                  const BaseSignatureCreator &creator,
                  const CScript &scriptCode, std::vector<valtype> &ret) {
    int nSigned = 0;
    int nRequired = multisigdata.front()[0];
    for (unsigned int i = 1; i < multisigdata.size() - 1 && nSigned < nRequired;
         i++) {
        const valtype &pubkey = multisigdata[i];
        CKeyID keyID = CPubKey(pubkey).GetID();
        if (Sign1(keyID, creator, scriptCode, ret)) ++nSigned;
    }
    return nSigned == nRequired;
}

/**
 * Sign scriptPubKey using signature made with creator.
 * Signatures are returned in scriptSigRet (or returns false if scriptPubKey
 * can't be signed), unless whichTypeRet is TX_SCRIPTHASH, in which case
 * scriptSigRet is the redemption script.
 * Returns false if scriptPubKey could not be completely satisfied.
 */
static bool SignStep(const BaseSignatureCreator &creator,
                     const CScript &scriptPubKey, std::vector<valtype> &ret,
                     txnouttype &whichTypeRet) {
    CScript scriptRet;
    uint160 h160;
    ret.clear();

    std::vector<valtype> vSolutions;
    if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) return false;

    CKeyID keyID;
    switch (whichTypeRet) {
        case TX_NONSTANDARD:
        case TX_NULL_DATA:
            return false;
        case TX_PUBKEY:
            keyID = CPubKey(vSolutions[0]).GetID();
            return Sign1(keyID, creator, scriptPubKey, ret);
        case TX_PUBKEYHASH:
            keyID = CKeyID(uint160(vSolutions[0]));
            if (!Sign1(keyID, creator, scriptPubKey, ret))
                return false;
            else {
                CPubKey vch;
                creator.KeyStore().GetPubKey(keyID, vch);
                ret.push_back(ToByteVector(vch));
            }
            return true;
        case TX_SCRIPTHASH:
            if (creator.KeyStore().GetCScript(uint160(vSolutions[0]),
                                              scriptRet)) {
                ret.push_back(std::vector<unsigned char>(scriptRet.begin(),
                                                         scriptRet.end()));
                return true;
            }
            return false;

        case TX_MULTISIG:
            // workaround CHECKMULTISIG bug
            ret.push_back(valtype());
            return (SignN(vSolutions, creator, scriptPubKey, ret));

        default:
            return false;
    }
}

static CScript PushAll(const std::vector<valtype> &values) {
    CScript result;
    for (const valtype &v : values) {
        if (v.size() == 0) {
            result << OP_0;
        } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
            result << CScript::EncodeOP_N(v[0]);
        } else {
            result << v;
        }
    }
    return result;
}

bool ProduceSignature(const BaseSignatureCreator &creator,
                      const CScript &fromPubKey, SignatureData &sigdata) {
    CScript script = fromPubKey;
    bool solved = true;
    std::vector<valtype> result;
    txnouttype whichType;
    solved = SignStep(creator, script, result, whichType);
    CScript subscript;

    if (solved && whichType == TX_SCRIPTHASH) {
        // Solver returns the subscript that needs to be evaluated; the final
        // scriptSig is the signatures from that and then the serialized
        // subscript:
        script = subscript = CScript(result[0].begin(), result[0].end());
        solved = solved && SignStep(creator, script, result, whichType) &&
                 whichType != TX_SCRIPTHASH;
        result.push_back(
            std::vector<unsigned char>(subscript.begin(), subscript.end()));
    }

    sigdata.scriptSig = PushAll(result);

    // Test solution
    return solved &&
           VerifyScript(sigdata.scriptSig, fromPubKey,
                        STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
}

SignatureData DataFromTransaction(const CMutableTransaction &tx,
                                  unsigned int nIn) {
    SignatureData data;
    assert(tx.vin.size() > nIn);
    data.scriptSig = tx.vin[nIn].scriptSig;
    return data;
}

void UpdateTransaction(CMutableTransaction &tx, unsigned int nIn,
                       const SignatureData &data) {
    assert(tx.vin.size() > nIn);
    tx.vin[nIn].scriptSig = data.scriptSig;
}

bool SignSignature(const CKeyStore &keystore, const CScript &fromPubKey,
                   CMutableTransaction &txTo, unsigned int nIn,
                   const CAmount &amount, uint32_t nHashType) {
    assert(nIn < txTo.vin.size());

    CTransaction txToConst(txTo);
    TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount,
                                        nHashType);

    SignatureData sigdata;
    bool ret = ProduceSignature(creator, fromPubKey, sigdata);
    UpdateTransaction(txTo, nIn, sigdata);
    return ret;
}

bool SignSignature(const CKeyStore &keystore, const CTransaction &txFrom,
                   CMutableTransaction &txTo, unsigned int nIn,
                   uint32_t nHashType) {
    assert(nIn < txTo.vin.size());
    CTxIn &txin = txTo.vin[nIn];
    assert(txin.prevout.n < txFrom.vout.size());
    const CTxOut &txout = txFrom.vout[txin.prevout.n];

    return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue,
                         nHashType);
}

static std::vector<valtype> CombineMultisig(
    const CScript &scriptPubKey, const BaseSignatureChecker &checker,
    const std::vector<valtype> &vSolutions, const std::vector<valtype> &sigs1,
    const std::vector<valtype> &sigs2) {
    // Combine all the signatures we've got:
    std::set<valtype> allsigs;
    for (const valtype &v : sigs1) {
        if (!v.empty()) allsigs.insert(v);
    }
    for (const valtype &v : sigs2) {
        if (!v.empty()) allsigs.insert(v);
    }

    // Build a map of pubkey -> signature by matching sigs to pubkeys:
    assert(vSolutions.size() > 1);
    unsigned int nSigsRequired = vSolutions.front()[0];
    unsigned int nPubKeys = vSolutions.size() - 2;
    std::map<valtype, valtype> sigs;
    for (const valtype &sig : allsigs) {
        for (unsigned int i = 0; i < nPubKeys; i++) {
            const valtype &pubkey = vSolutions[i + 1];
            // Already got a sig for this pubkey
            if (sigs.count(pubkey)) continue;

            if (checker.CheckSig(sig, pubkey, scriptPubKey)) {
                sigs[pubkey] = sig;
                break;
            }
        }
    }
    // Now build a merged CScript:
    unsigned int nSigsHave = 0;
    // pop-one-too-many workaround
    std::vector<valtype> result;
    result.push_back(valtype());
    for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++) {
        if (sigs.count(vSolutions[i + 1])) {
            result.push_back(sigs[vSolutions[i + 1]]);
            ++nSigsHave;
        }
    }
    // Fill any missing with OP_0:
    for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
        result.push_back(valtype());

    return result;
}

namespace {
struct Stacks {
    std::vector<valtype> script;

    Stacks() {}
    explicit Stacks(const std::vector<valtype> &scriptSigStack_)
        : script(scriptSigStack_) {}
    explicit Stacks(const SignatureData &data) {
        EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC,
                   BaseSignatureChecker());
    }

    SignatureData Output() const {
        SignatureData result;
        result.scriptSig = PushAll(script);
        return result;
    }
};
}

static Stacks CombineSignatures(const CScript &scriptPubKey,
                                const BaseSignatureChecker &checker,
                                const txnouttype txType,
                                const std::vector<valtype> &vSolutions,
                                Stacks sigs1, Stacks sigs2) {
    switch (txType) {
        case TX_NONSTANDARD:
        case TX_NULL_DATA:
            // Don't know anything about this, assume bigger one is correct:
            if (sigs1.script.size() >= sigs2.script.size()) return sigs1;
            return sigs2;
        case TX_PUBKEY:
        case TX_PUBKEYHASH:
            // Signatures are bigger than placeholders or empty scripts:
            if (sigs1.script.empty() || sigs1.script[0].empty()) return sigs2;
            return sigs1;
        case TX_SCRIPTHASH:
            if (sigs1.script.empty() || sigs1.script.back().empty())
                return sigs2;
            else if (sigs2.script.empty() || sigs2.script.back().empty())
                return sigs1;
            else {
                // Recur to combine:
                valtype spk = sigs1.script.back();
                CScript pubKey2(spk.begin(), spk.end());

                txnouttype txType2;
                std::vector<std::vector<unsigned char>> vSolutions2;
                Solver(pubKey2, txType2, vSolutions2);
                sigs1.script.pop_back();
                sigs2.script.pop_back();
                Stacks result = CombineSignatures(pubKey2, checker, txType2,
                                                  vSolutions2, sigs1, sigs2);
                result.script.push_back(spk);
                return result;
            }
        case TX_MULTISIG:
            return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions,
                                          sigs1.script, sigs2.script));
        default:
            return Stacks();
    }
}

SignatureData CombineSignatures(const CScript &scriptPubKey,
                                const BaseSignatureChecker &checker,
                                const SignatureData &scriptSig1,
                                const SignatureData &scriptSig2) {
    txnouttype txType;
    std::vector<std::vector<unsigned char>> vSolutions;
    Solver(scriptPubKey, txType, vSolutions);

    return CombineSignatures(scriptPubKey, checker, txType, vSolutions,
                             Stacks(scriptSig1), Stacks(scriptSig2))
        .Output();
}

namespace {
/** Dummy signature checker which accepts all signatures. */
class DummySignatureChecker : public BaseSignatureChecker {
public:
    DummySignatureChecker() {}

    bool CheckSig(const std::vector<unsigned char> &scriptSig,
                  const std::vector<unsigned char> &vchPubKey,
                  const CScript &scriptCode) const {
        return true;
    }
};
const DummySignatureChecker dummyChecker;
}

const BaseSignatureChecker &DummySignatureCreator::Checker() const {
    return dummyChecker;
}

bool DummySignatureCreator::CreateSig(std::vector<unsigned char> &vchSig,
                                      const CKeyID &keyid,
                                      const CScript &scriptCode) const {
    // Create a dummy signature that is a valid DER-encoding
    vchSig.assign(72, '\000');
    vchSig[0] = 0x30;
    vchSig[1] = 69;
    vchSig[2] = 0x02;
    vchSig[3] = 33;
    vchSig[4] = 0x01;
    vchSig[4 + 33] = 0x02;
    vchSig[5 + 33] = 32;
    vchSig[6 + 33] = 0x01;
    vchSig[6 + 33 + 32] = SIGHASH_ALL;
    return true;
}
<commit_msg>Various style improvements in sign.cpp<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "script/sign.h"

#include "key.h"
#include "keystore.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "script/standard.h"
#include "uint256.h"

typedef std::vector<unsigned char> valtype;

TransactionSignatureCreator::TransactionSignatureCreator(
    const CKeyStore *keystoreIn, const CTransaction *txToIn, unsigned int nInIn,
    const CAmount &amountIn, uint32_t nHashTypeIn)
    : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn),
      amount(amountIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountIn) {}

bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char> &vchSig,
                                            const CKeyID &address,
                                            const CScript &scriptCode) const {
    CKey key;
    if (!keystore->GetKey(address, key)) {
        return false;
    }

    uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount);
    if (!key.Sign(hash, vchSig)) {
        return false;
    }

    vchSig.push_back((unsigned char)nHashType);
    return true;
}

static bool Sign1(const CKeyID &address, const BaseSignatureCreator &creator,
                  const CScript &scriptCode, std::vector<valtype> &ret) {
    std::vector<unsigned char> vchSig;
    if (!creator.CreateSig(vchSig, address, scriptCode)) {
        return false;
    }

    ret.push_back(vchSig);
    return true;
}

static bool SignN(const std::vector<valtype> &multisigdata,
                  const BaseSignatureCreator &creator,
                  const CScript &scriptCode, std::vector<valtype> &ret) {
    int nSigned = 0;
    int nRequired = multisigdata.front()[0];
    for (size_t i = 1; i < multisigdata.size() - 1 && nSigned < nRequired;
         i++) {
        const valtype &pubkey = multisigdata[i];
        CKeyID keyID = CPubKey(pubkey).GetID();
        if (Sign1(keyID, creator, scriptCode, ret)) {
            ++nSigned;
        }
    }

    return nSigned == nRequired;
}

/**
 * Sign scriptPubKey using signature made with creator.
 * Signatures are returned in scriptSigRet (or returns false if scriptPubKey
 * can't be signed), unless whichTypeRet is TX_SCRIPTHASH, in which case
 * scriptSigRet is the redemption script.
 * Returns false if scriptPubKey could not be completely satisfied.
 */
static bool SignStep(const BaseSignatureCreator &creator,
                     const CScript &scriptPubKey, std::vector<valtype> &ret,
                     txnouttype &whichTypeRet) {
    CScript scriptRet;
    uint160 h160;
    ret.clear();

    std::vector<valtype> vSolutions;
    if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) {
        return false;
    }

    CKeyID keyID;
    switch (whichTypeRet) {
        case TX_NONSTANDARD:
        case TX_NULL_DATA:
            return false;
        case TX_PUBKEY:
            keyID = CPubKey(vSolutions[0]).GetID();
            return Sign1(keyID, creator, scriptPubKey, ret);
        case TX_PUBKEYHASH: {
            keyID = CKeyID(uint160(vSolutions[0]));
            if (!Sign1(keyID, creator, scriptPubKey, ret)) {
                return false;
            }

            CPubKey vch;
            creator.KeyStore().GetPubKey(keyID, vch);
            ret.push_back(ToByteVector(vch));
            return true;
        }
        case TX_SCRIPTHASH:
            if (creator.KeyStore().GetCScript(uint160(vSolutions[0]),
                                              scriptRet)) {
                ret.push_back(std::vector<unsigned char>(scriptRet.begin(),
                                                         scriptRet.end()));
                return true;
            }

            return false;

        case TX_MULTISIG:
            // workaround CHECKMULTISIG bug
            ret.push_back(valtype());
            return (SignN(vSolutions, creator, scriptPubKey, ret));

        default:
            return false;
    }
}

static CScript PushAll(const std::vector<valtype> &values) {
    CScript result;
    for (const valtype &v : values) {
        if (v.size() == 0) {
            result << OP_0;
        } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
            result << CScript::EncodeOP_N(v[0]);
        } else {
            result << v;
        }
    }

    return result;
}

bool ProduceSignature(const BaseSignatureCreator &creator,
                      const CScript &fromPubKey, SignatureData &sigdata) {
    CScript script = fromPubKey;
    bool solved = true;
    std::vector<valtype> result;
    txnouttype whichType;
    solved = SignStep(creator, script, result, whichType);
    CScript subscript;

    if (solved && whichType == TX_SCRIPTHASH) {
        // Solver returns the subscript that needs to be evaluated; the final
        // scriptSig is the signatures from that and then the serialized
        // subscript:
        script = subscript = CScript(result[0].begin(), result[0].end());
        solved = solved && SignStep(creator, script, result, whichType) &&
                 whichType != TX_SCRIPTHASH;
        result.push_back(
            std::vector<unsigned char>(subscript.begin(), subscript.end()));
    }

    sigdata.scriptSig = PushAll(result);

    // Test solution
    return solved &&
           VerifyScript(sigdata.scriptSig, fromPubKey,
                        STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
}

SignatureData DataFromTransaction(const CMutableTransaction &tx,
                                  unsigned int nIn) {
    SignatureData data;
    assert(tx.vin.size() > nIn);
    data.scriptSig = tx.vin[nIn].scriptSig;
    return data;
}

void UpdateTransaction(CMutableTransaction &tx, unsigned int nIn,
                       const SignatureData &data) {
    assert(tx.vin.size() > nIn);
    tx.vin[nIn].scriptSig = data.scriptSig;
}

bool SignSignature(const CKeyStore &keystore, const CScript &fromPubKey,
                   CMutableTransaction &txTo, unsigned int nIn,
                   const CAmount &amount, uint32_t nHashType) {
    assert(nIn < txTo.vin.size());

    CTransaction txToConst(txTo);
    TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount,
                                        nHashType);

    SignatureData sigdata;
    bool ret = ProduceSignature(creator, fromPubKey, sigdata);
    UpdateTransaction(txTo, nIn, sigdata);
    return ret;
}

bool SignSignature(const CKeyStore &keystore, const CTransaction &txFrom,
                   CMutableTransaction &txTo, unsigned int nIn,
                   uint32_t nHashType) {
    assert(nIn < txTo.vin.size());
    CTxIn &txin = txTo.vin[nIn];
    assert(txin.prevout.n < txFrom.vout.size());
    const CTxOut &txout = txFrom.vout[txin.prevout.n];

    return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue,
                         nHashType);
}

static std::vector<valtype> CombineMultisig(
    const CScript &scriptPubKey, const BaseSignatureChecker &checker,
    const std::vector<valtype> &vSolutions, const std::vector<valtype> &sigs1,
    const std::vector<valtype> &sigs2) {
    // Combine all the signatures we've got:
    std::set<valtype> allsigs;
    for (const valtype &v : sigs1) {
        if (!v.empty()) allsigs.insert(v);
    }

    for (const valtype &v : sigs2) {
        if (!v.empty()) allsigs.insert(v);
    }

    // Build a map of pubkey -> signature by matching sigs to pubkeys:
    assert(vSolutions.size() > 1);
    unsigned int nSigsRequired = vSolutions.front()[0];
    unsigned int nPubKeys = vSolutions.size() - 2;
    std::map<valtype, valtype> sigs;
    for (const valtype &sig : allsigs) {
        for (unsigned int i = 0; i < nPubKeys; i++) {
            const valtype &pubkey = vSolutions[i + 1];
            // Already got a sig for this pubkey
            if (sigs.count(pubkey)) {
                continue;
            }

            if (checker.CheckSig(sig, pubkey, scriptPubKey)) {
                sigs[pubkey] = sig;
                break;
            }
        }
    }
    // Now build a merged CScript:
    unsigned int nSigsHave = 0;
    // pop-one-too-many workaround
    std::vector<valtype> result;
    result.push_back(valtype());
    for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++) {
        if (sigs.count(vSolutions[i + 1])) {
            result.push_back(sigs[vSolutions[i + 1]]);
            ++nSigsHave;
        }
    }

    // Fill any missing with OP_0:
    for (unsigned int i = nSigsHave; i < nSigsRequired; i++) {
        result.push_back(valtype());
    }

    return result;
}

namespace {
struct Stacks {
    std::vector<valtype> script;

    Stacks() {}
    explicit Stacks(const std::vector<valtype> &scriptSigStack_)
        : script(scriptSigStack_) {}
    explicit Stacks(const SignatureData &data) {
        EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC,
                   BaseSignatureChecker());
    }

    SignatureData Output() const {
        SignatureData result;
        result.scriptSig = PushAll(script);
        return result;
    }
};
}

static Stacks CombineSignatures(const CScript &scriptPubKey,
                                const BaseSignatureChecker &checker,
                                const txnouttype txType,
                                const std::vector<valtype> &vSolutions,
                                Stacks sigs1, Stacks sigs2) {
    switch (txType) {
        case TX_NONSTANDARD:
        case TX_NULL_DATA:
            // Don't know anything about this, assume bigger one is correct:
            if (sigs1.script.size() >= sigs2.script.size()) {
                return sigs1;
            }

            return sigs2;
        case TX_PUBKEY:
        case TX_PUBKEYHASH:
            // Signatures are bigger than placeholders or empty scripts:
            if (sigs1.script.empty() || sigs1.script[0].empty()) {
                return sigs2;
            }

            return sigs1;
        case TX_SCRIPTHASH: {
            if (sigs1.script.empty() || sigs1.script.back().empty()) {
                return sigs2;
            }

            if (sigs2.script.empty() || sigs2.script.back().empty()) {
                return sigs1;
            }

            // Recur to combine:
            valtype spk = sigs1.script.back();
            CScript pubKey2(spk.begin(), spk.end());

            txnouttype txType2;
            std::vector<std::vector<unsigned char>> vSolutions2;
            Solver(pubKey2, txType2, vSolutions2);
            sigs1.script.pop_back();
            sigs2.script.pop_back();
            Stacks result = CombineSignatures(pubKey2, checker, txType2,
                                              vSolutions2, sigs1, sigs2);
            result.script.push_back(spk);
            return result;
        }
        case TX_MULTISIG:
            return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions,
                                          sigs1.script, sigs2.script));
        default:
            return Stacks();
    }
}

SignatureData CombineSignatures(const CScript &scriptPubKey,
                                const BaseSignatureChecker &checker,
                                const SignatureData &scriptSig1,
                                const SignatureData &scriptSig2) {
    txnouttype txType;
    std::vector<std::vector<unsigned char>> vSolutions;
    Solver(scriptPubKey, txType, vSolutions);

    return CombineSignatures(scriptPubKey, checker, txType, vSolutions,
                             Stacks(scriptSig1), Stacks(scriptSig2))
        .Output();
}

namespace {
/** Dummy signature checker which accepts all signatures. */
class DummySignatureChecker : public BaseSignatureChecker {
public:
    DummySignatureChecker() {}

    bool CheckSig(const std::vector<unsigned char> &scriptSig,
                  const std::vector<unsigned char> &vchPubKey,
                  const CScript &scriptCode) const {
        return true;
    }
};
const DummySignatureChecker dummyChecker;
}

const BaseSignatureChecker &DummySignatureCreator::Checker() const {
    return dummyChecker;
}

bool DummySignatureCreator::CreateSig(std::vector<unsigned char> &vchSig,
                                      const CKeyID &keyid,
                                      const CScript &scriptCode) const {
    // Create a dummy signature that is a valid DER-encoding
    vchSig.assign(72, '\000');
    vchSig[0] = 0x30;
    vchSig[1] = 69;
    vchSig[2] = 0x02;
    vchSig[3] = 33;
    vchSig[4] = 0x01;
    vchSig[4 + 33] = 0x02;
    vchSig[5 + 33] = 32;
    vchSig[6 + 33] = 0x01;
    vchSig[6 + 33 + 32] = SIGHASH_ALL;
    return true;
}
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/paint/TablePainter.h"

#include "core/paint/BoxPainter.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderBoxClipper.h"
#include "core/rendering/RenderTable.h"
#include "core/rendering/RenderTableSection.h"
#include "core/rendering/style/CollapsedBorderValue.h"

namespace blink {

void TablePainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderTable);

    LayoutPoint adjustedPaintOffset = paintOffset + m_renderTable.location();

    if (!m_renderTable.isDocumentElement()) {
        LayoutRect overflowBox = m_renderTable.visualOverflowRect();
        m_renderTable.flipForWritingMode(overflowBox);
        overflowBox.moveBy(adjustedPaintOffset);
        if (!overflowBox.intersects(paintInfo.rect))
            return;
    }

    RenderBoxClipper boxClipper(m_renderTable, paintInfo, adjustedPaintOffset, ForceContentsClip);
    paintObject(paintInfo, adjustedPaintOffset);
}

void TablePainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    PaintPhase paintPhase = paintInfo.phase;
    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && m_renderTable.hasBoxDecorationBackground() && m_renderTable.style()->visibility() == VISIBLE)
        paintBoxDecorationBackground(paintInfo, paintOffset);

    if (paintPhase == PaintPhaseMask) {
        m_renderTable.paintMask(paintInfo, paintOffset);
        return;
    }

    // We're done. We don't bother painting any children.
    if (paintPhase == PaintPhaseBlockBackground)
        return;

    // We don't paint our own background, but we do let the kids paint their backgrounds.
    if (paintPhase == PaintPhaseChildBlockBackgrounds)
        paintPhase = PaintPhaseChildBlockBackground;

    PaintInfo info(paintInfo);
    info.phase = paintPhase;
    info.updatePaintingRootForChildren(&m_renderTable);

    for (RenderObject* child = m_renderTable.firstChild(); child; child = child->nextSibling()) {
        if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
            LayoutPoint childPoint = m_renderTable.flipForWritingModeForChild(toRenderBox(child), paintOffset);
            child->paint(info, childPoint);
        }
    }

    if (m_renderTable.collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && m_renderTable.style()->visibility() == VISIBLE) {
        m_renderTable.recalcCollapsedBorders();
        // Using our cached sorted styles, we then do individual passes,
        // painting each style of border from lowest precedence to highest precedence.
        info.phase = PaintPhaseCollapsedTableBorders;
        RenderTable::CollapsedBorderValues collapsedBorders = m_renderTable.collapsedBorders();
        size_t count = collapsedBorders.size();
        for (size_t i = 0; i < count; ++i) {
            // FIXME: pass this value into children rather than storing temporarily on the RenderTable object.
            m_renderTable.setCurrentBorderValue(&collapsedBorders[i]);
            for (RenderTableSection* section = m_renderTable.bottomSection(); section; section = m_renderTable.sectionAbove(section)) {
                LayoutPoint childPoint = m_renderTable.flipForWritingModeForChild(section, paintOffset);
                section->paint(info, childPoint);
            }
        }
        m_renderTable.setCurrentBorderValue(0);
    }

    // Paint outline.
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_renderTable.style()->hasOutline() && m_renderTable.style()->visibility() == VISIBLE)
        m_renderTable.paintOutline(paintInfo, LayoutRect(paintOffset, m_renderTable.size()));
}

void TablePainter::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_renderTable))
        return;

    LayoutRect rect(paintOffset, m_renderTable.size());
    m_renderTable.subtractCaptionRect(rect);
    BoxPainter(m_renderTable).paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, rect);
}

void TablePainter::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_renderTable.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutRect rect(paintOffset, m_renderTable.size());
    m_renderTable.subtractCaptionRect(rect);

    BoxPainter(m_renderTable).paintMaskImages(paintInfo, rect);
}

} // namespace blink
<commit_msg>Add PaintCommandRecorders to TablePainter<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/paint/TablePainter.h"

#include "core/paint/BoxPainter.h"
#include "core/paint/ViewDisplayList.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderBoxClipper.h"
#include "core/rendering/RenderTable.h"
#include "core/rendering/RenderTableSection.h"
#include "core/rendering/style/CollapsedBorderValue.h"

namespace blink {

void TablePainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderTable);

    LayoutPoint adjustedPaintOffset = paintOffset + m_renderTable.location();

    if (!m_renderTable.isDocumentElement()) {
        LayoutRect overflowBox = m_renderTable.visualOverflowRect();
        m_renderTable.flipForWritingMode(overflowBox);
        overflowBox.moveBy(adjustedPaintOffset);
        if (!overflowBox.intersects(paintInfo.rect))
            return;
    }

    RenderBoxClipper boxClipper(m_renderTable, paintInfo, adjustedPaintOffset, ForceContentsClip);
    paintObject(paintInfo, adjustedPaintOffset);
}

void TablePainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    PaintPhase paintPhase = paintInfo.phase;
    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && m_renderTable.hasBoxDecorationBackground() && m_renderTable.style()->visibility() == VISIBLE)
        paintBoxDecorationBackground(paintInfo, paintOffset);

    if (paintPhase == PaintPhaseMask) {
        m_renderTable.paintMask(paintInfo, paintOffset);
        return;
    }

    // We're done. We don't bother painting any children.
    if (paintPhase == PaintPhaseBlockBackground)
        return;

    // We don't paint our own background, but we do let the kids paint their backgrounds.
    if (paintPhase == PaintPhaseChildBlockBackgrounds)
        paintPhase = PaintPhaseChildBlockBackground;

    PaintInfo info(paintInfo);
    info.phase = paintPhase;
    info.updatePaintingRootForChildren(&m_renderTable);

    for (RenderObject* child = m_renderTable.firstChild(); child; child = child->nextSibling()) {
        if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
            LayoutPoint childPoint = m_renderTable.flipForWritingModeForChild(toRenderBox(child), paintOffset);
            child->paint(info, childPoint);
        }
    }

    if (m_renderTable.collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && m_renderTable.style()->visibility() == VISIBLE) {
        m_renderTable.recalcCollapsedBorders();
        // Using our cached sorted styles, we then do individual passes,
        // painting each style of border from lowest precedence to highest precedence.
        info.phase = PaintPhaseCollapsedTableBorders;
        RenderTable::CollapsedBorderValues collapsedBorders = m_renderTable.collapsedBorders();
        size_t count = collapsedBorders.size();
        for (size_t i = 0; i < count; ++i) {
            // FIXME: pass this value into children rather than storing temporarily on the RenderTable object.
            m_renderTable.setCurrentBorderValue(&collapsedBorders[i]);
            for (RenderTableSection* section = m_renderTable.bottomSection(); section; section = m_renderTable.sectionAbove(section)) {
                LayoutPoint childPoint = m_renderTable.flipForWritingModeForChild(section, paintOffset);
                section->paint(info, childPoint);
            }
        }
        m_renderTable.setCurrentBorderValue(0);
    }

    // Paint outline.
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_renderTable.style()->hasOutline() && m_renderTable.style()->visibility() == VISIBLE)
        m_renderTable.paintOutline(paintInfo, LayoutRect(paintOffset, m_renderTable.size()));
}

void TablePainter::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_renderTable))
        return;

    LayoutRect rect(paintOffset, m_renderTable.size());
    m_renderTable.subtractCaptionRect(rect);
    PaintCommandRecorder recorder(paintInfo.context, &m_renderTable, paintInfo.phase, pixelSnappedIntRect(rect));
    BoxPainter(m_renderTable).paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, rect);
}

void TablePainter::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_renderTable.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutRect rect(paintOffset, m_renderTable.size());
    m_renderTable.subtractCaptionRect(rect);
    PaintCommandRecorder recorder(paintInfo.context, &m_renderTable, paintInfo.phase, pixelSnappedIntRect(rect));
    BoxPainter(m_renderTable).paintMaskImages(paintInfo, rect);
}

} // namespace blink
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gnujre.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-01-20 10:54:22 $
 *
 *  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 "osl/file.hxx"
#include "osl/thread.h"
#include "gnujre.hxx"
#include "util.hxx"

using namespace rtl;
using namespace std;
using namespace osl;

namespace jfw_plugin
{

Reference<VendorBase> GnuInfo::createInstance()
{
    return new GnuInfo;
}

char const* const* GnuInfo::getJavaExePaths(int * size)
{
    static char const * ar[] = {
        "gij",
        "bin/gij",
    };
    *size = sizeof (ar) / sizeof (char*);
    return ar;
}

char const* const* GnuInfo::getRuntimePaths(int * size)
{
    static char const* ar[]= {
          "/lib/libgcj.so.7",
          "/lib/libgcj.so.6"
#if 0   //unreliable
    , "/lib/libgcj.so.5"
        , "/lib/libgcj.so.4"
#endif
    };
    *size = sizeof(ar) / sizeof (char*);
    return ar;
}

bool GnuInfo::initialize(vector<pair<OUString, OUString> > props)
{
    //get java.vendor, java.version, java.home,
    //javax.accessibility.assistive_technologies from system properties

    OUString sVendor;
    typedef vector<pair<OUString, OUString> >::const_iterator it_prop;
    OUString sVendorProperty(
        RTL_CONSTASCII_USTRINGPARAM("java.vendor"));
    OUString sVersionProperty(
        RTL_CONSTASCII_USTRINGPARAM("java.version"));
    OUString sHomeProperty(
        RTL_CONSTASCII_USTRINGPARAM("java.home"));
    OUString sAccessProperty(
        RTL_CONSTASCII_USTRINGPARAM("javax.accessibility.assistive_technologies"));

    bool bVersion = false;
    bool bVendor = false;
    bool bHome = false;
    bool bAccess = false;

    typedef vector<pair<OUString, OUString> >::const_iterator it_prop;
    for (it_prop i = props.begin(); i != props.end(); i++)
    {
        if(! bVendor && sVendorProperty.equals(i->first))
        {
            m_sVendor = i->second;
            bVendor = true;
        }
        else if (!bVersion && sVersionProperty.equals(i->first))
        {
            m_sVersion = i->second;
            bVersion = true;
        }
        else if (!bHome && sHomeProperty.equals(i->first))
        {
           OUString fileURL;
           if (osl_getFileURLFromSystemPath(i->second.pData,& fileURL.pData) ==
               osl_File_E_None)
           {
               //make sure that the drive letter have all the same case
               //otherwise file:///c:/jre and file:///C:/jre produce two
               //different objects!!!
               if (makeDriveLetterSame( & fileURL))
               {
                   m_sHome = fileURL;
                   bHome = true;
               }
           }
        }
        else if (!bAccess && sAccessProperty.equals(i->first))
        {
            if (i->second.getLength() > 0)
            {
                m_bAccessibility = true;
                bAccess = true;
            }
        }
        // the javax.accessibility.xxx property may not be set. Therefore we
        //must search through all properties.

    }
    if (!bVersion || !bVendor || !bHome)
        return false;

    // init m_sRuntimeLibrary
    OSL_ASSERT(m_sHome.getLength());
    //call virtual function to get the possible paths to the runtime library.

    int size = 0;
    char const* const* arRtPaths = getRuntimePaths( & size);
    vector<OUString> libpaths = getVectorFromCharArray(arRtPaths, size);

    bool bRt = false;
    typedef vector<OUString>::const_iterator i_path;
    for(i_path ip = libpaths.begin(); ip != libpaths.end(); ip++)
    {
        //Construct an absolute path to the possible runtime
        OUString usRt= m_sHome + *ip;
        DirectoryItem item;
        if(DirectoryItem::get(usRt, item) == File::E_None)
        {
            //found runtime lib
            m_sRuntimeLibrary = usRt;
            bRt = true;
            break;
        }
    }

    if (!bRt)
    {
        m_sHome = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file:///usr"));
        for(i_path ip = libpaths.begin(); ip != libpaths.end(); ip++)
        {
            //Construct an absolute path to the possible runtime
            OUString usRt= m_sHome + *ip;
            DirectoryItem item;
            if(DirectoryItem::get(usRt, item) == File::E_None)
            {
                //found runtime lib
                m_sRuntimeLibrary = usRt;
                bRt = true;
                break;
            }
        }
    }
    if (!bRt)
        return false;

    // init m_sLD_LIBRARY_PATH
    OSL_ASSERT(m_sHome.getLength());
    size = 0;
    char const * const * arLDPaths = getLibraryPaths( & size);
    vector<OUString> ld_paths = getVectorFromCharArray(arLDPaths, size);

    char arSep[]= {SAL_PATHSEPARATOR, 0};
    OUString sPathSep= OUString::createFromAscii(arSep);
    bool bLdPath = true;
    int c = 0;
    for(i_path il = ld_paths.begin(); il != ld_paths.end(); il ++, c++)
    {
        OUString usAbsUrl= m_sHome + *il;
        // convert to system path
        OUString usSysPath;
        if(File::getSystemPathFromFileURL(usAbsUrl, usSysPath) == File::E_None)
        {

            if(c > 0)
                m_sLD_LIBRARY_PATH+= sPathSep;
            m_sLD_LIBRARY_PATH+= usSysPath;
        }
        else
        {
            bLdPath = false;
            break;
        }
    }
    if (bLdPath == false)
        return false;

    return true;
}

}
<commit_msg>INTEGRATION: CWS jw1 (1.5.12); FILE MERGED 2006/02/13 20:08:10 sparcmoz 1.5.12.1: #i53393 VendorBase::compareVersions must be overridden in derived class<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gnujre.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2006-02-28 10:30:59 $
 *
 *  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 "osl/file.hxx"
#include "osl/thread.h"
#include "gnujre.hxx"
#include "util.hxx"

using namespace rtl;
using namespace std;
using namespace osl;

namespace jfw_plugin
{

Reference<VendorBase> GnuInfo::createInstance()
{
    return new GnuInfo;
}

char const* const* GnuInfo::getJavaExePaths(int * size)
{
    static char const * ar[] = {
        "gij",
        "bin/gij",
    };
    *size = sizeof (ar) / sizeof (char*);
    return ar;
}

char const* const* GnuInfo::getRuntimePaths(int * size)
{
    static char const* ar[]= {
          "/lib/libgcj.so.7",
          "/lib/libgcj.so.6"
#if 0   //unreliable
    , "/lib/libgcj.so.5"
        , "/lib/libgcj.so.4"
#endif
    };
    *size = sizeof(ar) / sizeof (char*);
    return ar;
}

bool GnuInfo::initialize(vector<pair<OUString, OUString> > props)
{
    //get java.vendor, java.version, java.home,
    //javax.accessibility.assistive_technologies from system properties

    OUString sVendor;
    typedef vector<pair<OUString, OUString> >::const_iterator it_prop;
    OUString sVendorProperty(
        RTL_CONSTASCII_USTRINGPARAM("java.vendor"));
    OUString sVersionProperty(
        RTL_CONSTASCII_USTRINGPARAM("java.version"));
    OUString sHomeProperty(
        RTL_CONSTASCII_USTRINGPARAM("java.home"));
    OUString sAccessProperty(
        RTL_CONSTASCII_USTRINGPARAM("javax.accessibility.assistive_technologies"));

    bool bVersion = false;
    bool bVendor = false;
    bool bHome = false;
    bool bAccess = false;

    typedef vector<pair<OUString, OUString> >::const_iterator it_prop;
    for (it_prop i = props.begin(); i != props.end(); i++)
    {
        if(! bVendor && sVendorProperty.equals(i->first))
        {
            m_sVendor = i->second;
            bVendor = true;
        }
        else if (!bVersion && sVersionProperty.equals(i->first))
        {
            m_sVersion = i->second;
            bVersion = true;
        }
        else if (!bHome && sHomeProperty.equals(i->first))
        {
           OUString fileURL;
           if (osl_getFileURLFromSystemPath(i->second.pData,& fileURL.pData) ==
               osl_File_E_None)
           {
               //make sure that the drive letter have all the same case
               //otherwise file:///c:/jre and file:///C:/jre produce two
               //different objects!!!
               if (makeDriveLetterSame( & fileURL))
               {
                   m_sHome = fileURL;
                   bHome = true;
               }
           }
        }
        else if (!bAccess && sAccessProperty.equals(i->first))
        {
            if (i->second.getLength() > 0)
            {
                m_bAccessibility = true;
                bAccess = true;
            }
        }
        // the javax.accessibility.xxx property may not be set. Therefore we
        //must search through all properties.

    }
    if (!bVersion || !bVendor || !bHome)
        return false;

    // init m_sRuntimeLibrary
    OSL_ASSERT(m_sHome.getLength());
    //call virtual function to get the possible paths to the runtime library.

    int size = 0;
    char const* const* arRtPaths = getRuntimePaths( & size);
    vector<OUString> libpaths = getVectorFromCharArray(arRtPaths, size);

    bool bRt = false;
    typedef vector<OUString>::const_iterator i_path;
    for(i_path ip = libpaths.begin(); ip != libpaths.end(); ip++)
    {
        //Construct an absolute path to the possible runtime
        OUString usRt= m_sHome + *ip;
        DirectoryItem item;
        if(DirectoryItem::get(usRt, item) == File::E_None)
        {
            //found runtime lib
            m_sRuntimeLibrary = usRt;
            bRt = true;
            break;
        }
    }

    if (!bRt)
    {
        m_sHome = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file:///usr"));
        for(i_path ip = libpaths.begin(); ip != libpaths.end(); ip++)
        {
            //Construct an absolute path to the possible runtime
            OUString usRt= m_sHome + *ip;
            DirectoryItem item;
            if(DirectoryItem::get(usRt, item) == File::E_None)
            {
                //found runtime lib
                m_sRuntimeLibrary = usRt;
                bRt = true;
                break;
            }
        }
    }
    if (!bRt)
        return false;

    // init m_sLD_LIBRARY_PATH
    OSL_ASSERT(m_sHome.getLength());
    size = 0;
    char const * const * arLDPaths = getLibraryPaths( & size);
    vector<OUString> ld_paths = getVectorFromCharArray(arLDPaths, size);

    char arSep[]= {SAL_PATHSEPARATOR, 0};
    OUString sPathSep= OUString::createFromAscii(arSep);
    bool bLdPath = true;
    int c = 0;
    for(i_path il = ld_paths.begin(); il != ld_paths.end(); il ++, c++)
    {
        OUString usAbsUrl= m_sHome + *il;
        // convert to system path
        OUString usSysPath;
        if(File::getSystemPathFromFileURL(usAbsUrl, usSysPath) == File::E_None)
        {

            if(c > 0)
                m_sLD_LIBRARY_PATH+= sPathSep;
            m_sLD_LIBRARY_PATH+= usSysPath;
        }
        else
        {
            bLdPath = false;
            break;
        }
    }
    if (bLdPath == false)
        return false;

    return true;
}

int GnuInfo::compareVersions(const rtl::OUString& sSecond) const
{
    return 0;
}

}
<|endoftext|>