bool clEditorConfig::LoadForFile(const wxFileName& filename, wxFileName& editorConfigFile)
{
    editorConfigFile = wxFileName(filename.GetPath(), ".editorconfig");

    bool foundFile = false;
    while(editorConfigFile.GetDirCount()) {
        if(editorConfigFile.FileExists()) {
            foundFile = true;
            break;
        }
        editorConfigFile.RemoveLastDir();
    }

    if(!foundFile) return false;

    wxString content;
    if(!FileUtils::ReadFileContent(editorConfigFile, content)) {
        clDEBUG() << "Failed to read file:" << editorConfigFile << clEndl;
        return false;
    }

    clEditorConfigSection section;
    m_sections.push_back(section);
    clEditorConfigSection* cursection = &(m_sections.back());
    wxUnusedVar(cursection); // for debug purposes
    wxArrayString lines = ::wxStringTokenize(content, "\n", wxTOKEN_STRTOK);
    for(size_t i = 0; i < lines.size(); ++i) {
        // Remove comments
        wxString strLine = lines.Item(i);
        strLine = strLine.BeforeFirst('#');
        strLine = strLine.BeforeFirst(';');

        strLine.Trim().Trim(false);

        if(strLine.IsEmpty()) continue;

        // Process the line
        if(strLine.StartsWith("[") && strLine.EndsWith("]")) {
            strLine.RemoveLast().Remove(0, 1); // remove the []
            clEditorConfigSection section;
            section.patterns = ProcessSection(strLine);
            m_sections.push_back(section);
            cursection = &(m_sections.back());

        } else {
            ProcessDirective(strLine);
        }
    }
    clDEBUG() << "Using .editorconfig file:" << editorConfigFile << clEndl;
    return true;
}
wxArrayString clEditorConfig::ProcessSection(wxString& strLine)
{
    eEditorConfigState state = kEC_STATE_NORMAL;

    clEditorConfigTreeNode* tree = new clEditorConfigTreeNode;
    std::vector<clEditorConfigTreeNode*> trees;
    trees.push_back(tree);

    wxString curpattern;
    while(!strLine.IsEmpty()) {
        switch(state) {
        case kEC_STATE_NORMAL: {
            wxChar ch = strLine.at(0);
            strLine.Remove(0, 1);
            switch(ch) {
            case '{':
                state = kEC_STATE_IN_CURLYGRP;
                break;
            case '[':
                state = kEC_STATE_IN_SQUAREGRP;
                break;
            case ',':
                // new pattern
                if(!curpattern.IsEmpty()) {
                    tree->Add(curpattern);

                    tree = new clEditorConfigTreeNode;
                    trees.push_back(tree);
                    curpattern.clear();
                }
                break;
            default:
                curpattern << ch;
                break;
            }
            break;
        }
        case kEC_STATE_IN_CURLYGRP: {
            // if we got something so far, add it before we continue
            if(!curpattern.IsEmpty()) {
                tree->Add(curpattern);
                curpattern.clear();
            }

            // read the buffer until we hit the closing brace
            wxString buffer;
            if(!ReadUntil('}', strLine, buffer)) {
                return wxArrayString();
            }
            state = kEC_STATE_NORMAL;
            wxArrayString groupPatterns = ProcessSection(buffer);
            tree->Add(groupPatterns);
            break;
        }
        case kEC_STATE_IN_SQUAREGRP: {
            wxString buffer;
            if(!ReadUntil(']', strLine, buffer)) {
                return wxArrayString();
            }
            state = kEC_STATE_NORMAL;
            break;
        }
        }
    }

    // Remainder
    if(!curpattern.IsEmpty()) {
        tree->Add(curpattern);
    }

    wxArrayString res;
    for(size_t i = 0; i < trees.size(); ++i) {
        wxArrayString patterns;
        trees.at(i)->GetPatterns(patterns);
        res.insert(res.end(), patterns.begin(), patterns.end());
        delete trees.at(i);
    }

    // Loop over the array and change "**" => "*"
    for(size_t i = 0; i < res.size(); ++i) {
        res.Item(i).Replace("**", "*");
    }
    return res;
}
BOOL CRemoteLoader::ProcessSections( PVOID BaseAddress, PVOID RemoteAddress, BOOL MapPEHeader )
{
	IMAGE_NT_HEADERS* ImageNtHeaders = ToNts( BaseAddress );

	if( ImageNtHeaders == NULL ) 
		return FALSE;

	// Write PE header

	if( MapPEHeader )
	{
		if( WriteProcessMemory( GetProcess(), RemoteAddress, BaseAddress, ImageNtHeaders->OptionalHeader.SizeOfHeaders, NULL ) == FALSE )
		{
			DebugShout( "[ProcessSections] Failed to map PE header!" );
		}
		else
		{
			DebugShout( "[ProcessSections] Mapped PE Header successfully!" );
		}
	}
	else
	{
		DebugShout( "[ProcessSections] PE Header mapping disabled, skipping." );
	}

	// Write individual sections

	PIMAGE_SECTION_HEADER ImageSectionHeader = ( PIMAGE_SECTION_HEADER )
		( ( ( ULONG_PTR ) &ImageNtHeaders->OptionalHeader ) + ImageNtHeaders->FileHeader.SizeOfOptionalHeader );

	for( DWORD i = 0; i < ImageNtHeaders->FileHeader.NumberOfSections; i++ )
	{
		ULONG Protection = GetSectionProtection( ImageSectionHeader[ i ].Characteristics );

		if( !_stricmp( ".reloc", ( CHAR* ) ImageSectionHeader[ i ].Name ) )
		{
			DebugShout( "[ProcessSections] Skipping \".reloc\" section." );

			continue; // NOPE
		}

		if( ProcessSection( 
			ImageSectionHeader[ i ].Name,
			BaseAddress,
			RemoteAddress,
			ImageSectionHeader[ i ].PointerToRawData,
			ImageSectionHeader[ i ].VirtualAddress,
			ImageSectionHeader[ i ].SizeOfRawData,
			ImageSectionHeader[ i ].Misc.VirtualSize,
			Protection ) == FALSE )
		{
			DebugShout( "[ProcessSections] Failed %s", ImageSectionHeader[ i ].Name );
		}
		else
		{
			DebugShout( "[ProcessSections] Success %s", ImageSectionHeader[ i ].Name );
		}
	}

	return TRUE;
}