예제 #1
0
bool Ini_UpdaterLists::readSingleFileInfoRollback(const TCHAR *iniFileName, TCHAR *fileSectionName, FileInfo &file)
{
    if(!iniFileName || (*iniFileName == 0))
    {
        TRACE_MESSAGE("Read rollback file information error: configuration file name is not specified");
        return false;
    }
    if(!fileSectionName)
    {
        TRACE_MESSAGE("Read rollback file information error: configuration section is not specified");
        return false;
    }
    
    TCHAR buffer[MAX_STR_BUFF + 1] = _T("");
    
    // file name
    GetPrivateProfileString(fileSectionName, STRING(SS_KEY_RecentFileName).c_str(), _T(UNKNOWN_STRING), buffer, MAX_STR_BUFF, iniFileName);
    if(!_tcscmp(buffer, _T(UNKNOWN_STRING)))
    {
        TRACE_MESSAGE2("Read rollback file information error: no '%s' value found", STRING(SS_KEY_RecentFileName).to_string().c_str());
        return false;
    }
    file.m_filename = buffer;

    // local path
    GetPrivateProfileString(fileSectionName, STRING(SS_KEY_RecentLocalPath).c_str(), _T(UNKNOWN_STRING), buffer, MAX_STR_BUFF, iniFileName);
    if(!_tcscmp(buffer, _T(UNKNOWN_STRING)))
    {
        TRACE_MESSAGE2("Read rollback file information error: no '%s' value found", STRING(SS_KEY_RecentLocalPath).to_string().c_str());
        return false;
    }
    file.m_localPath = buffer;

    // change status
    GetPrivateProfileString(fileSectionName, STRING(SS_KEY_ChangeStatus).c_str(), _T(UNKNOWN_STRING), buffer, MAX_STR_BUFF, iniFileName);
    if(!_tcscmp(buffer, _T(UNKNOWN_STRING)))
    {
        TRACE_MESSAGE2("Read rollback file information error: no '%s' value found", STRING(SS_KEY_ChangeStatus).to_string().c_str());
        return false;
    }
    file.m_rollbackChange = buffer;

    // md5 for consistency check
    GetPrivateProfileString(fileSectionName, STRING(kayw_MD5).c_str(), _T(UNKNOWN_STRING), buffer, MAX_STR_BUFF, iniFileName);
    if(_tcscmp(buffer, _T(UNKNOWN_STRING)))
        file.m_md5 = CBase64::decodeBuffer(STRING(buffer).to_string().c_str());

    TRACE_MESSAGE2("Rollback information read: '%s'", file.toString().c_str());
    return true;
}
예제 #2
0
void KLUPD::UpdateInfo::removeComponentFromUpdate(
    const ComponentIdentefiers componentsToRemove,   // componentsToRemove - copy because when file is deleted iterator becomes invalid)
    JournalInterface &journal)
{
    // removing component from retranslation filter
    for(ComponentIdentefiers::const_iterator iter = componentsToRemove.begin(); iter != componentsToRemove.end(); ++iter)
    {
        TRACE_MESSAGE2("Warning: removing components from update %S", iter->toWideChar());

        // copy is needed, because iter will be invalid after remove from list
        const NoCaseString removingComponent = *iter;

        // removing from retranslation filter
        m_components.erase(std::remove_if(m_components.begin(), m_components.end(),
            std::bind2nd(std::equal_to<NoCaseString>(), removingComponent)), m_components.end());

        m_componentsRemovedFromUpdate.push_back(removingComponent);

		journal.publishMessage
			(
				m_retranslationMode ? EVENT_ComponentIsNotRetranslated : EVENT_ComponentIsNotUpdated, 
				removingComponent
			);
    }

    // removing file by component filter criteria
    if(!componentsToRemove.empty())
        filterByComponents(componentsToRemove);
}
예제 #3
0
KLUPD::CoreError KLUPD::AdministrationKitProtocol::setupLowLevelConnectionIfNeed(const bool useMasterAdministrationServer)
{
#ifdef DISABLE_AK_FILETRANSFER
    TRACE_MESSAGE("Administration Kit Transport is not implemented");
    return CORE_DOWNLOAD_ERROR;
#else
    if(m_connected)
        return CORE_NO_ERROR;

    m_downloadProgress.updateSpeedStartTimer();

    KLFT::ConnectResult connectResult = KLFT::CR_ConnectionServerError;
    if(useMasterAdministrationServer)
    {
        TRACE_MESSAGE("Connecting to master administration server");
        connectResult = m_adminKitTransprot->ConnectToMasterServer();
    }
    else
    {
        TRACE_MESSAGE("Connecting to administration server");
        connectResult = m_adminKitTransprot->Connect();
    }

    m_downloadProgress.updateSpeedStopTimer();

    switch(connectResult)
    {
    // successfully connected
    case KLFT::CR_Ok:
        m_connected = true;
        return CORE_NO_ERROR;
        
    // invalid AdminKit Transport identifier: either receiver was
     //  deleted or connect was already called for this receiver
    case KLFT::CR_WrongReceiverId:
        return CORE_AK_WrongReceiverId;
        
    // AdminKit server is busy and can not handle requests now
    case KLFT::CR_ServerBusy:
        return CORE_AK_ServerBusy;
        
    // physical connection to AdminKit error
    case KLFT::CR_ConnectionError:
        return CORE_AK_ConnectionError;
        
    // connection to AdminKit network agent physical error
    case KLFT::CR_ConnectionNagentError:
        return CORE_AK_ConnectionNagentError;
        
    // connection to master AdminKit server physical error
    case KLFT::CR_ConnectionServerError:
        return CORE_AK_ConnectionServerError;
        
    // unknown AdminKit connection error
    default:
        TRACE_MESSAGE2("Connecting to Administration Server failed with unknown code '%d'", connectResult);
        return CORE_AK_CannotConnectToServer;
    }
#endif  // DISABLE_AK_FILETRANSFER
}
예제 #4
0
bool KLUPD::UpdateInfo::checkIfFileOptional(const FileInfo absentFile)
                    // absentFile is a copy, because update file set is modified
{
    // in case component identifier is not specified, then it is primary index or other helper file
    for(ComponentIdentefiers::const_iterator componentIter = absentFile.m_componentIdSet.begin();; ++componentIter)
    {
        if(componentIter == absentFile.m_componentIdSet.end())
        {
            TRACE_MESSAGE2("Error: component identifier is not specified '%S', file is mandatory and can not be removed from update",
                absentFile.toString().toWideChar());
            return false;
        }
        // non-empty component found
        if(!componentIter->empty())
            break;
    }

    // check if any of component's file is mandatory
    for(FileVector::const_iterator fileIter = m_matchFileList.begin(); fileIter != m_matchFileList.end(); ++fileIter)
    {
        // search if absent file has the same component identifier that absent file
        ComponentIdentefiers::const_iterator componentIter = std::find_first_of(absentFile.m_componentIdSet.begin(),
            absentFile.m_componentIdSet.end(), fileIter->m_componentIdSet.begin(), fileIter->m_componentIdSet.end());

        // not match by component
        if(componentIter == absentFile.m_componentIdSet.end())
            continue;

        if(!m_callbacks.checkIfFileOptional(*fileIter, m_retranslationMode))
        {
            TRACE_MESSAGE3("Error: missing file '%S' which is mandatory for '%S'",
                absentFile.toString().toWideChar(), fileIter->toString().toWideChar());
            return false;
        }
    }

    TRACE_MESSAGE2("File '%S' is optional for update",
        absentFile.toString().toWideChar());
    return true;
}
예제 #5
0
bool KLUPD::IniFile::save()
{
    if(m_fileName.empty())
    {
        TRACE_MESSAGE("Failed to save ini file, because no file name is specified");
        return false;
    }

    FileStream file(pLog);
    if(!file.open(m_fileName, std::ios::out | std::ios::trunc))
    {
        TRACE_MESSAGE2("Unable to save ini configuration file, because unable to open file '%S'", m_fileName.toWideChar());
        return false;
    }

    for(std::vector<Section>::const_iterator sectionIter = m_sections.begin(); sectionIter != m_sections.end(); ++sectionIter)
    {
        bool wroteComment = false;
        if(!sectionIter->m_comment.empty())
        {
            wroteComment = true;
            file.writeLine(NoCaseString(L"\n") + commentStr(sectionIter->m_comment));
        }

        if(!sectionIter->m_name.empty())
        {
            NoCaseString buffer = wroteComment ? L"\n" : L"";
            buffer += NoCaseString(L"[") + sectionIter->m_name + L"]";
            file.writeLine(buffer);
        }

        for(std::vector<Key>::const_iterator keyIter = sectionIter->m_keys.begin(); keyIter != sectionIter->m_keys.end(); ++keyIter)
        {
            if(keyIter->m_key.empty())
                continue;

            NoCaseString buffer = keyIter->m_comment.empty() ? L"" : L"\n";
            buffer += commentStr(keyIter->m_comment);
            buffer += keyIter->m_comment.empty() ? L"" : L"\n";
            buffer += keyIter->m_key.toWideChar();
            buffer += s_equalIndicators[0];
            buffer += keyIter->m_value;

            file.writeLine(buffer);
        }
    }

    m_dirty = false;
    return true;
}
예제 #6
0
void KLUPD::UpdateInfo::filterByComponents(// filter parameter is passed *by value*
                                    const ComponentIdentefiers componentIdSet)
{
    // filtering is not needed
    if(componentIdSet.empty())
        return;

    for(size_t i = 0; i < m_matchFileList.size();)
    {
        // do not filter in case component is not set
        FileVector::iterator removeIter = m_matchFileList.begin();
        std::advance(removeIter, i);
        
        // there is the only component with specified identifier in component set
        if(removeIter->m_componentIdSet.size() == 1)
        {
            // check if the only component in a set to remove
            if(std::find(componentIdSet.begin(), componentIdSet.end(), removeIter->m_componentIdSet[0]) != componentIdSet.end())
            {
                TRACE_MESSAGE3("\tRemoved optional file from download list with Component Identifier '%S': %S",
                    removeIter->m_componentIdSet[0].toWideChar(), removeIter->toString().toWideChar());
                m_matchFileList.erase(removeIter);
                continue;
            }
        }
        // the file matches for several component
        else if(!removeIter->m_componentIdSet.empty())
        {
            // removing all components in file component set
            for(ComponentIdentefiers::const_iterator iter = componentIdSet.begin(); iter != componentIdSet.end(); ++iter)
            {
                removeIter->m_componentIdSet.erase(std::remove_if(removeIter->m_componentIdSet.begin(), removeIter->m_componentIdSet.end(),
                    std::bind2nd(std::equal_to<NoCaseString>(), *iter)), removeIter->m_componentIdSet.end());
            }

            // no matched component rests, so removing file from list
            if(removeIter->m_componentIdSet.empty())
            {
                TRACE_MESSAGE2("\tRemoved optional file from download list, because all its Component Identifiers are optional: %S",
                    removeIter->toString().toWideChar());
                m_matchFileList.erase(removeIter);
                continue;
            }
        }

        ++i;
    }
}
예제 #7
0
bool KLUPD::NtlmImplementation::loadSecurityLibrary()
{
    if(m_securityDll && m_funcionTable)
        return true;

    if(!m_securityDll)
    {
        m_securityDll = LoadLibrary(_T("secur32.dll"));
        if(!m_securityDll)
        {
            // on some platforms (e.g. Windows NT) there is no secur32.dll
            m_securityDll = LoadLibrary(_T("security.dll"));
            if(!m_securityDll)
            {
                const int lastError = GetLastError();
                TRACE_MESSAGE2("Failed to load both 'secur32.dll' and 'security.dll' libraries, last error '%S'",
                    errnoToString(lastError, windowsStyle).toWideChar());
                return false;
            }
        }
    }


    PSecurityFunctionTable (*getFuncTable)();
	getFuncTable = (PSecurityFunctionTable (*)(VOID))GetProcAddress(m_securityDll, tStringToAscii(SECURITY_ENTRYPOINT).c_str());

    if(!getFuncTable)
    {
        const int lastError = GetLastError();
        TRACE_MESSAGE3("Initialization NTLM functionality: failed to get function '%s' address, last error '%S'",
            tStringToAscii(SECURITY_ENTRYPOINT).c_str(), KLUPD::errnoToString(lastError, KLUPD::windowsStyle).toWideChar());
        return false;
    }

    m_funcionTable = getFuncTable();
    if(!m_funcionTable)
    {
        const int lastError = GetLastError();
        TRACE_MESSAGE3("Initialization NTLM functionality: '%s' call failed, last error '%S'",
            tStringToAscii(SECURITY_ENTRYPOINT).c_str(), errnoToString(lastError, windowsStyle).toWideChar());
        return false;
    }

    return true;
}
예제 #8
0
파일: Lo_send.c 프로젝트: nmap/npcap
static
NTSTATUS
InitWskBuffer_NBL(
	IN PNET_BUFFER_LIST NetBufferList,
	IN ULONG BufferOffset,
	OUT PWSK_BUF WskBuffer
	)
{
	NTSTATUS Status = STATUS_SUCCESS;

	TRACE_ENTER();

	ASSERT(NetBufferList);
	ASSERT(WskBuffer);

	WskBuffer->Offset = BufferOffset;
	WskBuffer->Length = NetBufferList->FirstNetBuffer->DataLength - BufferOffset;

	WskBuffer->Mdl = NetBufferList->FirstNetBuffer->CurrentMdl;
	if (!WskBuffer->Mdl)
	{
		TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "InitWskBuffer_NBL()::NetBufferList->FirstNetBuffer->CurrentMdl failed with status 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
		TRACE_EXIT();
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	__try
	{
		if ((WskBuffer->Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) != MDL_MAPPED_TO_SYSTEM_VA &&
			(WskBuffer->Mdl->MdlFlags & MDL_PAGES_LOCKED) != MDL_PAGES_LOCKED &&
			(WskBuffer->Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) != MDL_SOURCE_IS_NONPAGED_POOL)
		{
			MmProbeAndLockPages(WskBuffer->Mdl, KernelMode, IoWriteAccess);
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "InitWskBuffer_NBL()::MmProbeAndLockPages(%p) failed with status 0x%08X\n", WskBuffer->Mdl, STATUS_ACCESS_VIOLATION);
		Status = STATUS_ACCESS_VIOLATION;
	}

	TRACE_EXIT();
	return Status;
}
예제 #9
0
bool Ini_UpdaterLists::readRollbackFileListFromSS(FileVector &changedFiles)
{
    const STRING section_name = SS_KEY_RollbackTree;
    
    STRING rollbackFileAndPath;
    if(!getProductFolder(m_useCurrentFolder, rollbackFileAndPath, pLog))
        return false;
    rollbackFileAndPath += UPDATER_LISTS_FILENEME;
    
    TCHAR childSectionName[MAX_PATH + 1];
    
    for(int _i = 0;; ++_i)
    {
        TCHAR szKeyName[MAX_PATH + 1];
        TCHAR fullSectionName[MAX_PATH + MAX_PATH + 1];
        
        memset(childSectionName, 0, (MAX_PATH + 1) * sizeof(TCHAR));
        memset(szKeyName, 0, (MAX_PATH + 1) * sizeof(TCHAR));
        memset(fullSectionName, 0, (MAX_PATH + MAX_PATH + 1) * sizeof(TCHAR));
        
        _stprintf(szKeyName, _T("entry%d"), _i);
        
        GetPrivateProfileString(section_name.c_str(), szKeyName, _T(""), childSectionName, MAX_PATH, rollbackFileAndPath.c_str());
        
        if(!childSectionName[0])
            break;
        
        _tcscpy(fullSectionName, section_name.c_str());
        _tcscat(fullSectionName, _T(":"));
        _tcscat(fullSectionName, childSectionName);
        
        FileInfo rec;
        if(!readSingleFileInfoRollback(rollbackFileAndPath.c_str(), fullSectionName, rec))
        {
            TRACE_MESSAGE2("Invalid content of '%s' section, skipping", fullSectionName);
            // ignore error, try next entry if any
            continue;
        }
        
        changedFiles.push_back(rec);
    }
    
    return true;
}
예제 #10
0
KLUPD::CoreError HttpTransport::dataReceived(const unsigned char *data, const size_t &size)
{
    if(!m_destinationIO)
    {
        TRACE_MESSAGE("Warning: unable to write received data, no destination file is specified'");
		return KLUPD::CORE_NO_ERROR;
    }

    const tERROR writeFileResult = m_destinationIO->SeekWrite(0, m_currentOffset,
        const_cast<void *>(reinterpret_cast<const void *>(data)), size);
	if(PR_SUCC(writeFileResult))
    {
        m_currentOffset += size;
		return KLUPD::CORE_NO_ERROR;
    }

    TRACE_MESSAGE2("Failed to write received data with result '%s'",
        PRAGUE_HELPERS::toStringPragueResult(writeFileResult).c_str());
    return KLUPD::CORE_GenericFileOperationFailure;
}
예제 #11
0
bool KLUPD::IniFile::load()
{
    if(!LocalFile(m_fileName, pLog).exists())
    {
        TRACE_MESSAGE2("File does not exist '%S'", m_fileName.toWideChar());
        return false;
    }

    // do not create a new file here.  If it doesn't exist, just return false and report the failure.
    FileStream file(pLog);
    if(!file.open(m_fileName, std::ios::in))
    {
        TRACE_MESSAGE2("Failed to load ini configuration file, because failed to open file '%S'",
            m_fileName.toWideChar());
        return false;
    }

    const bool autoKey = (m_flags & AUTOCREATE_KEYS) == AUTOCREATE_KEYS;
    const bool autoSec = (m_flags & AUTOCREATE_SECTIONS) == AUTOCREATE_SECTIONS;

    NoCaseString comment;
    Section *section = getSection(L"");

    // needs to be set to restore the original values later
    m_flags |= AUTOCREATE_KEYS | AUTOCREATE_SECTIONS;

    bool doneWithFile = false;
    while(!doneWithFile)
    {
        NoCaseString line;
        file.getLine(line);
        line.trim();

        doneWithFile = file.done();

        if(line.find_first_of(s_commentIndicators.toWideChar()) == 0)
        {
            comment += L"\n";
            comment += line;
        }
        // new section
        else if(line.find_first_of("[") == 0)
        {
            line.erase(0, 1);
            const size_t lastOffset = line.find_last_of("]");
            if(lastOffset != NoCaseStringImplementation::npos)
            {
                line.erase(lastOffset, 1);

                createSection(line, comment);
                section = getSection(line);
                comment = NoCaseString();
            }
        }
        // we have a key, add this key/value pair
        else if(!line.empty())
        {
            NoCaseString keyName = getNextWord(line);
            NoCaseString value = line;

            if(!keyName.empty())
            {
                setValue(keyName, value, section ? section->m_name : NoCaseString(), comment);
                comment = NoCaseString(L"");
            }
        }
    }

    // restore the original flag values.
    if(!autoKey)
        m_flags &= ~AUTOCREATE_KEYS;
    if(!autoSec)
        m_flags &= ~AUTOCREATE_SECTIONS;
    return true;
}
예제 #12
0
파일: Openclos.c 프로젝트: 52M/npcap
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

	PDEVICE_EXTENSION	DeviceExtension;
	POPEN_INSTANCE		Open;
	PIO_STACK_LOCATION  IrpSp;
	NDIS_STATUS			Status;
	NDIS_STATUS			ErrorStatus;
	UINT				i;
	PUCHAR				tpointer;
	PLIST_ENTRY			PacketListEntry;
	NTSTATUS			returnStatus;

//  
//	Old registry based WinPcap names
//
//	WCHAR				EventPrefix[MAX_WINPCAP_KEY_CHARS];
//	UINT				RegStrLen;

	TRACE_ENTER();

	DeviceExtension = DeviceObject->DeviceExtension;

	IrpSp = IoGetCurrentIrpStackLocation(Irp);

	//  allocate some memory for the open structure
	Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');

	if (Open==NULL) {
		// no memory
		Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlZeroMemory(
		Open,
		sizeof(OPEN_INSTANCE)
		);

//  
//	Old registry based WinPcap names
//
//	//
//	// Get the Event names base from the registry
//	//
//	RegStrLen = sizeof(EventPrefix)/sizeof(EventPrefix[0]);
//
//	NPF_QueryWinpcapRegistryString(NPF_EVENTS_NAMES_REG_KEY_WC,
//		EventPrefix,
//		RegStrLen,
//		NPF_EVENTS_NAMES_WIDECHAR);
//
		
	Open->DeviceExtension=DeviceExtension;

	//  Allocate a packet pool for our xmit and receive packets
	NdisAllocatePacketPool(
		&Status,
		&Open->PacketPool,
		TRANSMIT_PACKETS,
		sizeof(PACKET_RESERVED));

	if (Status != NDIS_STATUS_SUCCESS) {

		TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Failed to allocate packet pool");

		ExFreePool(Open);
		Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	NdisInitializeEvent(&Open->WriteEvent);
	NdisInitializeEvent(&Open->NdisRequestEvent);
	NdisInitializeEvent(&Open->NdisWriteCompleteEvent);
	NdisInitializeEvent(&Open->DumpEvent);
	NdisAllocateSpinLock(&Open->MachineLock);
	NdisAllocateSpinLock(&Open->WriteLock);
	Open->WriteInProgress = FALSE;

	for (i = 0; i < g_NCpu; i++)
	{
		NdisAllocateSpinLock(&Open->CpuData[i].BufferLock);
	}

	NdisInitializeEvent(&Open->NdisOpenCloseCompleteEvent);

	//  list to hold irp's want to reset the adapter
	InitializeListHead(&Open->ResetIrpList);

	//  Initialize the request list
	KeInitializeSpinLock(&Open->RequestSpinLock);
	InitializeListHead(&Open->RequestList);

#ifdef HAVE_BUGGY_TME_SUPPORT
	// Initializes the extended memory of the NPF machine
	Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
	if((Open->mem_ex.buffer) == NULL)
	{
		//
		// no memory
		//
		ExFreePool(Open);
		Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
	RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
#endif //HAVE_BUGGY_TME_SUPPORT


	//
	// Initialize the open instance
	//
	Open->bpfprogram = NULL;	//reset the filter
	Open->mode = MODE_CAPT;
	Open->Nbytes.QuadPart = 0;
	Open->Npackets.QuadPart = 0;
	Open->Nwrites = 1;
	Open->Multiple_Write_Counter = 0;
	Open->MinToCopy = 0;
	Open->TimeOut.QuadPart = (LONGLONG)1;
	Open->DumpFileName.Buffer = NULL;
	Open->DumpFileHandle = NULL;
#ifdef HAVE_BUGGY_TME_SUPPORT
	Open->tme.active = TME_NONE_ACTIVE;
#endif // HAVE_BUGGY_TME_SUPPORT
	Open->DumpLimitReached = FALSE;
	Open->MaxFrameSize = 0;
	Open->WriterSN=0;
	Open->ReaderSN=0;
	Open->Size=0;
	Open->SkipSentPackets = FALSE;
	Open->ReadEvent = NULL;

	//
	// we need to keep a counter of the pending IRPs
	// so that when the IRP_MJ_CLEANUP dispatcher gets called,
	// we can wait for those IRPs to be completed
	//
	Open->NumPendingIrps = 0;
	Open->ClosePending = FALSE;
	NdisAllocateSpinLock(&Open->OpenInUseLock);

	//
	//allocate the spinlock for the statistic counters
	//
	NdisAllocateSpinLock(&Open->CountersLock);

	//
	//  link up the request stored in our open block
	//
	for (i = 0 ; i < MAX_REQUESTS ; i++ ) 
	{
		NdisInitializeEvent(&Open->Requests[i].InternalRequestCompletedEvent);

		ExInterlockedInsertTailList(
			&Open->RequestList,
			&Open->Requests[i].ListElement,
			&Open->RequestSpinLock);
	}

	NdisResetEvent(&Open->NdisOpenCloseCompleteEvent);

	// 
	// set the proper binding flags before trying to open the MAC
	//
	Open->AdapterBindingStatus = ADAPTER_BOUND;
	Open->AdapterHandleUsageCounter = 0;
	NdisAllocateSpinLock(&Open->AdapterHandleLock);

	//
	//  Try to open the MAC
	//
	TRACE_MESSAGE2(PACKET_DEBUG_LOUD,"Opening the device %ws, BindingContext=%p",DeviceExtension->AdapterName.Buffer, Open);

	returnStatus = STATUS_SUCCESS;

	NdisOpenAdapter(
		&Status,
		&ErrorStatus,
		&Open->AdapterHandle,
		&Open->Medium,
		MediumArray,
		NUM_NDIS_MEDIA,
		g_NdisProtocolHandle,
		Open,
		&DeviceExtension->AdapterName,
		0,
		NULL);

	TRACE_MESSAGE1(PACKET_DEBUG_LOUD,"Opened the device, Status=%x",Status);

	if (Status == NDIS_STATUS_PENDING)
	{
		NdisWaitEvent(&Open->NdisOpenCloseCompleteEvent, 0);

		if (!NT_SUCCESS(Open->OpenCloseStatus))
		{
			returnStatus = Open->OpenCloseStatus;
		}
		else
		{
			returnStatus = STATUS_SUCCESS;
		}
	}
	else
	{
		//
		// request not pending, we know the result, and OpenComplete has not been called.
		//
		if (Status == NDIS_STATUS_SUCCESS)
		{
			returnStatus = STATUS_SUCCESS;
		}
		else
		{
			//
			// this is not completely correct, as we are converting an NDIS_STATUS to a NTSTATUS
			//
			returnStatus = Status;

		}
	}

	if (returnStatus == STATUS_SUCCESS)
	{
		ULONG localNumOpenedInstances;	
		//
		// complete the open
		//
		localNumOpenedInstances = InterlockedIncrement(&g_NumOpenedInstances);

		TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Opened Instances: %u", localNumOpenedInstances);

		// Get the absolute value of the system boot time.
		// This is used for timestamp conversion.
		TIME_SYNCHRONIZE(&G_Start_Time);

		returnStatus = NPF_GetDeviceMTU(Open, Irp, &Open->MaxFrameSize);

		if (!NT_SUCCESS(returnStatus))
		{
			//
			// Close the binding
			//
			NPF_CloseBinding(Open);
		}
	}

	if (!NT_SUCCESS(returnStatus))
	{
		NPF_ReleaseOpenInstanceResources(Open);
		//
		// Free the open instance itself
		//
		ExFreePool(Open);
		
	}
	else
	{
		//  Save or open here
		IrpSp->FileObject->FsContext=Open;
	}

	Irp->IoStatus.Status = returnStatus;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	TRACE_EXIT();
	return returnStatus;
}
예제 #13
0
bool KLUPD::HttpProtocol::switchAuthorization(const Path &fileName, const Path &relativeUrlPath,
                const DownloadProgress::AuthorizationTarget &authorizationTarget, const Address &proxyAddress,
                bool &authorizationTypeSwitched,
                bool &ntlmAuthorizationTriedAlready)
{
    authorizationTypeSwitched = false;
    const AuthorizationType currentAuthorizationType = m_authorizationDriver.currentAuthorizationType();

    if(!m_downloadProgress.authorizationTargetEnabled(authorizationTarget))
    {
        TRACE_MESSAGE2("Failed to switch authorization by product '%s'", DownloadProgress::toString(authorizationTarget).c_str());
        return false;
    }

    // authorization needed
    bool needUpdateCredentials = false;
    const bool switchedToNextAuthorizationSuccess = m_authorizationDriver.switchToNextAuthorization(needUpdateCredentials,
        ntlmAuthorizationTriedAlready);

    // report authorization failed
    if(!switchedToNextAuthorizationSuccess || needUpdateCredentials)
    {
        if(m_authorizationDriver.credentials().userName().empty())
            informAuthorizationFailed(authorizationTarget, relativeUrlPath + fileName, proxyAddress.BuildURI().toWideChar());
        else
        {
            informAuthorizationFailed(authorizationTarget, relativeUrlPath + fileName,
                m_authorizationDriver.credentials().userName() + L"@" + proxyAddress.BuildURI().toWideChar());
        }
    }

    if(!switchedToNextAuthorizationSuccess)
        return false;

    if(needUpdateCredentials)
    {
        Credentials newCredentials = m_authorizationDriver.credentials();
        // proxy authorization failed, asking credentials to authenticate on proxy
        if(!m_downloadProgress.requestAuthorizationCredentials(newCredentials))
        {
            TRACE_MESSAGE("User cancelled HTTP authorization");
			// Treat cancel as "don't use credentials at all"
            //m_authorizationDriver.resetNtlmState();
			newCredentials.cancel( true );
			m_authorizationDriver.credentials( newCredentials );
            m_authorizationDriver.currentAuthorizationType(noAuthorization);

            // reset authorization to initial state to keep object consistency
            bool needUpdateCredentials = false;
            bool ntlmAuthorizationTriedAlready = false;
            m_authorizationDriver.switchToNextAuthorization(needUpdateCredentials, ntlmAuthorizationTriedAlready);
            return false;
        }
        // no credentials specified
        if(newCredentials.userName().empty())
        {
            TRACE_MESSAGE("Credentials to authenticate on proxy were asked, but not obtained from Product: user name is empty");
            return false;
        }

        TRACE_MESSAGE2("Credentials to authenticate on proxy were asked, user name provided is '%S'",
            newCredentials.userName().toWideChar());

        m_authorizationDriver.credentials(newCredentials);
    }

    authorizationTypeSwitched = currentAuthorizationType != m_authorizationDriver.currentAuthorizationType();
    return true;
}
예제 #14
0
bool Ini_UpdaterLists::processChangedFiles(const STRING &rollbackFolder, const bool validLocalFilesForRollback)
{
    // Ini updater can not perform rollback in retranslation mode
    if(m_retranslation)
        return false;

    if(!validLocalFilesForRollback)
    {
        TRACE_MESSAGE("Rollback is not created, because inconsistent bases set was locally before update operation started");
        removeRollbackSection();
        return false;
    }
    
    TRACE_MESSAGE("Saving rollback file list");
    
    FileVector updateList;
    
    // set correct status for all entries that have changed
    std::string rollbackTrace;
    for(size_t index = 0; index < m_changedFiles.size(); ++index)
    {
        // entry copy, because size, signature, and hash tags are not valid here.
        //  There are values not for rollback, but values for new files
		FileInfo entryCopy;
        entryCopy.m_filename = m_changedFiles[index].m_filename;
        entryCopy.m_localPath = m_changedFiles[index].m_localPath;

		entryCopy.m_rollbackChange;
        switch(m_changedFiles[index].m_transactionInformation.m_changeStatus)
		{
		case FileInfo::added:
			entryCopy.m_rollbackChange = SS_KEY_RecentStatusAdded;
			break;

		case FileInfo::deleted:
			entryCopy.m_rollbackChange = SS_KEY_RecentStatusDeleted;
			break;
		
		case FileInfo::modified:
			entryCopy.m_rollbackChange = SS_KEY_RecentStatusModified;
			break;

		default:
            // do not write to rollback settings storage unchanged files
            continue;
		}

        // calculate MD5 for consistency check to restore changed and deleted files
        if((entryCopy.m_rollbackChange != SS_KEY_RecentStatusAdded)
            && !calcMD5Hash(STRING(rollbackFolder + entryCopy.m_filename).to_string().c_str(), entryCopy.m_md5))
        {
            TRACE_MESSAGE2("Rollback is not created, failed to calculate md5 for '%s'", (rollbackFolder + entryCopy.m_filename).to_string().c_str());
            return false;
        }
		updateList.push_back(entryCopy);

        if(index != 0)
            rollbackTrace += ", ";
        if(!(index % 15))
            rollbackTrace += "\n\t";
        rollbackTrace += entryCopy.m_filename.to_string() + " " + entryCopy.m_rollbackChange.to_string().c_str();
    }

    TRACE_MESSAGE2("Saving rollback files: %s", rollbackTrace.c_str());
    
    // saving rollback information
    if(!saveRollbackInfo(updateList))
    {
        TRACE_MESSAGE("Failed to save rollback file list");
        return false;
    }
    
    TRACE_MESSAGE("Rollback file list saved successfully");
    return true;
}
예제 #15
0
KLUPD::CoreError KLUPD::AdministrationKitProtocol::getFile(
    const Path &fileName, const Path &localPath, const Path &relativeUrlPathIn,
    const bool useMasterAdministrationServer)
{
#ifdef DISABLE_AK_FILETRANSFER
    TRACE_MESSAGE("Administration Kit Transport is not implemented");
    return CORE_DOWNLOAD_ERROR;
#else
    // skip initial slash in relative URL path
    Path relativeUrlPath = relativeUrlPathIn;
    if(!relativeUrlPath.empty()
        && (relativeUrlPath[0] == L'\\' || relativeUrlPath[0] == L'/'))
    {
        relativeUrlPath = relativeUrlPath.toWideChar() + 1;   
    }

    const Path path = relativeUrlPath + fileName;

    ///////////////////////////////////////////////
    /// checking current state and parameters
    const CoreError connectionResult = setupLowLevelConnectionIfNeed(useMasterAdministrationServer);
    if(connectionResult != CORE_NO_ERROR)
    {
        TRACE_MESSAGE2("Failed to setup connection to Administration Server, result '%S'",
            toString(connectionResult).toWideChar());
        return connectionResult;
    }


    ///////////////////////////////////////////////
    /// receiving data by portions
    size_t regettingPosition = LocalFile(localPath + fileName).size();
    AutoStream destinationFile(pLog);
    while(true)
    {
        // check if request should be cancelled
        if(m_downloadProgress.checkCancel())
        {
            TRACE_MESSAGE2("File transfer cancelled '%S'", path.toWideChar());
            return CORE_CANCELLED;
        }

        const long localBufferSize = 65536;
        std::vector<unsigned char> localBuffer(localBufferSize, 0);

        int bytesRead = 0;
        m_downloadProgress.updateSpeedStartTimer();
        const KLFT::FileOpeartionResult getChunkResult = m_adminKitTransprot->GetFileChunk(
            path.toWideChar(),
            regettingPosition,
            &localBuffer[0], localBuffer.size(),
            bytesRead);
        m_downloadProgress.updateSpeedStopTimer();


        // a portion of file got successfully
        if(getChunkResult == KLFT::FR_Ok || getChunkResult == KLFT::FR_OkDownloaded)
        {
            const CoreError saveDataToFileResult = saveDataToFile(
                localPath + fileName,
                &localBuffer[0],
                bytesRead, regettingPosition != 0, destinationFile, pLog);
            if(!isSuccess(saveDataToFileResult))
            {
                TRACE_MESSAGE3("Failed to write data obtained from Administration Server to file '%S', result '%S'",
                    path.toWideChar(), toString(saveDataToFileResult).toWideChar());
                return saveDataToFileResult;
            }

            regettingPosition += bytesRead;
            m_downloadProgress.bytesTransferred(bytesRead);

            // file has been completely downloaded
            if(getChunkResult == KLFT::FR_OkDownloaded)
                return CORE_NO_ERROR;

            continue;
        }

        TRACE_MESSAGE5("Failed to obtain file chunk from Administration Server, file '%S', result '%s', bytes read %d, current position %d",
            path.toWideChar(), toString(getChunkResult).c_str(), bytesRead, regettingPosition);

        if(getChunkResult == KLFT::FR_Timeout)
        {
            // TODO check if time out is over and error should be returned
            continue;
        }

        // error while download happened
        switch(getChunkResult)
        {
        // invalid AdminKit Transport identifier: either receiver was deleted or connect was already called for this receiver
        case KLFT::FR_WrongReceiverId:
            return CORE_AK_WrongReceiverId;

        // invalid arguments for AdminKit Transport
           // wrong offset is requested, consider file is downloaded and signature should be checked
        case KLFT::FR_WrongArguments:
            {            // TODO: this is *work around* about the problem that AdminKit returns
                return CORE_NO_ERROR;    //  FR_WrongArguments code in case source contains
                                        //  valid file in target download folder
                                      // this code can be deleted when problem is fixed in AdminKit
            }

        // file not found on AdminKit server
        case KLFT::FR_FileNotFound:
            return CORE_NO_SOURCE_FILE;

        // AdminKit transport file receive error
        case KLFT::FR_ErrorInOperation:
            return CORE_AK_ErrorInOperation;

        // unknown AdminKit transport receive operation error
        default:
            return CORE_AK_UnknownError;
        }
    }
#endif  // DISABLE_AK_FILETRANSFER
}
예제 #16
0
KLUPD::CoreError KLUPD::HttpProtocol::httpRequestAttempt(
    const Path &fileNameIn,
    const Path &relativeUrlPathIn,
    const Address &serverAddressIn, const std::string &userAgent,
    const bool useProxy, const Address &proxyAddressIn,
    const AuthorizationTypeList &proxyAuthorizationMethods,
    const size_t regettingPosition)
{
    size_t infiniteRedirectLoop = 0;

    Path fileName = fileNameIn;
    Path relativeUrlPath = relativeUrlPathIn;
    Address serverAddress = serverAddressIn;
    Address proxyAddress = proxyAddressIn;

    m_regettingPosition = regettingPosition;

    // cache for next iteration generate request
     // at first attempt the target is not known, but proxy server target is used,
     //  because of possible protection from client for authorization on server
    DownloadProgress::AuthorizationTarget authorizationTarget = DownloadProgress::proxyServer;


    ////////////////////
    // the State flags agains proxies that close connection after authorization switch.
    //  There are proxies (e.g. Squid/2.4.STABLE7) which deals in next way:
    // *** Client -> Server:  GET file
    // *** Server -> Client: HTTP 407 / Proxy-Connection: keep-alive
    // *** Server closes connection
    // *** Client -> Server GET 407
    //
    // Here are 3 flags to track such situations, that previous response is received,
    //  BUT then server closes connection
    bool previousResponseReceived = false;
    bool authorizationTypeSwitched = false;
    bool requestHasAlreadyBeenRepeated = false;
    ////////////////////


    ////////////////////
    // in case proxy server requires authorization, but sends incorrect (from HTTP)
    //   code for authorization failure in next way
    // *** Client -> Server:  GET file
    // *** Server -> Client: HTTP 407 / Proxy-Authorization: NTLM
    // *** Client -> Server GET  / Proxy-Authorization: NTLM
    // *** Server -> Client: HTTP 502 (or 403 or other code)
    // *** here is authorization state is forgotten, because 502 request does NOT contain "Proxy-Authorization: NTLM"
    // *** Client ask from product new credentials
    // *** Client -> Server GET  / Proxy-Authorization: NTLM (with new credentials)
    bool authorizationWasNeededOnProxy = false;

    // it makes no sence to try Ntlm without credentials authorization type,
     // because this authorization type does not depend on provided credentials
    bool ntlmAuthorizationTriedAlready = false;

    int lastHttpCode = 0;

    for(size_t protectionAgainstCyclingCounter = 100; protectionAgainstCyclingCounter; --protectionAgainstCyclingCounter)
    {
        const CoreError connectionResult = setupLowLevelConnectionIfNeed(useProxy, useProxy ? proxyAddress : serverAddress, proxyAuthorizationMethods);
        if(connectionResult != CORE_NO_ERROR)
        {
            TRACE_MESSAGE2("Failed to setup connection to HTTP Server, result '%S'",
                toString(connectionResult).toWideChar());
            return connectionResult;
        }

        // make proxy authorization header
        std::string proxyAuthorizationHeader;
        if(!m_authorizationDriver.makeProxyAuthorizationHeader(proxyAuthorizationHeader)
            // we know authorization methods supported by proxy server
            || ((m_authorizationDriver.currentAuthorizationType() == noAuthorization) && !m_authorizationDriver.supportedAuthorizationTypesByServer().empty()))
        {
            if(!switchAuthorization(fileName, relativeUrlPath, authorizationTarget, proxyAddress,
                authorizationTypeSwitched, ntlmAuthorizationTriedAlready))
            {
                if(lastHttpCode)
                    return HttpHeader::convertHttpCodeToUpdaterCode(lastHttpCode);

                return useProxy ? CORE_PROXY_AUTH_ERROR : CORE_SERVER_AUTH_ERROR;
            }

            // try other authorization type
            continue;
        }

        HTTPRequestBuilder requestBuilder(m_method);
        const std::vector<unsigned char> requestBuffer = requestBuilder.generateRequest(
            fileName,
            relativeUrlPath,
            useProxy,
            serverAddress,
            userAgent,
            proxyAuthorizationHeader,
            m_regettingPosition,
            m_postData);

        TRACE_MESSAGE2("Sending HTTP request\n%s", requestBuilder.toString().c_str());

        if(requestBuffer.empty())
        {
            TRACE_MESSAGE("Failed to send empty HTTP request");
            return CORE_DOWNLOAD_ERROR;
        }

        const CoreError sendRequestResult = m_socket.send(reinterpret_cast<const char *>(&requestBuffer[0]), requestBuffer.size());
        if(sendRequestResult != CORE_NO_ERROR)
        {
            TRACE_MESSAGE2("Failed to send HTTP request, error %S", toString(sendRequestResult).toWideChar());
            if((sendRequestResult == CORE_REMOTE_HOST_CLOSED_CONNECTION)
                && previousResponseReceived && authorizationTypeSwitched && !requestHasAlreadyBeenRepeated)
            {
                TRACE_MESSAGE("Repeating the same request (without authorization switch), because server was reachable, but unexpectedly closed connection");
                requestHasAlreadyBeenRepeated = true;
                continue;
            }

            return sendRequestResult;
        }

        HttpHeader httpHeader;
        const CoreError receiveResponseAndDataResult = receiveResponseAndData(httpHeader);

        const bool needCloseConnection = httpHeader.needCloseConnection(useProxy)
            || (receiveResponseAndDataResult != CORE_NO_ERROR);

        if(needCloseConnection)
        {
            TRACE_MESSAGE2("Closing connection to HTTP server, get file result %S",
                toString(receiveResponseAndDataResult).toWideChar());
            closeSession();
        }

        if(receiveResponseAndDataResult != CORE_NO_ERROR)
        {
            TRACE_MESSAGE2("Failed to receive HTTP response, error %S",
                toString(receiveResponseAndDataResult).toWideChar());

            if((receiveResponseAndDataResult == CORE_REMOTE_HOST_CLOSED_CONNECTION)
                && previousResponseReceived && authorizationTypeSwitched && !requestHasAlreadyBeenRepeated)
            {
                TRACE_MESSAGE("Repeating the same request (without authorization switch), because server was reachable, but unexpectedly closed connection");
                requestHasAlreadyBeenRepeated = true;
                continue;
            }
            return receiveResponseAndDataResult;
        }
        previousResponseReceived = true;
        requestHasAlreadyBeenRepeated = false;

        m_authorizationDriver.authorized(
            // authorization information is reset in case connection is to be closed
            !needCloseConnection
            // authorization success in case file received or successful redirect
            && (httpHeader.isFile()
                 || httpHeader.redirectRequired()
                 || httpHeader.fileNotFound()));

        if(httpHeader.isFile())
        {
            // in case proxy server by some ocassion desided to close
            //  connection after successful file receive event
            if(needCloseConnection)
                m_authorizationDriver.resetNtlmState();

            return CORE_NO_ERROR;
        }

        authorizationTarget = httpHeader.authorizationTarget();
		authorizationWasNeededOnProxy = !proxyAuthorizationHeader.empty();
        lastHttpCode = httpHeader.httpCode();

        // authorization error
        if(httpHeader.authorizationNeeded())
        {
            authorizationWasNeededOnProxy = (authorizationTarget == DownloadProgress::proxyServer);
            if(!switchAuthorization(fileName, relativeUrlPath, httpHeader.authorizationTarget(), proxyAddress,
                authorizationTypeSwitched, ntlmAuthorizationTriedAlready))
            {
                return httpHeader.convertHttpCodeToUpdaterCode();
            }
        }
        // redirect needed
        else if(httpHeader.redirectRequired())
        {
            // protection against infinite loop (according to RFC 2616)
            if(++infiniteRedirectLoop > 2)
            {
                TRACE_MESSAGE2("Infinite redirection loop detected for location '%S'",
                    httpHeader.m_location.toWideChar());
                return CORE_NO_SOURCE_FILE;
            }

            if(httpHeader.m_location.isAbsoluteUri())
                serverAddress.parse(httpHeader.m_location);
            else
            {
                serverAddress.parse(toProtocolPrefix(serverAddress.m_protocol) + serverAddress.m_hostname
                    + serverAddress.m_path + httpHeader.m_location);
                serverAddress.m_path.correctPathDelimiters();
            }

            fileName = serverAddress.m_fileName;
            relativeUrlPath.erase();

            TRACE_MESSAGE3("HTTP Redirect to file '%S' on server %S",
                fileName.toWideChar(), serverAddress.toString().toWideChar());
        }
        // known HTTP results
        else if(httpHeader.resourceUnavailable()
            || httpHeader.fileNotFound())
        {
            return httpHeader.convertHttpCodeToUpdaterCode();
        }
        // retry authorization with other credentials in case Forbidden
         // code received after successful authorization has happened
        else if(httpHeader.retryAuthorization(authorizationWasNeededOnProxy)
            && treat_403_502_httpCodesAs407())
        {
            if(!switchAuthorization(fileName, relativeUrlPath, DownloadProgress::proxyServer,
                proxyAddress, authorizationTypeSwitched, ntlmAuthorizationTriedAlready))
            {
                TRACE_MESSAGE2("Authorization was needed, but error HTTP code '%d' received and switch to next authorization type failed",
                    httpHeader.httpCode());
                return httpHeader.convertHttpCodeToUpdaterCode();
            }
            TRACE_MESSAGE3("Authorization was needed, but error HTTP code '%d' received, try next authorization type '%S'",
                httpHeader.httpCode(),
                toString(m_authorizationDriver.currentAuthorizationType()).toWideChar());
        }
        else
        {
            // processing HTTP code is not implemented
            m_authorizationDriver.resetAuthorizatoinState(proxyAuthorizationMethods);
            return httpHeader.convertHttpCodeToUpdaterCode();
        }
    }

    // Authorization state machine is complex and may contain bug,
     //  that is why protection against infinite loop is implemented
    TRACE_MESSAGE3("Error in HTTP authorization state implementation: credentials '%S', current authorization type '%S'",
        m_authorizationDriver.credentials().toString().toWideChar(),
        toString(m_authorizationDriver.currentAuthorizationType()).toWideChar());
    return CORE_DOWNLOAD_ERROR;
}
예제 #17
0
KLUPD::CoreError KLUPD::HttpProtocol::receiveResponseAndData(HttpHeader &httpHeader)
{
    bool httpHeaderFullyReceived = false;

    const char *entity = 0;
    size_t total_entity_bytes = 0;

    const size_t httpBufferSize = 65536;
    char httpBuffer[httpBufferSize + 1];
    memset(httpBuffer, 0, httpBufferSize + 1);
    size_t currentOffsetInHttpBuffer = 0;

    while(true)
    {
        CoreError receiveResult = CORE_NO_ERROR;
        const int bytesReceived = m_socket.recv(httpBuffer + currentOffsetInHttpBuffer,
            httpBufferSize - currentOffsetInHttpBuffer, receiveResult);
        currentOffsetInHttpBuffer += bytesReceived;

        // according to RFC 2616, 4.4 point 5: connection close may indicate
         // file transfer completion if Range or Content-Length is not specified
        if(httpHeaderFullyReceived
            && (receiveResult == CORE_REMOTE_HOST_CLOSED_CONNECTION)
            && (httpHeader.m_contentLength == -1))
        {
            TRACE_MESSAGE2("HTTP connection closed by server, no Content-Length field, consider file is obtained, size %d bytes", currentOffsetInHttpBuffer);
            return CORE_NO_ERROR;
        }
        if(receiveResult != CORE_NO_ERROR)
            return receiveResult;

        // size of entity part that is currently in buffer
        size_t entityBytes = 0;
        if(httpHeaderFullyReceived)
        {
            // http header was obtained on previous iteration
            entityBytes = currentOffsetInHttpBuffer;
            entity = httpBuffer;
        }
        else
        {
            // HTTP header has not been obtained yet, check if it is in httpBuffer
            const char *const headerEndMarker = "\r\n\r\n";
            char *const headerLastPosition = strstr(httpBuffer, headerEndMarker);

            if(!headerLastPosition)
            {
                // no end-of-header marker found
                if(httpBufferSize < currentOffsetInHttpBuffer)
                {
                    TRACE_MESSAGE3("Error: response HTTP header can not fit into %d-bytes buffer (already received %d bytes)",
                        httpBufferSize, currentOffsetInHttpBuffer);
                    return CORE_DOWNLOAD_ERROR;
                }

                // continue reading from socket
                continue;
            }

            httpHeaderFullyReceived = true;

            // pass to applicaiton data included into HTTP header
            fullHttpHeaderReceived(std::string(httpBuffer, headerLastPosition + strlen(headerEndMarker)));

            *headerLastPosition = 0;
            TRACE_MESSAGE2("HTTP response received:\n%s", HTTPRequestBuilder::toString(httpBuffer).c_str());

            // Parse HTTP header, data loaded into httpHeader structure
            if(!httpHeader.load(httpBuffer, m_authorizationDriver))
            {
                TRACE_MESSAGE("Failed to parse HTTP response header");
                return CORE_DOWNLOAD_ERROR;
            }

            // it is expected 206 code in case regetting is used
            if(m_regettingPosition && (httpHeader.httpCode() == 200))
            {
                TRACE_MESSAGE("It is expected 206 code in case regetting is used, but 200 code is received");
                return CORE_DOWNLOAD_ERROR;
            }

            // data from socket after the HTTP header
            entityBytes = (httpBuffer + currentOffsetInHttpBuffer)  // pointer to the end of received bytes
                - (headerLastPosition + strlen(headerEndMarker));   // pointer to the data (begin of the file)
            entity = entityBytes ? headerLastPosition + strlen(headerEndMarker) : 0;
        }

        total_entity_bytes += entityBytes;

        if(httpHeader.isFile()
            // only header has been received, but data is not received yet
            && entityBytes)
        {
            const CoreError saveDataToFileResult = dataReceived(reinterpret_cast<const unsigned char *>(entity), entityBytes);
            if(!isSuccess(saveDataToFileResult))
            {
                TRACE_MESSAGE2("Failed to write data obtained from HTTP Server, result %S",
                    toString(saveDataToFileResult).toWideChar());
                return saveDataToFileResult;
            }
            m_regettingPosition += entityBytes;
        }

        //////////////////////////////////////////////////////////////////////////
        /// check if complete file is downloaded

        // Content-Length header presents
        if(httpHeader.m_contentLength == -1)
        {
            TRACE_MESSAGE("HTTP chunk received (header does not contain the content-length field), continue receiving message until connection is closed by remote peer");
        }
        else if(static_cast<size_t>(httpHeader.m_contentLength) <= total_entity_bytes)
        {
            TRACE_MESSAGE2("HTTP message successfully received, content length = %d", httpHeader.m_contentLength);
            return CORE_NO_ERROR;
        }

        currentOffsetInHttpBuffer = 0;
        entityBytes = 0;
    }
}
예제 #18
0
KLUPD::CoreError KLUPD::UpdateInfo::parse(const Path &path,
                                          FileInfo &fileInfo,
                                          const ChangeStateCheck &changeStateCheck,
                                          const FileVector &localFilesToCheckAgainst,
                                          const bool suppressSuccessLogMessages)
{
    // index is already parsed, files already attached
    if(fileAlreadyParsed(fileInfo))
        return CORE_NO_ERROR;

    const Path fullFileName = path + fileInfo.m_filename;

    if(!suppressSuccessLogMessages)
        TRACE_MESSAGE2("Parsing XML index file '%S'", fullFileName.toWideChar());

    std::vector<unsigned char> buffer;
    const CoreError readFileResult = LocalFile(fullFileName, pLog).read(buffer);
    if(!KLUPD::isSuccess(readFileResult))
    {
        TRACE_MESSAGE3("Failed to read XML index file '%S', result '%S'",
            fullFileName.toWideChar(), KLUPD::toString(readFileResult).toWideChar());
        return readFileResult;
    }
    if(buffer.empty())
    {
        TRACE_MESSAGE3("Index XML file '%S' is corrupted, file size is %d", fullFileName.toWideChar(), buffer.size());
        return CORE_UPDATE_DESCRIPTION_DAMAGED;
    }

    // a file list obtained from XML
    FileVector fileList;
    IndexFileXMLParser xmler(fileInfo.m_filename.m_value, fileList, m_signature6Checker, fileInfo.m_relativeURLPath, m_retranslationMode, m_callbacks, pLog);

    XmlReader xmlReader(reinterpret_cast<const char *>(&buffer[0]), buffer.size());
    if(!xmler.parseXMLRecursively(xmlReader, 0)
        || fileList.empty())
    {
        TRACE_MESSAGE3("\tXML file parse error '%S', file number found %d",
            fullFileName.toWideChar(), fileList.size());
        return CORE_UPDATE_DESCRIPTION_DAMAGED;
    }
    m_parsedIndexCache.push_back(fileInfo);

    xmler.GetUpdateDate(fileInfo.m_strUpdateDate);
    xmler.GetBlackDate(fileInfo.m_strBlackDate);

    // save variables to write into settings storage
    std::vector<UpdatedSettings> updatedSettings = xmler.updatedSettings();
    m_updatedSettings.insert(m_updatedSettings.end(), updatedSettings.begin(), updatedSettings.end());

    // copy to match list only those items which suits download criteria
    for(FileVector::iterator fileIter = fileList.begin(); fileIter != fileList.end(); ++fileIter)
    {
        // check download filters criteria should be performed
        NoCaseString reasonNotMatch;
        if(!matchesSettings(reasonNotMatch, *fileIter))
        {
            if(!suppressSuccessLogMessages)
            {
                TRACE_MESSAGE3("\tFile filtered, download criteria does not matches: '%S', %S",
                    reasonNotMatch.toWideChar(), fileIter->toString().toWideChar());
            }
            continue;
        }

        // check download mandatory criteria
        reasonNotMatch.erase();
        if(!isEntryRequired(reasonNotMatch, *fileIter, m_filterFlags))
        {
            if(!suppressSuccessLogMessages)
            {
                TRACE_MESSAGE3("\tFile filtered, mandatory criteria does not matches: '%S', %S",
                    reasonNotMatch.toWideChar(), fileIter->toString().toWideChar());
            }
            continue;
        }

        // setup transaction folders
        fileIter->m_transactionInformation.m_currentLocation = m_callbacks.productFolder(*fileIter, m_retranslationMode);
        fileIter->m_transactionInformation.m_newLocation = m_callbacks.temporaryFolder(*fileIter);
        NoCaseString statusExplanations;
        fileIter->m_transactionInformation.m_changeStatus = getFileStatusAgainstLocal(*fileIter,
            changeStateCheck, localFilesToCheckAgainst, statusExplanations);

        // insert file with filtering duplicates
        bool fileDuplicate = false;

        // insert black list into the beginning of list, because it should be checked before downloading other bases
        if(fileIter->m_type == FileInfo::blackList)
            m_matchFileList.insertNewInTheBeginOfListOrUpdateTheSame(*fileIter, *fileIter, fileDuplicate, m_retranslationMode);
        else
            m_matchFileList.insertNewOrUpdateTheSame(*fileIter, *fileIter, fileDuplicate, m_retranslationMode);


        if(!suppressSuccessLogMessages)
        {
            // to avoid empty brackets output to trace
            if(!statusExplanations.empty())
                statusExplanations = NoCaseString(L"(") + statusExplanations + L")";

            if(fileDuplicate)
            {
                TRACE_MESSAGE3("\tDuplicate file information updated: %S %S",
                    fileIter->toString().toWideChar(), statusExplanations.toWideChar());
            }
            else
            {
                TRACE_MESSAGE3("\tFile matches download criteria: %S %S",
                    fileIter->toString().toWideChar(), statusExplanations.toWideChar());
            }
        }
    }

    return CORE_NO_ERROR;
}