void CharArrayBufferTest::testCompareTo() {

    // compare to self
    CPPUNIT_ASSERT( 0 == testBuffer1->compareTo( *testBuffer1 ) );

    CPPUNIT_ASSERT( testBuffer1->capacity() > SMALL_TEST_LENGTH );
    testBuffer1->clear();
    CharBuffer* other = CharBuffer::allocate( testBuffer1->capacity() );

    for( int ix = 0; ix < testData1Size; ++ix ){
        testBuffer1->put( ix, testData1[ix] );
    }

    for( int ix = 0; ix < testData1Size; ++ix ){
        other->put( ix, testData1[ix] );
    }

    CPPUNIT_ASSERT( 0 == testBuffer1->compareTo( *other ) );
    CPPUNIT_ASSERT( 0 == other->compareTo( *testBuffer1 ) );
    testBuffer1->position(1);
    CPPUNIT_ASSERT( testBuffer1->compareTo( *other ) > 0 );
    CPPUNIT_ASSERT( other->compareTo( *testBuffer1 ) < 0 );
    other->position( 2 );
    CPPUNIT_ASSERT( testBuffer1->compareTo( *other ) < 0 );
    CPPUNIT_ASSERT( other->compareTo( *testBuffer1 ) > 0 );
    testBuffer1->position( 2 );
    other->limit(SMALL_TEST_LENGTH);
    CPPUNIT_ASSERT( testBuffer1->compareTo( *other ) > 0 );
    CPPUNIT_ASSERT( other->compareTo( *testBuffer1 ) < 0 );

    char* data = new char[21];
    memset( data, 0, 21 );
    CharBuffer* empty = CharBuffer::allocate(21);
    CharBuffer* wrapped = CharBuffer::wrap( data, 21, 0, 21 );

    CPPUNIT_ASSERT( wrapped->compareTo( *empty ) == 0 );

    delete empty;
    delete wrapped;
    delete other;
    delete [] data;
}
Ejemplo n.º 2
0
CFURLRef createCFURLFromBuffer(const CharBuffer& buffer)
{
    // NOTE: We use UTF-8 here since this encoding is used when computing strings when returning URL components
    // (e.g calls to NSURL -path). However, this function is not tolerant of illegal UTF-8 sequences, which
    // could either be a malformed string or bytes in a different encoding, like Shift-JIS, so we fall back
    // onto using ISO Latin-1 in those cases.
    CFURLRef result = CFURLCreateAbsoluteURLWithBytes(0, reinterpret_cast<const UInt8*>(buffer.data()), buffer.size(), kCFStringEncodingUTF8, 0, true);
    if (!result)
        result = CFURLCreateAbsoluteURLWithBytes(0, reinterpret_cast<const UInt8*>(buffer.data()), buffer.size(), kCFStringEncodingISOLatin1, 0, true);
    return result;
}
Ejemplo n.º 3
0
void WinConsole::SetupConfigFile()
{
	// create new config-file from config template

	char commonAppDataPath[MAX_PATH];
	SHGetFolderPath(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, commonAppDataPath);

	BString<1024> filename("%s\\NZBGet\\nzbget.conf", commonAppDataPath);

	BString<1024> appDataPath("%s\\NZBGet", commonAppDataPath);
	FileSystem::CreateDirectory(appDataPath);

	BString<1024> confTemplateFilename("%s\\nzbget.conf.template", g_Options->GetAppDir());
	CopyFile(confTemplateFilename, filename, FALSE);

	// set MainDir in the config-file
	int size = 0;
	CharBuffer config;
	if (FileSystem::LoadFileIntoBuffer(filename, config, true))
	{
		const char* SIGNATURE = "MainDir=${AppDir}\\downloads";
		char* p = strstr(config, SIGNATURE);
		if (p)
		{
			DiskFile outfile;
			if (outfile.Open(filename, DiskFile::omWrite))
			{
				outfile.Write(config, p - config);
				outfile.Write("MainDir=", 8);
				outfile.Write(appDataPath, strlen(appDataPath));
				outfile.Write(p + strlen(SIGNATURE), config.Size() - 1 - (p + strlen(SIGNATURE) - config) - 1);
				outfile.Close();
			}
		}
	}

	// create default destination directory (which is not created on start automatically)
	BString<1024> completeDir("%s\\NZBGet\\complete", commonAppDataPath);
	FileSystem::CreateDirectory(completeDir);
}
void CharArrayBufferTest::testReadOnlyMap() {

    CharBuffer* cb = testBuffer1->asReadOnlyBuffer();
    MyCharSequence cs( "String" );

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a ReadOnlyBufferException",
        cb->append( 'A' ),
        ReadOnlyBufferException );

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a ReadOnlyBufferException",
        cb->append( &cs ),
        ReadOnlyBufferException );

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a ReadOnlyBufferException",
        cb->append( &cs, 1, 2 ),
        ReadOnlyBufferException );

    delete cb;
}
void CharArrayBufferTest::testAppendCharSequenceNormal() {

    CharBuffer* cb = CharBuffer::allocate(10);
    cb->put('A');
    MyCharSequence cs( "String" );

    CPPUNIT_ASSERT( cb == &( cb->append( &cs ) ) );
    cb->flip();
    CPPUNIT_ASSERT( MyCharSequence("AString").toString() == cb->toString() );
    cb->append( (const lang::CharSequence*)NULL );
    cb->flip();
    CPPUNIT_ASSERT( cb->toString() == "null" );

    delete cb;
}
void CharArrayBufferTest::testAppendCharSequenceIINormal() {

    CharBuffer* cb = CharBuffer::allocate( 10 );
    cb->put( 'A' );
    MyCharSequence cs( "String" );

    CPPUNIT_ASSERT( cb == &( cb->append( &cs, 1, 3 ) ) );
    cb->flip();
    CPPUNIT_ASSERT( "Atr" == cb->toString() );

    cb->append( (const lang::CharSequence*)NULL, 0, 1 );
    cb->flip();
    CPPUNIT_ASSERT( "n" == cb->toString() );
    delete cb;
}
Ejemplo n.º 7
0
bool RarVolume::ReadRar3File(DiskFile& file, RarBlock& block, RarFile& innerFile)
{
	innerFile.m_splitBefore = block.flags & RAR3_FILE_SPLITBEFORE;
	innerFile.m_splitAfter = block.flags & RAR3_FILE_SPLITAFTER;

	uint16 namelen;

	uint32 size;
	if (!Read32(file, &block, &size)) return false;
	innerFile.m_size = size;

	if (!Skip(file, &block, 1)) return false;
	if (!Skip(file, &block, 4)) return false;
	if (!Read32(file, &block, &innerFile.m_time)) return false;
	if (!Skip(file, &block, 2)) return false;
	if (!Read16(file, &block, &namelen)) return false;
	if (!Read32(file, &block, &innerFile.m_attr)) return false;

	if (block.flags & RAR3_FILE_ADDSIZE)
	{
		uint32 highsize;
		if (!Read32(file, &block, &highsize)) return false;
		block.trailsize += (uint64)highsize << 32;

		if (!Read32(file, &block, &highsize)) return false;
		innerFile.m_size += (uint64)highsize << 32;
	}

	if (namelen > 8192) return false; // an error
	CharBuffer name;
	name.Reserve(namelen + 1);
	if (!Read(file, &block, (char*)name, namelen)) return false;
	name[namelen] = '\0';
	innerFile.m_filename = name;
	debug("%i, %i, %s", (int)block.trailsize, (int)namelen, (const char*)name);

	return true;
}
void CharArrayBufferTest::testReadOverflow() {

    std::vector<char> buffer;
    buffer.push_back('S');
    CharBuffer* source = CharBuffer::wrap( buffer );
    CharBuffer* target = CharBuffer::allocate( 1 );

    CPPUNIT_ASSERT( 1 == source->read(target) );
    target->flip();
    CPPUNIT_ASSERT( "S" == target->toString() );
    CPPUNIT_ASSERT( 1 == source->position() );

    delete source;
    delete target;
}
Ejemplo n.º 9
0
PathName SessionImpl::GetMyProgramFile(bool canonicalized)
{
  // we do this once
  if (myProgramFile.Empty())
  {
#if defined(__APPLE__)
    CharBuffer<char> buf;
    uint32_t bufsize = buf.GetCapacity();
    if (_NSGetExecutablePath(buf.GetData(), &bufsize) < 0)
    {
      buf.Reserve(bufsize);
      if (_NSGetExecutablePath(buf.GetData(), &bufsize) != 0)
      {
        MIKTEX_UNEXPECTED();
      }
    }
    myProgramFile = buf.GetData();
#else
    string invocationName = initInfo.GetProgramInvocationName();
    if (invocationName.empty())
    {
      MIKTEX_FATAL_ERROR(T_("No invocation name has been set."));
    }
    if (Utils::IsAbsolutePath(invocationName.c_str()))
    {
      myProgramFile = invocationName;
    }
    else if (invocationName.length() > 3 && (invocationName.substr(0, 2) == "./" || invocationName.substr(0, 3) == "../"))
    {
      myProgramFile = GetFullPath(invocationName.c_str());
    }
    else if (!Utils::FindProgram(invocationName, myProgramFile))
    {
      MIKTEX_FATAL_ERROR_2(T_("The invoked program could not be found in the PATH."), "invocationName", invocationName);
    }
#endif
    myProgramFileCanon = myProgramFile;
    myProgramFileCanon.Canonicalize();
  }
  if (canonicalized)
  {
    return myProgramFileCanon;
  }
  else
  {
    return myProgramFile;
  }
}
Ejemplo n.º 10
0
String FileAccess::get_line() const {

	CharBuffer line;

	CharType c = get_8();

	while (!eof_reached()) {

		if (c == '\n' || c == '\0') {
			line.push_back(0);
			return String::utf8(line.get_data());
		} else if (c != '\r')
			line.push_back(c);

		c = get_8();
	}
	line.push_back(0);
	return String::utf8(line.get_data());
}
void CharArrayBufferTest::testEquals() {

    // equal to self
    CPPUNIT_ASSERT( testBuffer1->equals( *testBuffer1 ) );
    CharBuffer* readOnly = testBuffer1->asReadOnlyBuffer();
    CPPUNIT_ASSERT( testBuffer1->equals( *readOnly ) );
    CharBuffer* duplicate = testBuffer1->duplicate();
    CPPUNIT_ASSERT( testBuffer1->equals( *duplicate ) );

    CPPUNIT_ASSERT( testBuffer1->capacity() > SMALL_TEST_LENGTH );

    testBuffer1->limit( testBuffer1->capacity() ).position( 0 );
    readOnly->limit( readOnly->capacity() ).position( 1 );
    CPPUNIT_ASSERT( !testBuffer1->equals( *readOnly ) );

    testBuffer1->limit( testBuffer1->capacity() - 1 ).position( 0 );
    duplicate->limit( duplicate->capacity() ).position( 0 );
    CPPUNIT_ASSERT( !testBuffer1->equals( *duplicate ) );

    delete readOnly;
    delete duplicate;
}
Ejemplo n.º 12
0
void BinHTTPInputStreamCommon::createHTTPRequest(const XMLURL &urlSource, const XMLNetHTTPInfo *httpInfo, CharBuffer &buffer)
{
    static const char *GET = "GET ";
    static const char *PUT = "PUT ";
    static const char *POST = "POST ";
    static const char *HTTP10 = " HTTP/1.0\r\n";
    static const char *HOST = "Host: ";
    static const char *AUTHORIZATION = "Authorization: Basic ";
    static const char *COLON = ":";

    XMLTransService::Codes failReason;
    const XMLSize_t blockSize = 2048;

    XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor("ISO8859-1", failReason, blockSize, fMemoryManager);
    Janitor<XMLTranscoder> janTrans(trans);

    TranscodeToStr hostName(urlSource.getHost(), trans, fMemoryManager);
    TranscodeToStr path(urlSource.getPath(), trans, fMemoryManager);
    TranscodeToStr fragment(urlSource.getFragment(), trans, fMemoryManager);
    TranscodeToStr query(urlSource.getQuery(), trans, fMemoryManager);

    // Build up the http GET command to send to the server.
    // To do:  We should really support http 1.1.  This implementation
    //         is weak.
    if(httpInfo) {
        switch(httpInfo->fHTTPMethod) {
        case XMLNetHTTPInfo::GET:   buffer.append(GET); break;
        case XMLNetHTTPInfo::PUT:   buffer.append(PUT); break;
        case XMLNetHTTPInfo::POST:  buffer.append(POST); break;
        }
    }
    else {
        buffer.append(GET);
    }

    if(path.str() != 0) {
        buffer.append((char*)path.str());
    }
    else {
        buffer.append("/");
    }

    if(query.str() != 0) {
        buffer.append("?");
        buffer.append((char*)query.str());
    }

    if(fragment.str() != 0) {
        buffer.append((char*)fragment.str());
    }
    buffer.append(HTTP10);

    buffer.append(HOST);
    buffer.append((char*)hostName.str());
    if(urlSource.getPortNum() != 80)
    {
        buffer.append(COLON);
        buffer.appendDecimalNumber(urlSource.getPortNum());
    }
    buffer.append(CRLF);

    const XMLCh *username = urlSource.getUser();
    const XMLCh *password = urlSource.getPassword();
    if(username && password) {
        XMLBuffer userPassBuf(256, fMemoryManager);
        userPassBuf.append(username);
        userPassBuf.append(chColon);
        userPassBuf.append(password);

        TranscodeToStr userPass(userPassBuf.getRawBuffer(), trans, fMemoryManager);

        XMLSize_t len;
        XMLByte* encodedData = Base64::encode(userPass.str(), userPass.length(), &len, fMemoryManager);
        ArrayJanitor<XMLByte> janBuf2(encodedData, fMemoryManager);

        if(encodedData) {
            // HTTP doesn't want the 0x0A separating the data in chunks of 76 chars per line
            XMLByte* authData = (XMLByte*)fMemoryManager->allocate((len+1)*sizeof(XMLByte));
            ArrayJanitor<XMLByte> janBuf(authData, fMemoryManager);
            XMLByte *cursor = authData;
            for(XMLSize_t i = 0; i < len; ++i)
                if(encodedData[i] != chLF)
                    *cursor++ = encodedData[i];
            *cursor++ = 0;
            buffer.append(AUTHORIZATION);
            buffer.append((char*)authData);
            buffer.append(CRLF);
        }
    }

    if(httpInfo && httpInfo->fHeaders)
        buffer.append(httpInfo->fHeaders, httpInfo->fHeadersLen);

    buffer.append(CRLF);
}
Ejemplo n.º 13
0
int CLI::pollEvent(GRE::Event &ev)
{
	struct pollfd fd;
	bool food = false;
	char ch;
	int idx;
	int r;

	if (!m_enabled)
		return -1;

	idx = 0;
	do {
		fd.fd = STDIN_FILENO;
		fd.events = POLLIN | POLLRDHUP;
		fd.revents = 0;

		r = poll(&fd, 1, 0);
		if (r < 0) {
			m_enabled = false;
			return -1;
		} else if (r == 0) {
			break;
		}

		if (fd.revents & POLLRDHUP) {
			m_enabled = false;
			return -1;
		} else {
			r = read(STDIN_FILENO, &ch, 1);
			if (r == 1) {
				m_buffer->push(ch);
			} else {
				m_enabled = false;
				return -1;
			}
		}
	} while (r > 0);

	while (m_buffer->size()) {
		food = true;
		switch ((ch = m_buffer->pop())) {
		case 0xd:
		case 0x20:
			ev.type = GRE::Event::Next;
			break;
		case 'q':
			ev.type = GRE::Event::Quit;
			break;
		case 'h':
			ev.type = GRE::Event::HaltToggle;
			break;
		case 'F':
			ev.type = GRE::Event::FilterToggle;
			break;
		case 'f':
			ev.type = GRE::Event::FullscreenToggle;
			break;
		case 0x1b:
			if (m_buffer->size() < 2) {
				ev.type = GRE::Event::Quit;
				break;
			}
			if (!memcmp(m_buffer->peek(), "[C", 2)) {
				ev.type = GRE::Event::Next;
				m_buffer->pop(), m_buffer->pop();
				break;
			}
			if (!memcmp(m_buffer->peek(), "[D", 2)) {
				ev.type = GRE::Event::Prev;
				m_buffer->pop(), m_buffer->pop();
				break;
			}
			food = false;
			break;
		default:
			food = false;
			break;
		}
		if (food)
			break;
	}

	return -(food == false);
}
Ejemplo n.º 14
0
    void run() {
        // start server thread
        _myAcceptor = AcceptorPtr(new ConduitAcceptor<POLICY>(_myLocalEndpoint,
                                  myLowercaseServer<POLICY>::create));
        ENSURE(_myAcceptor->start());

        // XXX uncomment this to play with telnet
        //while (true);

        // start client
        {
            CharBuffer myInputBuffer;
            typename Conduit<POLICY>::Ptr myClient(new Conduit<POLICY>(_myLocalEndpoint));
            ENSURE(myClient);
            setSilentSuccess(true);
            for (int i = 0; i < 20; ++i) {
                myClient->sendData("HELLO",5);
                while (!myClient->receiveData(myInputBuffer)) {
                    myClient->handleIO(10);
                }
                ENSURE(myInputBuffer.size()==5);
                ENSURE(strncmp(&myInputBuffer[0],"hello",5)==0);
            }
            setSilentSuccess(false);
            // now send something, but don't pick up the reply
            myClient->sendData("GOOD BYE!",5);
        }
        msleep(100);
        // Stress Test
        setSilentSuccess(true);
        for (int i=0; i < 20; ++i) {
            CharBuffer myInputBuffer(5,0);
            typename Conduit<POLICY>::Ptr myClient(new Conduit<POLICY>(_myLocalEndpoint));
            ENSURE(myClient);
            //msleep(100);
            string myOutput("Q");
            myOutput += as_string(i);

            ENSURE(myClient->sendData(myOutput.c_str(), myOutput.length()));
            while (!myClient->receiveData(myInputBuffer)) {
                myClient->handleIO(10);
            }
            //cerr << "sent '" << myOutput << "', recv '" << &(myInputBuffer[0]) << "'" << endl;
            ENSURE(myInputBuffer.size()==myOutput.length());
            string myExpectedReply("q");
            myExpectedReply += as_string(i);
            ENSURE_MSG(strncmp(&myInputBuffer[0],myExpectedReply.c_str(),myInputBuffer.size())==0, " iterations.");
        }
        setSilentSuccess(false);
        // now start two clients simultaneously
        {
            CharBuffer myInputBuffer1;
            typename Conduit<POLICY>::Ptr myClient1(new Conduit<POLICY>(_myLocalEndpoint));
            ENSURE(myClient1);
            CharBuffer myInputBuffer2;
            typename Conduit<POLICY>::Ptr myClient2(new Conduit<POLICY>(_myLocalEndpoint));
            ENSURE(myClient2);
            myClient2->sendData("WORLD",5);
            myClient1->sendData("HELLO",5);
            bool myWaiting1 = true;
            bool myWaiting2 = true;
            while (myWaiting1 || myWaiting2) {
                if (myWaiting1 && myClient1->receiveData(myInputBuffer1)) {
                    myWaiting1 = false;
                };
                if (myWaiting2 && myClient2->receiveData(myInputBuffer2)) {
                    myWaiting2 = false;
                };
            }
            ENSURE(strncmp(&myInputBuffer1[0],"hello",5)==0);
            ENSURE(strncmp(&myInputBuffer2[0],"world",5)==0);
        }
        // how about a really big string
        {
            std::string myBigString;
            for (int i = 0; i<10000; ++i) {
                myBigString += as_string(i);
            }
            CharBuffer myInputBuffer;

            typename Conduit<POLICY>::Ptr myClient(new Conduit<POLICY>(_myLocalEndpoint));
            ENSURE(myClient);
            ENSURE(myClient->sendData(myBigString.c_str(), myBigString.length()));
            string myReceiveString;
            while (myReceiveString.length() < myBigString.length()  && myClient->isValid()) {
                if (myClient->receiveData(myInputBuffer)) {
                    myReceiveString += string(&myInputBuffer[0], myInputBuffer.size());
                }
            }
            ENSURE(myReceiveString == myBigString);
        }
        // check already-is-use behaviour
        {
            AcceptorPtr myAcceptor;
            ENSURE_EXCEPTION(myAcceptor = AcceptorPtr(new ConduitAcceptor<POLICY>(_myLocalEndpoint,
                                          myLowercaseServer<POLICY>::create)), ConduitInUseException);
        }

        // close the server (also test if the server is cancelable)
        msleep(100);
        ENSURE_MSG(_myAcceptor->stop(), "Cancelling server thread");
        msleep(100);
        _myAcceptor = AcceptorPtr(0);
    }
Ejemplo n.º 15
0
bool RarVolume::ReadRar5File(DiskFile& file, RarBlock& block, RarFile& innerFile)
{
	innerFile.m_splitBefore = block.flags & RAR5_BLOCK_SPLITBEFORE;
	innerFile.m_splitAfter = block.flags & RAR5_BLOCK_SPLITAFTER;

	uint64 val;

	uint64 fileflags;
	if (!ReadV(file, &block, &fileflags)) return false;

	if (!ReadV(file, &block, &val)) return false; // skip
	innerFile.m_size = (int64)val;

	if (!ReadV(file, &block, &val)) return false;
	innerFile.m_attr = (uint32)val;

	if (fileflags & RAR5_FILE_TIME && !Read32(file, &block, &innerFile.m_time)) return false;
	if (fileflags & RAR5_FILE_CRC && !Skip(file, &block, 4)) return false;

	if (!ReadV(file, &block, &val)) return false; // skip
	if (!ReadV(file, &block, &val)) return false; // skip

	uint64 namelen;
	if (!ReadV(file, &block, &namelen)) return false;
	if (namelen > 8192) return false; // an error
	CharBuffer name;
	name.Reserve((uint32)namelen + 1);
	if (!Read(file, &block, (char*)name, namelen)) return false;
	name[namelen] = '\0';
	innerFile.m_filename = name;

	// reading extra headers to find file time
	if (block.flags & RAR5_BLOCK_EXTRADATA)
	{
		uint64 remsize = block.addsize;
		while (remsize > 0)
		{
			uint64 trailsize = block.trailsize;

			uint64 len;
			if (!ReadV(file, &block, &len)) return false;
			remsize -= trailsize - block.trailsize + len;
			trailsize = block.trailsize;

			uint64 type;
			if (!ReadV(file, &block, &type)) return false;

			if (type == RAR5_FILE_EXTRATIME)
			{
				uint64 flags;
				if (!ReadV(file, &block, &flags)) return false;
				if (flags & RAR5_FILE_EXTRATIMEUNIXFORMAT)
				{
					if (!Read32(file, &block, &innerFile.m_time)) return false;
				}
				else
				{
					uint32 timelow, timehigh;
					if (!Read32(file, &block, &timelow)) return false;
					if (!Read32(file, &block, &timehigh)) return false;
					uint64 wintime = ((uint64)timehigh << 32) + timelow;
					innerFile.m_time = (uint32)(wintime / 10000000 - 11644473600LL);
				}
			}

			len -= trailsize - block.trailsize;

			if (!Skip(file, &block, len)) return false;
		}
	}

	debug("%llu, %i, %s", (long long)block.trailsize, (int)namelen, (const char*)name);

	return true;
}
Ejemplo n.º 16
0
void
TarExtractor::Extract (/*[in]*/ Stream *		pStreamIn_,
		       /*[in]*/ const PathName &	destDir,
		       /*[in]*/ bool			makeDirectories,
		       /*[in]*/ IExtractCallback *	pCallback,
		       /*[in]*/ const char *		lpszPrefix)
{
  try
    {
      pStreamIn = pStreamIn_;
      totalBytesRead = 0;

      traceStream->WriteFormattedLine ("libextractor",
				       T_("extracting to %s (%s)"),
				       Q_(destDir),
				       (makeDirectories
					? T_("make directories")
					: T_("don't make directories")));

      size_t len;
      Header header;
      size_t prefixLen = (lpszPrefix == 0 ? 0 : StrLen(lpszPrefix));
      unsigned fileCount = 0;
  
      bool checkHeader = true;
  
      CharBuffer<char> buffer;
      buffer.Reserve (1024 * 1024);

      while ((len = Read(&header, sizeof(header))) > 0)
	{
	  // read next header
	  if (len != sizeof(header))
	    {
	      FATAL_EXTRACTOR_ERROR
		("TarExtractor::Extract",
		 T_("Invalid package archive file."),
		 0);
	    }
      
	  if (header.IsEndOfArchive())
	    {
	      break;
	    }
      
	  if (checkHeader)
	    {
	      if (! header.Check())
		{
		  FATAL_EXTRACTOR_ERROR
		    ("TarExtractor::Extract",
		     T_("Invalid package archive file."),
		     0);
		}
#if ! defined(MIKTEX_DEBUG)
	      checkHeader = false;
#endif
	    }
      
	  PathName dest = header.GetFileName();
	  size_t size = header.GetFileSize();
      
	  if (! header.IsNormalFile())
	    {
	      if (header.GetType() == Header::LongName)
		{
		  if (size >= BLOCKSIZE)
		    {
		      UNEXPECTED_CONDITION ("TarExtractor::Extract");
		    }
		  char longNameData[BLOCKSIZE];
		  ReadBlock (longNameData);
		  longNameData[size] = 0;
		  longName = longNameData;
		  haveLongName = true;
		}
	      else
		{
		  Skip (((size + sizeof(Header) - 1) / sizeof(Header))
			* sizeof(Header));
		}
	      continue;
	    }

	  if (haveLongName)
	    {
	      dest = longName;
	      haveLongName = false;
	    }
      
	  // skip directory prefix
	  if (lpszPrefix != 0
	      && PathName::Compare(lpszPrefix, dest, prefixLen) == 0)
	    {
	      PathName tmp (dest);
	      dest = tmp.Get() + prefixLen;
	    }
      
	  // make the destination path name
	  PathName path (destDir);
	  if (! makeDirectories)
	    {
	      dest.RemoveDirectorySpec ();
	    }
	  path += dest;
      
	  // notify the client
	  if (pCallback != 0)
	    {
	      pCallback->OnBeginFileExtraction (path.Get(), size);
	    }
      
	  // create the destination directory
	  Directory::Create (PathName(path).RemoveFileSpec());
      
	  // remove the existing file
	  if (File::Exists(path))
	    {
	      File::Delete (path, true);
	    }
      
	  // extract the file
	  FileStream streamOut (File::Open(path,
					   FileMode::Create,
					   FileAccess::Write,
					   false));
	  size_t bytesRead = 0;
	  while (bytesRead < size)
	  {
	    size_t remaining = size - bytesRead;
	    size_t n = (remaining > buffer.GetCapacity() ? buffer.GetCapacity() : remaining);
	    if (Read(buffer.GetBuffer(), n) != n)
	    {
	      FATAL_EXTRACTOR_ERROR ("TarExtractor::Extract",
		T_("Invalid package archive file."),
		0);
	    }
	    streamOut.Write (buffer.Get(), n);
	    bytesRead += n;
	  }
	  streamOut.Close ();

	  // skip extra bytes
	  if (bytesRead % sizeof(Header) > 0)
	    {
	      Skip (sizeof(Header) - bytesRead % sizeof(Header));
	    }
      
	  fileCount += 1;
      
	  // set time when the file was created
	  time_t time = header.GetLastModificationTime();
	  File::SetTimes (path, time, time, time);
      
#if 0
	  // set file attributes
	  File::SetAttributes (path, todo);
#endif
      
	  // notify the client
	  if (pCallback != 0)
	    {
	      pCallback->OnEndFileExtraction (0, size);
	    }
	}
  
      traceStream->WriteFormattedLine ("libextractor",
				       T_("extracted %u file(s)"),
				       fileCount);
    }
  catch (const exception &)
    {
      traceStream->WriteFormattedLine
	("libextractor",
	 T_("%u bytes were read from the tar stream"),
	 static_cast<unsigned>(totalBytesRead));
      throw;
    }
}
void CharArrayBufferTest::testAppendSelf() {

    CharBuffer* cb = CharBuffer::allocate(10);
    CharBuffer* cb2 = cb->duplicate();

    cb->append( cb );
    CPPUNIT_ASSERT( 10 == cb->position() );
    cb->clear();
    CPPUNIT_ASSERT( cb2->equals( *cb ) );

    delete cb2;
    cb->put( "abc" );
    cb2 = cb->duplicate();
    cb->append( cb );
    CPPUNIT_ASSERT( 10 == cb->position() );
    cb->clear();
    cb2->clear();
    CPPUNIT_ASSERT( cb2->equals( *cb ) );

    delete cb2;
    cb->put( "edfg" );
    cb->clear();
    cb2 = cb->duplicate();
    cb->append( cb );
    CPPUNIT_ASSERT( 10 == cb->position() );
    cb->clear();
    cb2->clear();
    CPPUNIT_ASSERT( cb->equals( *cb2 ) );

    delete cb;
    delete cb2;
}
void CharArrayBufferTest::testSlice() {

    CPPUNIT_ASSERT( testBuffer1->capacity() > SMALL_TEST_LENGTH );
    testBuffer1->position( 1 );
    testBuffer1->limit( testBuffer1->capacity() - 1 );

    CharBuffer* slice = testBuffer1->slice();
    CPPUNIT_ASSERT( testBuffer1->isReadOnly() == slice->isReadOnly() );
    CPPUNIT_ASSERT( slice->position() == 0 );
    CPPUNIT_ASSERT( slice->limit() == testBuffer1->remaining() );
    CPPUNIT_ASSERT( slice->capacity() == testBuffer1->remaining() );

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a InvalidMarkException",
        slice->reset(),
        InvalidMarkException );

    // slice share the same content with buf
    for( int ix = 0; ix < slice->capacity(); ++ix ){
        slice->put( ix, testData1[ix] );
    }

    for( int ix = 0; ix < slice->capacity(); ix++ ) {
        CPPUNIT_ASSERT( testBuffer1->get( ix + 1 ) == slice->get( ix ) );
    }
    testBuffer1->put( 2, 100 );
    CPPUNIT_ASSERT( slice->get(1) == 100 );

    delete slice;
}
void CharArrayBufferTest::testPutCharBuffer() {

    CharBuffer* other = CharBuffer::allocate( testBuffer1->capacity() );

    CharBuffer* readOnly = testBuffer1->asReadOnlyBuffer();
    readOnly->clear();
    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a ReadOnlyBufferException",
        readOnly->put( *other ),
        ReadOnlyBufferException );
    delete readOnly;

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a IllegalArgumentException",
        testBuffer1->put( *testBuffer1 ),
        IllegalArgumentException );

    CharBuffer* toBig = testBuffer1->allocate( testBuffer1->capacity() + 1 );
    toBig->clear();
    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a BufferOverflowException",
        testBuffer1->put( *toBig ),
        BufferOverflowException );
    delete toBig;

    for( int ix = 0; ix < testData1Size; ++ix ){
        other->put( ix, testData1[ix] );
    }
    other->clear();

    testBuffer1->clear();
    CharBuffer& ret = testBuffer1->put( *other );
    CPPUNIT_ASSERT( other->position() == other->capacity() );
    CPPUNIT_ASSERT( testBuffer1->position() == testBuffer1->capacity() );
    for( int ix = 0; ix < testBuffer1->capacity() - 1; ix++ ) {
        CPPUNIT_ASSERT( testBuffer1->get( ix ) == other->get( ix ) );
    }
    CPPUNIT_ASSERT( &ret == testBuffer1 );

    delete other;
}
Ejemplo n.º 20
0
bool Frontend::RequestFileList()
{
	const char* controlIp = !strcmp(g_Options->GetControlIp(), "0.0.0.0") ? "127.0.0.1" : g_Options->GetControlIp();
	Connection connection(controlIp, g_Options->GetControlPort(), false);

	bool OK = connection.Connect();
	if (!OK)
	{
		return false;
	}

	SNzbListRequest ListRequest;
	InitMessageBase(&ListRequest.m_messageBase, rrList, sizeof(ListRequest));
	ListRequest.m_fileList = htonl(m_fileList);
	ListRequest.m_serverState = htonl(m_summary);

	if (!connection.Send((char*)(&ListRequest), sizeof(ListRequest)))
	{
		return false;
	}

	// Now listen for the returned list
	SNzbListResponse ListResponse;
	bool read = connection.Recv((char*) &ListResponse, sizeof(ListResponse));
	if (!read ||
		(int)ntohl(ListResponse.m_messageBase.m_signature) != (int)NZBMESSAGE_SIGNATURE ||
		ntohl(ListResponse.m_messageBase.m_structSize) != sizeof(ListResponse))
	{
		return false;
	}

	CharBuffer buf;
	if (ntohl(ListResponse.m_trailingDataLength) > 0)
	{
		buf.Reserve(ntohl(ListResponse.m_trailingDataLength));
		if (!connection.Recv(buf, buf.Size()))
		{
			return false;
		}
	}

	connection.Disconnect();

	if (m_summary)
	{
		m_pauseDownload = ntohl(ListResponse.m_downloadPaused);
		m_remainingSize = Util::JoinInt64(ntohl(ListResponse.m_remainingSizeHi), ntohl(ListResponse.m_remainingSizeLo));
		m_currentDownloadSpeed = ntohl(ListResponse.m_downloadRate);
		m_downloadLimit = ntohl(ListResponse.m_downloadLimit);
		m_threadCount = ntohl(ListResponse.m_threadCount);
		m_postJobCount = ntohl(ListResponse.m_postJobCount);
		m_upTimeSec = ntohl(ListResponse.m_upTimeSec);
		m_dnTimeSec = ntohl(ListResponse.m_downloadTimeSec);
		m_standBy = ntohl(ListResponse.m_downloadStandBy);
		m_allBytes = Util::JoinInt64(ntohl(ListResponse.m_downloadedBytesHi), ntohl(ListResponse.m_downloadedBytesLo));
	}

	if (m_fileList && ntohl(ListResponse.m_trailingDataLength) > 0)
	{
		RemoteClient client;
		client.SetVerbose(false);

		client.BuildFileList(&ListResponse, buf, DownloadQueue::Guard());
	}

	return true;
}
Ejemplo n.º 21
0
bool TwoWayReply::parse(RFC822Message *msg)
{
  // Parse the message in <msg>.  Parsing continues until all data has
  // been read.  If an item is specified multiple times, only the
  // first will be used.  If parsing is not successful, the individual
  // Reply methods may be used to see what information was
  // successfully read.

  // Returns: true if all items were successfully parsed from the message,
  // false otherwise.

  bool ret = false;
  
#if defined(DEBUG)
  dlog->log_entry(DEBUG_MAJTRC, "TwoWayReply::parse(%d)", msg);
  dlog->log_progress(DEBUG_PARSER, "Trying to parse message as Nextel reply");
#endif

  if(msg)
  {
    // First, get stuff from the headers

    char *mf = msg->header_entry("From", 0);

    if(mf)
    {
#if defined(DEBUG)
      dlog->log_progress(DEBUG_PARSER, "Message from '%s'", mf);
#endif
      
      f = xstrdup(mf);
    }

    char *ms = msg->header_entry("Subject", 0);

    if(ms)
    {
      // Pull out hostname and service

      char *p = strstr(ms, "ALERT: ");

      if(p)
      {
	p += 7;

	List *ts = tokenize(p, "@");

	if(ts)
	{
	  // This was backwards, bug #635
	  // Patched by Olivier Calle
	  svc = xstrdup(ts->retrieve(0));
	  h = xstrdup(ts->retrieve(1));
	  
#if defined(DEBUG)
	  dlog->log_progress(DEBUG_PARSER, "Host '%s', service '%s'", h, svc);
#endif
      
	  xdelete(ts);
	}
      }
    }

    // Now get the rest of the info from the body

    CharBuffer *body = msg->body();

    if(body)
    {
      for(char *s = body->read_line();s != NULL;s = body->read_line())
      {
	if(!t && strncmp(s, "Token=", 6)==0)
	{
	  // Pull out token

	  t = xstrdup(s+6);

#if defined(DEBUG)
	  dlog->log_progress(DEBUG_PARSER, "Token '%s'", t);
#endif
	}
	else if(!inst && strncmp(s, "Instance=", 9)==0)
	{
	  // Pull out instance
	  
	  inst = xstrdup(s+9);

#if defined(DEBUG)
	  dlog->log_progress(DEBUG_PARSER, "Instance '%s'", inst);
#endif
	}
	else if(ry == unknown_reply && strcmp(s, "Acknowledge")==0)
	{
	  ry = acknowledge_reply;

#if defined(DEBUG)
	  dlog->log_progress(DEBUG_PARSER, "Reply command '%s'", s);
#endif
	}
	else if(ry == unknown_reply && strcmp(s, "Escalate")==0)
	{
	  ry = escalate_reply;

#if defined(DEBUG)
	  dlog->log_progress(DEBUG_PARSER, "Reply command '%s'", s);
#endif
	}
	else if(ry == unknown_reply && strcmp(s, "Inhibit")==0)
	{
	  ry = inhibit_reply;

#if defined(DEBUG)
	  dlog->log_progress(DEBUG_PARSER, "Reply command '%s'", s);
#endif
	}
      }
    }

    if(f && h && inst && svc && t && (ry != unknown_reply))
      ret = true;
  }
  
#if defined(DEBUG)
  dlog->log_exit(DEBUG_MAJTRC, "TwoWayReply::parse = %s", IOTF(ret));
#endif

  return(ret);
}
Ejemplo n.º 22
0
	void CharSource::ConstCharPtr::ReleaseString(CharBuffer & buffer)
	{
		const char * begin = PopPtr();

		buffer.Append(begin, ptr_);
	}
Ejemplo n.º 23
0
// Read a BAM file's header.
bool BamInterface::readHeader(IFILE filePtr, SamFileHeader& header,
                              SamStatus& status)
{
    if(filePtr == NULL)
    {
        // File is not open, return false.
        status.setStatus(SamStatus::FAIL_ORDER,
                         "Cannot read header since the file pointer is null");
        return(false);
    }
    if(filePtr->isOpen() == false)
    {
        status.setStatus(SamStatus::FAIL_ORDER,
                         "Cannot read header since the file is not open");
        return(false);
    }

    // Clear the passed in header.
    header.resetHeader();

    int32_t headerLength;
    int readSize = ifread(filePtr, &headerLength, sizeof(headerLength));

    if(readSize != sizeof(headerLength))
    {
        String errMsg = "Failed to read the BAM header length, read ";
        errMsg += readSize;
        errMsg += " bytes instead of ";
        errMsg += (unsigned int)sizeof(headerLength);
        status.setStatus(SamStatus::FAIL_IO, errMsg.c_str());
        return(false);
    }

    String headerStr;
    if(headerLength > 0)
    {
        // Read the header.
        readSize =
            ifread(filePtr, headerStr.LockBuffer(headerLength + 1), headerLength);
        headerStr[headerLength] = 0;
        headerStr.UnlockBuffer();
        if(readSize != headerLength)
        {
            // Failed to read the header.
            status.setStatus(SamStatus::FAIL_IO, "Failed to read the BAM header.");
            return(false);
        }
    }

    // Parse the header that was read.
    if(!header.addHeader(headerStr))
    {
        // Status is set in the method on failure.
        status.setStatus(SamStatus::FAIL_PARSE, header.getErrorMessage());
        return(false);
    }

    int referenceCount;
    // Read the number of references sequences.
    ifread(filePtr, &referenceCount, sizeof(int));

    // Get and clear the reference info so it can be set
    // from the bam reference table.
    SamReferenceInfo& refInfo =
        header.getReferenceInfoForBamInterface();
    refInfo.clear();

    CharBuffer refName;

    // Read each reference sequence
    for (int i = 0; i < referenceCount; i++)
    {
        int nameLength;
        int rc;
        // Read the length of the reference name.
        rc = ifread(filePtr, &nameLength, sizeof(int));
        if(rc != sizeof(int))
        {
            status.setStatus(SamStatus::FAIL_IO,
                             "Failed to read the BAM reference dictionary.");
            return(false);
        }

        // Read the name.
        refName.readFromFile(filePtr, nameLength);

        // Read the length of the reference sequence.
        int32_t refLen;
        rc = ifread(filePtr, &refLen, sizeof(int));

        if(rc != sizeof(int)) {
            status.setStatus(SamStatus::FAIL_IO,
                             "Failed to read the BAM reference dictionary.");
            return(false);
        }

        refInfo.add(refName.c_str(), refLen);
    }

    // Successfully read the file.
    return(true);
}
Ejemplo n.º 24
0
bool Frontend::RequestMessages()
{
	const char* controlIp = !strcmp(g_Options->GetControlIp(), "0.0.0.0") ? "127.0.0.1" : g_Options->GetControlIp();
	Connection connection(controlIp, g_Options->GetControlPort(), false);

	bool OK = connection.Connect();
	if (!OK)
	{
		return false;
	}

	SNzbLogRequest LogRequest;
	InitMessageBase(&LogRequest.m_messageBase, rrLog, sizeof(LogRequest));
	LogRequest.m_lines = htonl(m_neededLogEntries);
	if (m_neededLogEntries == 0)
	{
		LogRequest.m_idFrom = htonl(m_neededLogFirstId > 0 ? m_neededLogFirstId : 1);
	}
	else
	{
		LogRequest.m_idFrom = 0;
	}

	if (!connection.Send((char*)(&LogRequest), sizeof(LogRequest)))
	{
		return false;
	}

	// Now listen for the returned log
	SNzbLogResponse LogResponse;
	bool read = connection.Recv((char*) &LogResponse, sizeof(LogResponse));
	if (!read ||
		(int)ntohl(LogResponse.m_messageBase.m_signature) != (int)NZBMESSAGE_SIGNATURE ||
		ntohl(LogResponse.m_messageBase.m_structSize) != sizeof(LogResponse))
	{
		return false;
	}

	CharBuffer buf;
	if (ntohl(LogResponse.m_trailingDataLength) > 0)
	{
		buf.Reserve(ntohl(LogResponse.m_trailingDataLength));
		if (!connection.Recv(buf, buf.Size()))
		{
			return false;
		}
	}

	connection.Disconnect();

	if (ntohl(LogResponse.m_trailingDataLength) > 0)
	{
		char* bufPtr = (char*)buf;
		for (uint32 i = 0; i < ntohl(LogResponse.m_nrTrailingEntries); i++)
		{
			SNzbLogResponseEntry* logAnswer = (SNzbLogResponseEntry*) bufPtr;

			char* text = bufPtr + sizeof(SNzbLogResponseEntry);

			m_remoteMessages.emplace_back(ntohl(logAnswer->m_id), (Message::EKind)ntohl(logAnswer->m_kind), ntohl(logAnswer->m_time), text);

			bufPtr += sizeof(SNzbLogResponseEntry) + ntohl(logAnswer->m_textLen);
		}
	}

	return true;
}
void CharArrayBufferTest::testCompact() {

    // readonly's contents should be the same as buf
    CharBuffer* readOnly = testBuffer1->asReadOnlyBuffer();

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a ReadOnlyBufferExceptio",
        readOnly->compact(),
        ReadOnlyBufferException );

    // case: buffer is full
    testBuffer1->clear();
    testBuffer1->mark();

    for( int ix = 0; ix < testData1Size; ++ix ){
        testBuffer1->put( ix, testData1[ix] );
    }

    CharBuffer& ret = testBuffer1->compact();

    CPPUNIT_ASSERT( &ret == testBuffer1 );
    CPPUNIT_ASSERT( testBuffer1->position() == testBuffer1->capacity() );
    CPPUNIT_ASSERT( testBuffer1->limit() == testBuffer1->capacity() );

    for( int ix = 0; ix < testBuffer1->capacity(); ix++ ) {
        CPPUNIT_ASSERT( testBuffer1->get( ix ) == testData1[ix] );
    }

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a InvalidMarkException",
        readOnly->reset(),
        InvalidMarkException );

    delete readOnly;

    // case: buffer is empty
    testBuffer1->position(0);
    testBuffer1->limit(0);
    testBuffer1->mark();
    ret = testBuffer1->compact();
    CPPUNIT_ASSERT( &ret == testBuffer1 );
    CPPUNIT_ASSERT( testBuffer1->position() == 0 );
    CPPUNIT_ASSERT( testBuffer1->limit() == testBuffer1->capacity() );

    for( int ix = 0; ix < testBuffer1->capacity(); ix++ ) {
        CPPUNIT_ASSERT( testBuffer1->get( ix ) == testData1[ix] );
    }

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a InvalidMarkException",
        testBuffer1->reset(),
        InvalidMarkException );

    // case: normal
    testBuffer1->position(1);
    testBuffer1->limit(SMALL_TEST_LENGTH);
    testBuffer1->mark();
    ret = testBuffer1->compact();
    CPPUNIT_ASSERT( &ret == testBuffer1 );
    CPPUNIT_ASSERT( testBuffer1->position() == SMALL_TEST_LENGTH - 1  );
    CPPUNIT_ASSERT( testBuffer1->limit() == testBuffer1->capacity() );

    for( int ix = 0; ix < SMALL_TEST_LENGTH - 1; ix++ ) {
        CPPUNIT_ASSERT( testBuffer1->get( ix ) == testData1[ix + 1] );
    }

    CPPUNIT_ASSERT_THROW_MESSAGE(
        "Should throw a InvalidMarkException",
        testBuffer1->reset(),
        InvalidMarkException );
}
Ejemplo n.º 26
0
// see Q246772
bool Utils::GetDefPrinter(string& printerName)
{
  OSVERSIONINFOW osv;
  osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
  GetVersionExW(&osv);
  if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  {
#if defined(MIKTEX_SUPPORT_LEGACY_WINDOWS)
    unsigned long dwNeeded, dwReturned;
    EnumPrintersW(PRINTER_ENUM_DEFAULT, 0, 2, 0, 0, &dwNeeded, &dwReturned);
    if (dwNeeded == 0)
    {
      return false;
    }
    AutoGlobalMemory hMem(GlobalAlloc(GPTR, dwNeeded));
    if (hMem.Get() == nullptr)
    {
      OUT_OF_MEMORY("GlobalAlloc");
    }
    PRINTER_INFO_2W* ppi2 =
      reinterpret_cast<PRINTER_INFO_2W *>(hMem.Get());
    if (!EnumPrintersW(PRINTER_ENUM_DEFAULT, 0, 2, reinterpret_cast<LPBYTE>(ppi2), dwNeeded, &dwNeeded, &dwReturned))
    {
      return false;
    }
    size_t l = StrLen(ppi2->pPrinterName);
    if (l >= *pBufferSize)
    {
      *pBufferSize = l + 1;
      return false;
    }
    StringUtil::CopyString(pPrinterName, *pBufferSize, ppi2->pPrinterName);
    *pBufferSize = l + 1;
    return true;
#else
    UNSUPPORTED_PLATFORM();
#endif
  }
  else
  {
    if (osv.dwPlatformId != VER_PLATFORM_WIN32_NT)
    {
      MIKTEX_UNEXPECTED();
    }
    if (osv.dwMajorVersion >= 5)
    {
      CharBuffer<wchar_t> printerNameBuf;
      DWORD dwBufferSize = static_cast<DWORD>(printerNameBuf.GetCapacity());
      BOOL bDone = GetDefaultPrinterW(printerNameBuf.GetData(), &dwBufferSize);
      if (!bDone)
      {
        if (::GetLastError() == ERROR_FILE_NOT_FOUND)
        {
          return false;
        }
        else
        {
          MIKTEX_FATAL_WINDOWS_ERROR("GetDefaultPrinterW");
        }
      }
      else
      {
        printerName = WU_(printerNameBuf.GetData());
        return true;
      }
    }
    else
    {
#if defined(MIKTEX_SUPPORT_LEGACY_WINDOWS)
      wchar_t cBuffer[4096];
      if (GetProfileStringW(L"windows", L"device", L",,,", cBuffer, 4096) <= 0)
      {
        return false;
      }
      Tokenizer tok(StringUtil::WideCharToUTF8(cBuffer), ",");
      if (tok.GetCurrent() == nullptr)
      {
        return false;
      }
      unsigned long l = static_cast<unsigned long>(StrLen(tok.GetCurrent()));
      if (l >= *pBufferSize)
      {
        *pBufferSize = l + 1;
        return false;
      }
      StringUtil::CopyString(pPrinterName, *pBufferSize, tok.GetCurrent());
      *pBufferSize = l + 1;
      return true;
#else
      UNSUPPORTED_PLATFORM();
#endif
    }
  }
}
Ejemplo n.º 27
0
void ArticleWriter::CompleteFileParts()
{
	debug("Completing file parts");
	debug("ArticleFilename: %s", m_fileInfo->GetFilename());

	bool directWrite = (g_Options->GetDirectWrite() || m_fileInfo->GetForceDirectWrite()) && m_fileInfo->GetOutputInitialized();

	BString<1024> nzbName;
	BString<1024> nzbDestDir;
	BString<1024> filename;

	{
		GuardedDownloadQueue guard = DownloadQueue::Guard();
		nzbName = m_fileInfo->GetNzbInfo()->GetName();
		nzbDestDir = m_fileInfo->GetNzbInfo()->GetDestDir();
		filename = m_fileInfo->GetFilename();
	}

	BString<1024> infoFilename("%s%c%s", *nzbName, PATH_SEPARATOR, *filename);

	bool cached = m_fileInfo->GetCachedArticles() > 0;

	if (g_Options->GetRawArticle())
	{
		detail("Moving articles for %s", *infoFilename);
	}
	else if (directWrite && cached)
	{
		detail("Writing articles for %s", *infoFilename);
	}
	else if (directWrite)
	{
		detail("Checking articles for %s", *infoFilename);
	}
	else
	{
		detail("Joining articles for %s", *infoFilename);
	}

	// Ensure the DstDir is created
	CString errmsg;
	if (!FileSystem::ForceDirectories(nzbDestDir, errmsg))
	{
		m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
			"Could not create directory %s: %s", *nzbDestDir, *errmsg);
		return;
	}

	CString ofn;
	if (m_fileInfo->GetForceDirectWrite())
	{
		ofn.Format("%s%c%s", *nzbDestDir, PATH_SEPARATOR, *filename);
	}
	else
	{
		ofn = FileSystem::MakeUniqueFilename(nzbDestDir, *filename);
	}

	DiskFile outfile;
	BString<1024> tmpdestfile("%s.tmp", *ofn);

	if (!g_Options->GetRawArticle() && !directWrite)
	{
		FileSystem::DeleteFile(tmpdestfile);
		if (!outfile.Open(tmpdestfile, DiskFile::omWrite))
		{
			m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
				"Could not create file %s: %s", *tmpdestfile, *FileSystem::GetLastErrorMessage());
			return;
		}
	}
	else if (directWrite && cached)
	{
		if (!outfile.Open(m_outputFilename, DiskFile::omReadWrite))
		{
			m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
				"Could not open file %s: %s", *m_outputFilename, *FileSystem::GetLastErrorMessage());
			return;
		}
		tmpdestfile = *m_outputFilename;
	}
	else if (g_Options->GetRawArticle())
	{
		FileSystem::DeleteFile(tmpdestfile);
		if (!FileSystem::CreateDirectory(ofn))
		{
			m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
				"Could not create directory %s: %s", *ofn, *FileSystem::GetLastErrorMessage());
			return;
		}
	}

	if (outfile.Active())
	{
		SetWriteBuffer(outfile, 0);
	}

	uint32 crc = 0;

	{
		std::unique_ptr<ArticleCache::FlushGuard> flushGuard;
		if (cached)
		{
			flushGuard = std::make_unique<ArticleCache::FlushGuard>(g_ArticleCache->GuardFlush());
		}

		CharBuffer buffer;
		bool firstArticle = true;

		if (!g_Options->GetRawArticle() && !directWrite)
		{
			buffer.Reserve(1024 * 64);
		}

		for (ArticleInfo* pa : m_fileInfo->GetArticles())
		{
			if (pa->GetStatus() != ArticleInfo::aiFinished)
			{
				continue;
			}

			if (!g_Options->GetRawArticle() && !directWrite && pa->GetSegmentOffset() > -1 &&
				pa->GetSegmentOffset() > outfile.Position() && outfile.Position() > -1)
			{
				memset(buffer, 0, buffer.Size());
				if (!g_Options->GetSkipWrite())
				{
					while (pa->GetSegmentOffset() > outfile.Position() && outfile.Position() > -1 &&
						outfile.Write(buffer, std::min((int)(pa->GetSegmentOffset() - outfile.Position()), buffer.Size())));
				}
			}

			if (pa->GetSegmentContent())
			{
				if (!g_Options->GetSkipWrite())
				{
					outfile.Seek(pa->GetSegmentOffset());
					outfile.Write(pa->GetSegmentContent(), pa->GetSegmentSize());
				}
				pa->DiscardSegment();
			}
			else if (!g_Options->GetRawArticle() && !directWrite && !g_Options->GetSkipWrite())
			{
				DiskFile infile;
				if (pa->GetResultFilename() && infile.Open(pa->GetResultFilename(), DiskFile::omRead))
				{
					int cnt = buffer.Size();
					while (cnt == buffer.Size())
					{
						cnt = (int)infile.Read(buffer, buffer.Size());
						outfile.Write(buffer, cnt);
					}
					infile.Close();
				}
				else
				{
					m_fileInfo->SetFailedArticles(m_fileInfo->GetFailedArticles() + 1);
					m_fileInfo->SetSuccessArticles(m_fileInfo->GetSuccessArticles() - 1);
					m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
						"Could not find file %s for %s [%i/%i]",
						pa->GetResultFilename(), *infoFilename, pa->GetPartNumber(),
						(int)m_fileInfo->GetArticles()->size());
				}
			}
			else if (g_Options->GetRawArticle())
			{
				BString<1024> dstFileName("%s%c%03i", *ofn, PATH_SEPARATOR, pa->GetPartNumber());
				if (!FileSystem::MoveFile(pa->GetResultFilename(), dstFileName))
				{
					m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
						"Could not move file %s to %s: %s", pa->GetResultFilename(),
						*dstFileName, *FileSystem::GetLastErrorMessage());
				}
			}

			if (m_format == Decoder::efYenc)
			{
				crc = firstArticle ? pa->GetCrc() : Crc32::Combine(crc, pa->GetCrc(), pa->GetSegmentSize());
				firstArticle = false;
			}
		}

		buffer.Clear();
	}

	if (outfile.Active())
	{
		outfile.Close();
		if (!directWrite && !FileSystem::MoveFile(tmpdestfile, ofn))
		{
			m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
				"Could not move file %s to %s: %s", *tmpdestfile, *ofn,
				*FileSystem::GetLastErrorMessage());
		}
	}

	if (directWrite)
	{
		if (!FileSystem::SameFilename(m_outputFilename, ofn) &&
			!FileSystem::MoveFile(m_outputFilename, ofn))
		{
			m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
				"Could not move file %s to %s: %s", *m_outputFilename, *ofn,
				*FileSystem::GetLastErrorMessage());
		}

		// if destination directory was changed delete the old directory (if empty)
		int len = strlen(nzbDestDir);
		if (!(!strncmp(nzbDestDir, m_outputFilename, len) &&
			(m_outputFilename[len] == PATH_SEPARATOR || m_outputFilename[len] == ALT_PATH_SEPARATOR)))
		{
			debug("Checking old dir for: %s", *m_outputFilename);
			BString<1024> oldDestDir;
			oldDestDir.Set(m_outputFilename, (int)(FileSystem::BaseFileName(m_outputFilename) - m_outputFilename));
			if (FileSystem::DirEmpty(oldDestDir))
			{
				debug("Deleting old dir: %s", *oldDestDir);
				FileSystem::RemoveDirectory(oldDestDir);
			}
		}
	}

	if (!directWrite)
	{
		for (ArticleInfo* pa : m_fileInfo->GetArticles())
		{
			if (pa->GetResultFilename())
			{
				FileSystem::DeleteFile(pa->GetResultFilename());
			}
		}
	}

	if (m_fileInfo->GetTotalArticles() == m_fileInfo->GetSuccessArticles())
	{
		m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Successfully downloaded %s", *infoFilename);
	}
	else if (m_fileInfo->GetMissedArticles() + m_fileInfo->GetFailedArticles() > 0)
	{
		m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkWarning,
			"%i of %i article downloads failed for \"%s\"",
			m_fileInfo->GetMissedArticles() + m_fileInfo->GetFailedArticles(),
			m_fileInfo->GetTotalArticles(), *infoFilename);
	}
	else
	{
		m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Partially downloaded %s", *infoFilename);
	}

	{
		GuardedDownloadQueue guard = DownloadQueue::Guard();

		m_fileInfo->SetCrc(crc);
		m_fileInfo->SetOutputFilename(ofn);

		if (strcmp(m_fileInfo->GetFilename(), filename))
		{
			// file was renamed during completion, need to move the file
			ofn = FileSystem::MakeUniqueFilename(nzbDestDir, m_fileInfo->GetFilename());
			if (!FileSystem::MoveFile(m_fileInfo->GetOutputFilename(), ofn))
			{
				m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError,
					"Could not rename file %s to %s: %s", m_fileInfo->GetOutputFilename(),
					*ofn, *FileSystem::GetLastErrorMessage());
			}
			m_fileInfo->SetOutputFilename(ofn);
		}

		if (strcmp(m_fileInfo->GetNzbInfo()->GetDestDir(), nzbDestDir))
		{
			// destination directory was changed during completion, need to move the file
			MoveCompletedFiles(m_fileInfo->GetNzbInfo(), nzbDestDir);
		}
	}
}