2015年5月24日星期日

Oracle 11g NetworkConfig

首先是监听的配置文件listener.ora。

在SID_LIST_LISTENER中添加一个SID_DESC。注意保留原始部分。
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = $db_name)
      (SID_NAME = $sid_name)
      (ORACLE_HOME = C:\app\Administrator\product\11.2.0\dbhome_1)
    )

  )

修改LISTENER部分中的HOST为外网IP
 LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx )(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )


其次修改tnsname.ora中的部分,增加一个TNS配置信息。
HOST部分需要与 listener.ora中LISTENER部分的HOST相同
TEST =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 10.211.55.17)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = $service_name)
    )
  )

SQL Injection: Time Based Injection

之前一直都不是很了解Time Based的适用场景。
前段时间拿了一个站点,该站点只能用盲注拿下,当初是用sqlmap跑回来的。
而且sqlmap的给出的注入方法是Boolean Based。
后来反反复复思考了很久,发现这个站点其实应该只能用Stacked Query + Time Based拿下。这是今天重新扫的结果。

 (看到截图里的Warning没有,连目标又AntiXSS都发现了。因为确实在该页面的代码里发现了一段对id参数进行AntiXSS处理的代码。大小尖括号这种东西,肯定被HTML编码替换了。)

今天又重新翻了一下webconfig,发现当前数据库连接的用户是sa。直接用stacked query+xp_cmdshell提权就好了= =。还费那么大力气找后台,用上传漏洞

注入点在URL里,参数为id=1
构造id=1'后直接报错,重定向蹈了一个通用错误页面。
构造id=1' and '1'='1后结果同上。
构造id=1-0后显示了一个不包含任何内容的正常页面。

拿下Server以后第一件事情不是跑去提权,而是去翻www目录里对应站点的Source Code。
才发现了问题的所在。
原来id参数被带入的两个sql语句中。

String SqlStr1 = "select * from [news] where id = '" +id + "'";

String SqlStr2 = "select  * from [news]  WHERE (id NOT IN ('" + id + "')) order by  NewsID()";

之前注入构造的参数仅能满足第一个SQL正常执行,但是不能保证第二条SQL正常被执行。
因此无法构造出一个同时满足两条sql语句都正常执行。

这里就会用到Time Based了。因为Time Based只要被带入,就会执行。并产生延时效果。
因为String SqlStr1 = "select * from [news] where id = '" +id + "'";首先被执行,因此只要构造id=1'; WAITFOR DELAY '0:0:5'--
然后观察一下是不是5秒之后才被重定向到通用错误页面,即可判断当前的id是不是一个注入点了。

其实也是今天才发现,当初用来注入的,其实是另一个页面的注入点。一个纯string类型的。

2015年5月12日星期二

Libreoffice的gbuild-to-ide,可生成xcode项目。

当初在mac下做libreoffice时写的,没提交到他们的git。
对应的libreoffice版本不记得了,大致是2015年初的时候的最新版本。
直接保存替换gbuild-to-ide即可。
记得chmod +x一下!
这段py生成的xcode项目不能直接在xcode里编译。
但是整个Project可以直接在xcode里浏览,对应的智能感知也能用。
要编译的话,就在终端里用命令编译吧!
不知道如何在blogger里插入代码,直接就贴上了。

#! /usr/bin/env python3
# -*- Mode: python; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#

import argparse
import os
import os.path
import shutil
import re
import sys
import uuid
import json
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom
import pickle

class GbuildParserState:
    def __init__(self):
        self.target = None
        self.ilib = None
        self.include = []
        self.defs = {}
        self.cxxobjects = []
        self.cxxflags = []
        self.linked_libs = []
        self.include_sys = []


class GbuildLinkTarget:
    def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
        (self.name, self.location, self.include, self.include_sys, self.defs, self.cxxobjects, self.cxxflags,
         self.linked_libs) = (
            name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)

    def short_name(self):
        return self.name

    def is_empty(self):
        return not self.include and not self.defs and not self.cxxobjects and not self.linked_libs

    def __str__(self):
        return '%s at %s with include path: %s, isystem includes: %s, defines: %s, objects: %s, cxxflags: %s and linked libs: %s' % (
            self.short_name(), self.location, self.include, self.include_sys, self.defs, self.cxxobjects,
            self.cxxflags, self.linked_libs)


class GbuildLib(GbuildLinkTarget):
    def __init__(self, name, library, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
        GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
        self.library = library

    def short_name(self):
        """Return the short name of target based on the Library_* makefile name"""
        return 'Library %s' % self.name

    def target_name(self):
        return 'Library_%s' % self.library

    def library_name(self):
        return self.library


class GbuildExe(GbuildLinkTarget):
    def __init__(self, name, executable, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
        GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
        self.executable = executable

    def short_name(self):
        """Return the short name of target based on the Executable_* makefile name"""
        return 'Executable %s' % self.name

    def target_name(self):
        return 'Executable_%s' % self.executable


class GbuildParser:
    makecmdpattern = re.compile('^MAKE_COMMAND := (.*)')
    srcdirpattern = re.compile('^SRCDIR = (.*)')
    builddirpattern = re.compile('^BUILDDIR = (.*)')
    instdirpattern = re.compile('^INSTDIR = (.*)')
    binpathpattern = re.compile('^GPERF = (.*)gperf(.exe)?')
    libnamespattern = re.compile('^gb_Library_ILIBFILENAMES := (.*)')
    exenamepattern = re.compile('^gb_Executable_FILENAMES_FOR_BUILD := (.*)')
    rulepattern = re.compile('^(.+?):( .*)?$')
    libpattern = re.compile('#  [a-z]+ to execute \(from [\'`](.*)/Library_(.*)\.mk\', line [0-9]*\):')
    exepattern = re.compile('#  [a-z]+ to execute \(from [\'`](.*)/Executable_(.*)\.mk\', line [0-9]*\):')
    includepattern = re.compile('-I(\S+)')
    isystempattern = re.compile('-isystem\s*(\S+)')
    defspattern = re.compile('# DEFS := (.*)')
    cxxpattern = re.compile('# CXXOBJECTS := (.*)')
    linkedlibspattern = re.compile('# LINKED_LIBS := (.*)')
    ilibpattern = re.compile('# ILIBTARGET := (.*)')
    warningpattern = re.compile('-W\S+')

    def __init__(self):
        (self.makecmd, self.srcdir, self.builddir, self.instdir, self.libs,
         self.exes, self.libnames, self.exenames) = ('', '', '', '', [], [], {}, {})

    def __mapping_to_dict(self, mapping):
        mapping_dict = {}
        for item in mapping.split(' '):
            library, target = item.split(':')
            mapping_dict[target] = library
        return mapping_dict

    def _parse_hash(self, line, state):
        libmatch = GbuildParser.libpattern.match(line)
        if libmatch:
            libname = self.libnames.get(state.ilib, None)
            self.libs.append(
                GbuildLib(libmatch.group(2), libname, libmatch.group(1),
                          state.include, state.include_sys, state.defs, state.cxxobjects,
                          state.cxxflags, state.linked_libs))
            state = GbuildParserState()
            return state
        exematch = GbuildParser.exepattern.match(line)
        if exematch:
            exename = self.exenames.get(state.target, None)
            self.exes.append(
                GbuildExe(exematch.group(2), exename, exematch.group(1),
                          state.include, state.include_sys, state.defs, state.cxxobjects,
                          state.cxxflags, state.linked_libs))
            state = GbuildParserState()
            return state
        if line.find('# INCLUDE :=') == 0:
            isystemmatch = GbuildParser.isystempattern.findall(line)
            if isystemmatch:
                state.include_sys = isystemmatch
            state.include = [includeswitch.strip() for includeswitch in GbuildParser.includepattern.findall(line) if
                             len(includeswitch) > 2]
            return state
        defsmatch = GbuildParser.defspattern.match(line)
        if defsmatch:
            alldefs = [defswitch.strip()[2:] for defswitch in defsmatch.group(1).split(' ') if len(defswitch) > 2]
            for d in alldefs:
                defparts = d.split('=')
                if len(defparts) == 1:
                    defparts.append(None)
                state.defs[defparts[0]] = defparts[1]
            return state
        cxxmatch = GbuildParser.cxxpattern.match(line)
        if cxxmatch:
            state.cxxobjects = [obj for obj in cxxmatch.group(1).split(' ') if len(obj) > 0]
            return state
        linkedlibsmatch = GbuildParser.linkedlibspattern.match(line)
        if linkedlibsmatch:
            state.linked_libs = linkedlibsmatch.group(1).strip().split(' ')
            return state
        ilibmatch = GbuildParser.ilibpattern.match(line)
        if ilibmatch:
            state.ilib = os.path.basename(ilibmatch.group(1))
            return state
        if line.find('# T_CXXFLAGS :=') == 0:
            state.cxxflags = [cxxflag.strip() for cxxflag in
                              GbuildParser.warningpattern.sub('', line.replace('# T_CXXFLAGS :=', '')).split(' ') if
                              len(cxxflag) > 1]
            return state
        # we could match a lot of other stuff here if needed for integration rpaths etc.
        return state

    def parse(self, gbuildstate):
        state = GbuildParserState()
        for line in gbuildstate:
            if line.startswith('#'):
                state = self._parse_hash(line, state)
            else:
                makecmdmatch = GbuildParser.makecmdpattern.match(line)
                if makecmdmatch:
                    self.makecmd = makecmdmatch.group(1)
                    # FIXME: Hack
                    if self.makecmd == 'make':
                        self.makecmd = '/usr/bin/make'
                    continue
                srcdirmatch = GbuildParser.srcdirpattern.match(line)
                if srcdirmatch:
                    self.srcdir = srcdirmatch.group(1)
                    continue
                builddirmatch = GbuildParser.builddirpattern.match(line)
                if builddirmatch:
                    self.builddir = builddirmatch.group(1)
                    continue
                instdirmatch = GbuildParser.instdirpattern.match(line)
                if instdirmatch:
                    self.instdir = instdirmatch.group(1)
                    continue
                binpathmatch = GbuildParser.binpathpattern.match(line)
                if binpathmatch:
                    self.binpath = binpathmatch.group(1)
                    continue
                rulematch = self.rulepattern.match(line)
                if rulematch:
                    if len(rulematch.groups()) == 2 \
                            and rulematch.group(2) is not None \
                            and ':=' in rulematch.group(2):
                        # Hack to make GNU make >= 4.x happy
                        state = self._parse_hash('#' + rulematch.group(2), state)
                    else:
                        state.target = os.path.basename(rulematch.group(1))
                    continue
                libnamesmatch = GbuildParser.libnamespattern.match(line)
                if libnamesmatch:
                    self.libnames = self.__mapping_to_dict(libnamesmatch.group(1))
                    continue
                exenamesmatch = GbuildParser.exenamepattern.match(line)
                if exenamesmatch:
                    self.exenames = self.__mapping_to_dict(exenamesmatch.group(1))
                    continue
                state = GbuildParserState()
        return self


class IdeIntegrationGenerator:
    def __init__(self, gbuildparser, ide):
        self.gbuildparser = gbuildparser
        self.ide = ide

    def emit(self):
        pass

class XcodeIntegrationGenerator(IdeIntegrationGenerator):
    def indent(self, file, level):
        if level == 0:
            return
        for i in range(0, level):
            file.write(' ')

    def write_object(self, object, file, indent):
        if isinstance(object, int):
            file.write('%d' % object)
        elif isinstance(object, str) and not re.search('[^A-Za-z0-9_]', object):
            file.write('%s' % object)
        elif isinstance(object, str):
            file.write('"%s"' % object)
        elif isinstance(object, dict):
            self.write_dict(object, file, indent)
        elif isinstance(object, list):
            file.write('(')
            for i in object:
                file.write(i)
                if object.index(i) != len(object) -1:
                    file.write(',')

            file.write(')')



    # Write a dictionary out as an "old-style (NeXT) ASCII plist"
    def write_dict(self, dict, file, indent):
        file.write('{')
        file.write('\n')
        for key in dict.keys():
            self.indent(file, indent + 1)
            file.write('%s = ' % key)
            self.write_object(dict[key], file, indent + 1)
            file.write(';\n')
        self.indent(file, indent)
        file.write('}')

    def write_dict_to_plist(self, dict, file):
        file.write('// !$*UTF8*$!\n')
        self.write_dict(dict, file, 0)

    def get_product_type(self, modulename):
        if modulename in self.gbuildparser.libs:
            return 'com.apple.product-type.library.dynamic'
        elif modulename in self.gbuildparser.exes:
            return 'com.apple.product-type.something'

    counter = 0

    def generate_id(self):
        XcodeIntegrationGenerator.counter = XcodeIntegrationGenerator.counter + 1
        return str('X%07x' % XcodeIntegrationGenerator.counter)

    def generate_build_phases(self, modulename):
        result = [self.sourcesBuildPhaseId]
        return result

#targets 必须有()
#projectDirPath, projectRoot必须有""
    def generate_root_object(self, modulename, configurationListId):
        result = {'isa': 'PBXProject',
                  'attributes': {'LastUpgradeCheck': '0500',
                                 'ORGANIZATIONNAME': 'LibreOffice'},
                  'buildConfigurationList': configurationListId,
                  'compatibilityVersion': 'Xcode 3.2',
                  'hasScannedForEncodings': 0,
                  'knownRegions': ['en'],
                  'mainGroup': self.mainGroupId,
                  'productRefGroup': self.productRefGroupId,
                  'projectDirPath': ' ',
                  'projectRoot': ' ',
                  'targets': [self.targetId]}
        return result

    def generate_configuration(self, target):
        includePath = ''
        for i in target.include:
            includePath += i
            includePath += ' '
        result ={
            'isa':'XCBuildConfiguration',
            'buildSettings': {'ALWAYS_SEARCH_USER_PATH':'YES',
                'USER_HEADER_SEARCH_PATHS' : includePath},
            'name':'Debug'
        }
        return result;

    def generate_configuration_list(self, configuration):
        result = {
            'isa': 'XCConfigurationList',
            'buildConfigurations': [configuration],
            'defaultConfigurationIsVisible': '0',
            'defaultConfigurationName':'Debug'
        }
        return result

    def generate_target(self, target, buildConfigutationList):
        result = {'isa': 'PBXNativeTarget',
                  'name': target.name,
                  'productType':self.get_product_type(target),
                  'buildPhases': []
        }
        return result

    #children = () 如何去掉“”
    def generate_main_group(self, modulename):
        cpplist = [];
        for i in self.sourceRefList.keys():
            cpplist.append(i)

        result = {'isa': 'PBXGroup',
                  'children': cpplist,
                  'sourceTree': '<group>'}
        return result

    def generate_sub_main_children(self, modulename):
        return {}

    def generate_sub_main_group(self, modulename):
        result = {'isa': 'PBXGroup',
                  'children': self.generate_sub_main_children(modulename),
                  'path': modulename,
                  'sourceTree': '<group>'}
        return result

    def generate_product_group(self, modulename):
        result = {'isa': 'PBXGroup',
                  'children': [self.productReferenceId],
                  'name': 'Products',
                  'sourceTree': '<group>'}
        return result

    def generate_sub_group(self, subDictionaryName):
        index = 0
        for key in self.projectSubDictionarys.keys():
            if subDictionaryName != key:
                index+=1
                continue

        if index == len(self.projectSubDictionarys.keys()):
            ret = self.generate_id()
            projectSubDictionarys[ret]
            return ret
        return 0

    def build_group(self, cppfiles):

        self.groups={}
        subDictionaryMap=[]
        for cppfileIndex in range(0, len(cppfiles)):
            subDictionary = cppfiles[cppfileIndex].split('/')
            subDictionary[len(subDictionary)-1]+='.cxx'
            subDictionaryMap.append([])
            if cppfileIndex == 0:
                for subDictionaryIndex in range(0, len(subDictionary)):
                    id = self.generate_id()
                    item = {}
                    if 'cxx' in subDictionary[subDictionaryIndex]:
                        item = {'isa': 'PBXFileReference',
                                'lastKnownFileType': 'sourcecode.cpp.cpp',
                                               'path': '../../'+cppfiles[cppfileIndex]+'.cxx',
                                               'sourceTree': '<group>',
                                               'name': subDictionary[subDictionaryIndex].split('.')[0],
                                               'id':id,
                            'appended':'no'}
                    else:
                        item = {
                            'isa':'PBXGroup',
                            'children':[],
                            'name':subDictionary[subDictionaryIndex],
                            'sourceTree':'<group>',
                            'id':id,
                            'appended':'no'
                        }
                    subDictionaryMap[cppfileIndex].append(item)
                    self.objects[id]=item
            else:
                for subDictionaryIndex in range(0, len(subDictionary)):
                    subDictionaryRecordIndex = 0
                    missMatchTimes = 0
                    for subDictionaryRecordIndex in range(0, len(subDictionaryMap)-1):
                        if subDictionaryIndex >= len(subDictionaryMap[subDictionaryRecordIndex]):
                            continue

                        if subDictionaryIndex>=len(subDictionaryMap[cppfileIndex]):
                            subDictionaryMap[cppfileIndex].append({})

                        itemInMap = subDictionaryMap[subDictionaryRecordIndex][subDictionaryIndex]['name']
                        itemInRecord = subDictionary[subDictionaryIndex]
                        if  itemInMap == itemInRecord:
                            subDictionaryMap[cppfileIndex][subDictionaryIndex] = subDictionaryMap[subDictionaryRecordIndex][subDictionaryIndex]
                        else:
                            missMatchTimes+=1
                        subDictionaryRecordIndex+=1

                    if missMatchTimes == len(subDictionaryMap) -1:
                        id = self.generate_id()
                        item = {}
                        if 'cxx' in subDictionary[subDictionaryIndex]:
                            item = {'isa': 'PBXFileReference',
                                    'lastKnownFileType': 'sourcecode.cpp.cpp',
                                               'path': '../../'+cppfiles[cppfileIndex]+'.cxx',
                                               'sourceTree': '<group>',
                                               'name': subDictionary[subDictionaryIndex].split('.')[0],
                            'id':id,
                            'appended':'no'}
                        else:
                            item = {
                            'isa':'PBXGroup',
                            'children':[],
                            'name':subDictionary[subDictionaryIndex],
                            'sourceTree':'<group>',
                            'id':id,
                            'appended':'no'
                            }
                        self.objects[id]=item
                        subDictionaryMap[cppfileIndex][subDictionaryIndex] = item


        maxSubDictionaryCount = 0
        for subDictionaryRecord in subDictionaryMap:
            if maxSubDictionaryCount < len(subDictionaryRecord):
                maxSubDictionaryCount = len(subDictionaryRecord)


        for i in range(0, maxSubDictionaryCount-1):
            for subDictionaryItem in subDictionaryMap:
                if(i>len(subDictionaryItem)-1):
                    break
                if subDictionaryItem[i+1]['appended'] =='no':
                    subDictionaryItem[i]['children'].append(subDictionaryItem[i+1]['id'])
                    subDictionaryItem[i+1]['appended']='yes'
        #生成maingroup节点
        return 0





    def build_source_list(self, modulename):
        self.sourceList = {}
        self.sourceRefList = {}
        subDictionarys = {}
        for lib in self.gbuildparser.libs:
            if lib.name == modulename:
                self.build_group(lib.cxxobjects)
                for cppobj in lib.cxxobjects:
                    cppobj+='.cxx'
                    subDictionary = cppobj.split('/')
                    for item in subDictionary:
                        index = 0
                        for key in subDictionarys.keys():
                            if item != key:
                                index+=1
                                continue

                        if index == len(subDictionarys.keys()):
                            subDictionarys[item]=self.generate_id()

                    ref = self.generate_id()
                    self.sourceList[self.generate_id()] = ref
                    self.sourceRefList[ref] = {'lastKnownFileType': 'sourcecode.cpp.cpp',
                                               'path': '../../'+cppobj + '.cxx',
                                               'sourceTree': '<group>',
                                               'name': cppobj.split('/')[-1]}

                    # for i in self.gbuildparser.libs[modulename].cxxobjects:


    def generate_project(self, modulename):
        self.objects = {}
        self.projectSubDictionarys={}
        self.rootObjectId = self.generate_id()
        self.productRefGroupId = self.generate_id()
        self.targetId = self.generate_id()
        self.configurationId = self.generate_id()
        self.configurationListId = self.generate_id()
        self.subMainGroupId = self.generate_id()
        self.productReferenceId = self.generate_id()
        self.sourcesBuildPhaseId = self.generate_id()
        self.build_source_list(modulename)

        self.objects[self.configurationId] = self.generate_configuration()
        self.objects[self.configurationListId]=  self.generate_configuration_list(self.configurationId)
        self.objects[self.targetId] = self.generate_target(modulename, self.configurationListId)
        self.objects[self.rootObjectId] = self.generate_root_object(modulename, self.configurationListId)


        project = {'archiveVersion': '1',
                   'classes': {},
                   'objectVersion': 46,
                   'objects': self.objects,
                   'rootObject': self.rootObjectId}
        return project

    # For some reverse-engineered documentation on the project.pbxproj format,
    # see http://www.monobjc.net/xcode-project-file-format.html .
    def write_xcodeproj(self, moduledir, modulename):
        xcodeprojdir = os.path.join(moduledir, '%s.xcodeproj' % modulename.name)
        try:
            os.mkdir(xcodeprojdir)
        except:
            pass
        self.write_dict_to_plist(self.write_target_xcodeproj(modulename),
                                 open(os.path.join(xcodeprojdir, 'project.pbxproj'), 'w'))

    def write_target_xcodeproj(self, target):
        self.xcodeProjObjects={}

        self.sourcesBuildPhaseId = self.generate_id()
        self.xcodeProjObjects[self.sourcesBuildPhaseId] =  {'isa':'PBXSourcesBuildPhase',
            'buildActionMask':'2147483647',
            'runOnlyForDeploymentPostprocessing':'0',
            'files':[]}

        mainGroup = self.generate_source_code_groups(target.name, target.cxxobjects)

        self.projectSubDictionarys={}
        self.rootObjectId = self.generate_id()
        self.productRefGroupId = self.generate_id()
        self.targetId = self.generate_id()
        self.configurationId = self.generate_id()
        self.configurationListId = self.generate_id()
        self.subMainGroupId = self.generate_id()
        self.productReferenceId = self.generate_id()


        self.xcodeProjObjects[self.configurationId] = self.generate_configuration(target)
        self.xcodeProjObjects[self.configurationListId]=  self.generate_configuration_list(self.configurationId)
        self.xcodeProjObjects[self.targetId] = self.generate_target(target, self.configurationListId)
        self.xcodeProjObjects[self.rootObjectId] = self.generate_root_object(target.name, self.configurationListId)
        self.xcodeProjObjects[self.targetId]['buildPhases'].append(self.sourcesBuildPhaseId)
        project = {'archiveVersion': '1',
                   'classes': {},
                   'objectVersion': 46,
                   'objects': self.xcodeProjObjects,
                   'rootObject': self.rootObjectId}
        return project

    def generate_pbx_file_reference(self, fileName, filePath):
        return {
            'isa':'PBXFileReference',
            'lastKnownFileType': 'sourcecode.cpp.cpp',
            'path':filePath,
            'name':fileName,
            'sourceTree' : '<group>',
            'appended':'no',
            'id':self.generate_id()
        }

    def generate_pbx_group(self, groupName):
        return {
        'isa':'PBXGroup',
        'children':[],
        'name':groupName,
        'sourceTree' : '<group>',
        'appended':'no',
        'id':self.generate_id()
        }
    def generate_build_file(self, fileId):
        buildFileId = self.generate_id()
        buildFile = {
            'isa':'PBXBuildFile',
            'fileRef':fileId
        }
        self.xcodeProjObjects[self.sourcesBuildPhaseId]['files'].append(buildFileId)
        self.xcodeProjObjects[buildFileId] = buildFile
        return
    #生成一组dict类型的对象用于描述分组信息
    def generate_source_code_groups(self, moduleName, sourceFileFullPaths):
        #self.xcodeProjObjects={}
        tmpxcodeProjObjectsMap = []
        for srcFileFullPathIndex in range(0, len(sourceFileFullPaths)): #srcFileIndex
            sourceFileFullPath = sourceFileFullPaths[srcFileFullPathIndex]
            suffixs = ['.h', '.hxx', '.cxx', '.c']
            for suffix in suffixs:
                if os.path.isfile(self.gbuildparser.builddir + '/' + sourceFileFullPath + suffix) != True:
                    continue
                else:
                    splittedPath = (sourceFileFullPath + suffix).split('/')

                    #为待插入的记录开辟空间
                    tmpxcodeProjObjectsMap.append([])
                    for i in range(0, len(splittedPath)):
                        tmpxcodeProjObjectsMap[len(tmpxcodeProjObjectsMap)-1].append({})

                    #其他记录自动匹配
                    for splittedPathItemIndex in range(0, len(splittedPath)):
                        splittedPathItem = splittedPath[splittedPathItemIndex]

                        matchItem = {}
                        #isa = 'PBXFileReference'
                        if splittedPathItemIndex == len(splittedPath) - 1:
                            matchItem = self.generate_pbx_file_reference(splittedPathItem, self.gbuildparser.builddir + '/' + sourceFileFullPath+suffix)
                            self.generate_build_file(matchItem['id'])
                        #isa = 'PBXGroup'
                        else:
                            matchItem = self.generate_pbx_group(splittedPathItem)

                        #首行记录手工添加
                        if len(tmpxcodeProjObjectsMap) == 1:
                            self.xcodeProjObjects[matchItem['id']] = matchItem
                            tmpxcodeProjObjectsMap[0][splittedPathItemIndex] = matchItem
                        #非首行记录 开始匹配
                        else:
                            #不与新插入的行做匹配
                            matchRecordCount = len(tmpxcodeProjObjectsMap) - 1
                            missMatchTimes = 0
                            for tmpPathRecordIndex in range(0, matchRecordCount):
                                #当前行所包含的splittedItem不足
                                if splittedPathItemIndex >= len(tmpxcodeProjObjectsMap[tmpPathRecordIndex]):
                                    missMatchTimes+=1
                                    continue

                                InMapItemName = tmpxcodeProjObjectsMap[tmpPathRecordIndex][splittedPathItemIndex]['name']
                                currentItemName = splittedPathItem
                                if InMapItemName == currentItemName:
                                    #tmpxcodeProjObjectsMap[srcFileFullPathIndex][splittedPathItemIndex] = tmpxcodeProjObjectsMap[tmpPathRecordIndex][splittedPathItemIndex]
                                    matchItem = tmpxcodeProjObjectsMap[tmpPathRecordIndex][splittedPathItemIndex]
                                    break
                                else:
                                    missMatchTimes+=1
                            if missMatchTimes == matchRecordCount:
                                self.xcodeProjObjects[matchItem['id']] = matchItem
                            tmpxcodeProjObjectsMap[len(tmpxcodeProjObjectsMap)-1][splittedPathItemIndex] = matchItem

        #合并父子关系,从第二列开始合并
        for i in range(1, 100):
           for index in range(0, len(tmpxcodeProjObjectsMap)):
               if i >= len(tmpxcodeProjObjectsMap[index]):
                   continue
               else:
                   if tmpxcodeProjObjectsMap[index][i]['appended'] == 'no':
                       tmpxcodeProjObjectsMap[index][i]['appended'] = 'yes'
                       tmpxcodeProjObjectsMap[index][i-1]['children'].append(tmpxcodeProjObjectsMap[index][i]['id'])


        if(len(tmpxcodeProjObjectsMap) != 0 ):
            if(len(tmpxcodeProjObjectsMap[0])):
                self.mainGroupId = tmpxcodeProjObjectsMap[0][0]['id']
                return tmpxcodeProjObjectsMap[0][0];

        print(moduleName + 'has no source file \r\n' )
        emptyGroup = self.generate_pbx_group(moduleName)
        self.mainGroupId = emptyGroup['id']
        return emptyGroup;

    def __init__(self, gbuildparser, ide):
        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
        self.target_by_location = {}
        for target in set(self.gbuildparser.libs) | set(self.gbuildparser.exes):
            if target.location not in self.target_by_location:
                self.target_by_location[target.location] = set()
            self.target_by_location[target.location] |= set([target])

    def emit(self):
        for location in self.target_by_location:
            for target in self.target_by_location[location]:
                self.write_xcodeproj(location, target)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='LibreOffice gbuild IDE project generator')
    parser.add_argument('--ide', dest='ide', required=True,
                    help='the IDE to generate project files for')
    parser.add_argument('--input', dest='input', required=False,
                            help='the input file, not normally used, for debugging this script')
    args = parser.parse_args()
    paths = {}
    if args.input:
            gbuildparser = GbuildParser().parse(open(args.input, 'r'))
    else:
            gbuildparser = GbuildParser().parse(sys.stdin)
    #DebugIntegrationGenerator(gbuildparser).emit()

    if args.ide == 'xcode':
            XcodeIntegrationGenerator(gbuildparser).emit()
    else:
            parser.print_help()
            sys.exit(1)


    # Local Variables:
    # indent-tabs-mode: nil
    # End:
    #
    # vim: set et sw=4 ts=4: