1#!/usr/bin/python
2
3import sys
4from struct import *
5from xml.dom import minidom
6#s2x Runtime Error Class Definition:
7class s2xErr(Exception):
8    def __init__(self,msg):
9        self.msg=msg
10#constants start:
11#------------------------------------------------------------#
12NUMBER='\x00'
13BOOLEAN='\x01'
14STRING='\x02'
15OBJOBJ='\x03'
16NULL='\x05'
17UNDEF='\x06'
18OBJARR='\x08'
19#RAWARR='\x0A'
20OBJDATE='\x0B'
21OBJM='\x0D'
22OBJXML='\x0F'
23OBJCC='\x10'
24#constants end.
25#------------------------------------------------------------#
26argv=sys.argv
27if len(argv)<3:
28    print 's2x v 0.75 by iceeLyne, Dec., 2003.'
29    print 'usage:'
30    print 'python s2x.py -x foo.sol [foo.xml]'
31    print 'python s2x.py -s foo.xml [foo.sol]'
32else:
33    argvSw=argv[1]
34    argvInpFile=argv[2]
35    if len(argv)>3:
36        argvOutFile=argv[3]
37    else:
38        argvOutFile=''
39    if argvSw=='-x':
40        # parse sol to xml
41        try:
42            f=open(argvInpFile,'rb')
43        except IOError:
44            print 'Could Not Open The Input File: '+argvInpFile
45        else:
46            def num2x():
47                global cparent,sVname
48                s=f.read(8)
49                if s=='\x7F\xF0\x00\x00\x00\x00\x00\x00':
50                    sValue='Infinity'
51                elif s=='\xFF\xF0\x00\x00\x00\x00\x00\x00':
52                    sValue='-Infinity'
53                elif s=='\x7F\xF8\x00\x00\x00\x00\x00\x00':
54                    sValue='NaN'
55                else:
56                    nValue,=unpack('>d',s)#Double,Big-endian
57                    sValue=str(nValue)
58                c=cparent.appendChild(d.createElement('data'))
59                c.setAttribute('type','number')
60                c.setAttribute('name',sVname)
61                c.setAttribute('value',sValue)
62            def bol2x():
63                global cparent,sVname
64                b=f.read(1)
65                if b=='\x00':
66                    sValue='false'
67                elif b=='\x01':
68                    sValue='true'
69                else:
70                    print 'Warning: Boolean Value Error.'
71                    sValue='true'
72                c=cparent.appendChild(d.createElement('data'))
73                c.setAttribute('type','boolean')
74                c.setAttribute('name',sVname)
75                c.setAttribute('value',sValue)
76            def str2x():
77                global cparent,sVname
78                nLenStr,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
79                s=f.read(nLenStr)
80                s=s.decode('utf-8')#
81                c=cparent.appendChild(d.createElement('data'))
82                c.setAttribute('type','string')
83                c.setAttribute('name',sVname)
84                c.appendChild(d.createCDATASection(s))
85            def obj2x():
86                global cparent,sVname,nLenVname#is necessary
87                c=cparent.appendChild(d.createElement('data'))
88                c.setAttribute('type','object')
89                c.setAttribute('name',sVname)
90                cparent=cparent.lastChild
91                nLenVname,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
92                while nLenVname!=0:
93                    sVname=f.read(nLenVname)
94                    sVname=sVname.decode('utf-8')#
95                    type=f.read(1)
96                    if type==NUMBER:
97                        num2x()
98                    elif type==BOOLEAN:
99                        bol2x()
100                    elif type==STRING:
101                        str2x()
102                    elif type==OBJARR:
103                        arr2x()
104                    elif type==OBJOBJ:
105                        obj2x()
106                    elif type==OBJDATE:
107                        dat2x()
108                    elif type==OBJXML:
109                        xml2x()
110                    elif type==OBJCC:
111                        occ2x()
112                    elif type==OBJM:
113                        ojm2x()
114                    elif type==NULL:
115                        nul2x()
116                    elif type==UNDEF:
117                        und2x()
118                    else:
119                        raise s2xErr('Unexpected Data Type: '+hex(ord(type)))
120                    nLenVname,=unpack('>H',f.read(2))
121                objend=f.read(1)#=='\x09'
122                cparent=cparent.parentNode
123            def arr2x():
124                global cparent,sVname,nLenVname#is necessary
125                nArrLength,=unpack('>L',f.read(4))#Unsigned Long,Big-endian
126                c=cparent.appendChild(d.createElement('data'))
127                c.setAttribute('type','array')
128                c.setAttribute('name',sVname)
129                c.setAttribute('length',str(nArrLength))
130                cparent=cparent.lastChild
131                nLenVname,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
132                while nLenVname!=0:
133                    sVname=f.read(nLenVname)
134                    sVname=sVname.decode('utf-8')#
135                    type=f.read(1)
136                    if type==NUMBER:
137                        num2x()
138                    elif type==BOOLEAN:
139                        bol2x()
140                    elif type==STRING:
141                        str2x()
142                    elif type==OBJOBJ:
143                        obj2x()
144                    elif type==OBJARR:
145                        arr2x()
146                    elif type==OBJDATE:
147                        dat2x()
148                    elif type==OBJXML:
149                        xml2x()
150                    elif type==OBJCC:
151                        occ2x()
152                    elif type==OBJM:
153                        ojm2x()
154                    elif type==NULL:
155                        nul2x()
156                    elif type==UNDEF:
157                        und2x()
158                    else:
159                        raise s2xErr('Unexpected Data Type: '+hex(ord(type)))
160                    nLenVname,=unpack('>H',f.read(2))
161                objend=f.read(1)#=='\x09'
162                cparent=cparent.parentNode
163            def dat2x():
164                global cparent,sVname
165                nMsec,=unpack('>d',f.read(8))#Double,Big-endian
166                nMinOffset,=unpack('>h',f.read(2))#Short,Big-endian
167                nOffset=nMinOffset/60
168                c=cparent.appendChild(d.createComment('DateObject:Milliseconds Count From Dec. 1, 1969; Timezone UTC + Offset.'))
169                c=cparent.appendChild(d.createElement('data'))
170                c.setAttribute('type','date')
171                c.setAttribute('name',sVname)
172                c.setAttribute('msec',str(nMsec))
173                c.setAttribute('utcoffset',str(-nOffset))
174            def xml2x():
175                global cparent,sVname
176                nLenCData,=unpack('>L',f.read(4))#Unsigned Long,Big-endian
177                sCData=f.read(nLenCData)
178                sCData=sCData.decode('utf-8')#
179                c=cparent.appendChild(d.createElement('data'))
180                c.setAttribute('type','xml')
181                c.setAttribute('name',sVname)
182                c.appendChild(d.createCDATASection(sCData))
183            def occ2x():
184                global cparent,sVname,nLenVname#is necessary
185                nLenCname,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
186                sCname=f.read(nLenCname)
187                sCname=sCname.decode('utf-8')#
188                c=cparent.appendChild(d.createElement('data'))
189                c.setAttribute('type','c_object')
190                c.setAttribute('name',sVname)
191                c.setAttribute('class_name',sCname)
192                cparent=cparent.lastChild
193                nLenVname,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
194                while nLenVname!=0:
195                    sVname=f.read(nLenVname)
196                    sVname=sVname.decode('utf-8')#
197                    type=f.read(1)
198                    if type==NUMBER:
199                        num2x()
200                    elif type==BOOLEAN:
201                        bol2x()
202                    elif type==STRING:
203                        str2x()
204                    elif type==OBJARR:
205                        arr2x()
206                    elif type==OBJOBJ:
207                        obj2x()
208                    elif type==OBJDATE:
209                        dat2x()
210                    elif type==OBJXML:
211                        xml2x()
212                    elif type==OBJCC:
213                        occ2x()
214                    elif type==OBJM:
215                        ojm2x()
216                    elif type==NULL:
217                        nul2x()
218                    elif type==UNDEF:
219                        und2x()
220                    else:
221                        raise s2xErr('Unexpected Data Type: '+hex(ord(type)))
222                    nLenVname,=unpack('>H',f.read(2))
223                objend=f.read(1)#=='\x09'
224                cparent=cparent.parentNode
225            def ojm2x():
226                global cparent,sVname
227                c=cparent.appendChild(d.createElement('data'))
228                c.setAttribute('type','m_object')
229                c.setAttribute('name',sVname)
230            def nul2x():
231                global cparent,sVname
232                c=cparent.appendChild(d.createElement('data'))
233                c.setAttribute('type','null')
234                c.setAttribute('name',sVname)
235            def und2x():
236                global cparent,sVname
237                c=cparent.appendChild(d.createElement('data'))
238                c.setAttribute('type','undefined')
239                c.setAttribute('name',sVname)
240            d=minidom.parseString('<solx/>')
241            try:
242                f.seek(0,2)
243                nLenFile=f.tell()
244                f.seek(0)
245                sHeader=f.read(2)
246                sLenData=f.read(4)
247                nLenData,=unpack('>L',sLenData)#Unsigned Long,Big-endian
248                if nLenFile!=nLenData+6:
249                    print 'Warning: Data Length Mismatch.'
250                sFileType=f.read(4)#=='TCSO'
251                sth1=f.read(6)
252                nLenSoln,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
253                solname=f.read(nLenSoln)
254                solname=solname.decode('utf-8')#
255                sth2=f.read(4)
256                solxroot=d.firstChild
257                solxroot.setAttribute('std_version','0.75')
258                solxroot.setAttribute('std_author','iceeLyne')
259                solxroot.setAttribute('sol_name',solname)
260                cparent=solxroot
261                while f.tell()<nLenFile:
262                    nLenVname,=unpack('>H',f.read(2))#Unsigned Short,Big-endian
263                    sVname=f.read(nLenVname)
264                    sVname=sVname.decode('utf-8')#
265                    type=f.read(1)
266                    if type==NUMBER:
267                        num2x()
268                    elif type==BOOLEAN:
269                        bol2x()
270                    elif type==STRING:
271                        str2x()
272                    elif type==OBJOBJ:
273                        obj2x()
274                    elif type==OBJARR:
275                        arr2x()
276                    elif type==OBJDATE:
277                        dat2x()
278                    elif type==OBJXML:
279                        xml2x()
280                    elif type==OBJCC:
281                        occ2x()
282                    elif type==OBJM:
283                        ojm2x()
284                    elif type==NULL:
285                        nul2x()
286                    elif type==UNDEF:
287                        und2x()
288                    else:
289                        raise s2xErr('Unexpected Data Type: '+hex(ord(type)))
290                    end=f.read(1)#=='\x00'
291                sxmloutput=d.toprettyxml('\t','\n','utf-8')
292                if argvOutFile=='':
293                    argvOutFile=argvInpFile[:argvInpFile.rfind('.')]+'.xml'
294                foutput=open(argvOutFile,'w')
295                foutput.write(sxmloutput)
296                foutput.close()
297                print 'Converted File: '+argvOutFile+' Was Successfully Created.'
298            except s2xErr,e:
299                print e.msg
300            except:
301                print 'Unexpected Error.'
302            d.unlink()#
303            f.close()#
304    elif argvSw=='-s':
305        # parse xml to sol
306        try:
307            d=minidom.parse(argvInpFile)
308        except IOError:
309            print 'Could Not Open The Input File: '+argvInpFile
310        except:
311            print 'Error At Parsing XML File Input.'
312        else:
313            def x2num():
314                global sData,sLenVname,sVname,c
315                sData+=sLenVname+sVname+NUMBER
316                sValue=c.getAttribute('value')
317                if sValue=='Infinity':
318                    sData+='\x7F\xF0\x00\x00\x00\x00\x00\x00'
319                elif sValue=='-Infinity':
320                    sData+='\xFF\xF0\x00\x00\x00\x00\x00\x00'
321                elif sValue=='NaN':
322                    sData+='\x7F\xF8\x00\x00\x00\x00\x00\x00'
323                else:
324                    nValue=float(sValue)
325                    sData+=pack('>d',nValue)
326            def x2bol():
327                global sData,sLenVname,sVname,c
328                sData+=sLenVname+sVname+BOOLEAN
329                sValue=c.getAttribute('value')
330                if sValue=='true':
331                    sData+='\x01'
332                elif sValue=='false':
333                    sData+='\x00'
334                else:
335                    raise s2xErr('Unexpected Boolean Value: '+sValue)
336            def x2str():
337                global sData,sLenVname,sVname,c
338                sData+=sLenVname+sVname+STRING
339                sCData=''
340                for cData in c.childNodes:
341                    if cData.nodeType==4:#CDATA_SECTION_NODE
342                        sCData=cData.nodeValue
343                        break
344                sCData=sCData.encode('utf-8')#
345                nLenCData=len(sCData)
346                sLenCData=pack('>H',nLenCData)
347                sData+=sLenCData+sCData
348            def x2obj():
349                global sData,sLenVname,sVname,c
350                sData+=sLenVname+sVname+OBJOBJ
351                temp=c
352                c=c.firstChild
353                while c:
354                    if c.nodeType==1:#ELEMENT_NODE
355                        sVname=c.getAttribute('name')
356                        sVname=sVname.encode('utf-8')#
357                        nLenVname=len(sVname)
358                        sLenVname=pack('>H',nLenVname)
359                        type=c.getAttribute('type')
360                        if type=='number':
361                            x2num()
362                        elif type=='boolean':
363                            x2bol()
364                        elif type=='string':
365                            x2str()
366                        elif type=='object':
367                            x2obj()
368                        elif type=='array':
369                            x2arr()
370                        elif type=='date':
371                            x2dat()
372                        elif type=='xml':
373                            x2xml()
374                        elif type=='c_object':
375                            x2occ()
376                        elif type=='m_object':
377                            x2ojm()
378                        elif type=='null':
379                            x2nul()
380                        elif type=='undefined':
381                            x2und()
382                        else:
383                            raise s2xErr('Unexpected Data Type: '+type)
384                    c=c.nextSibling
385                sData+='\x00\x00\x09'
386                c=temp
387            def x2arr():
388                global sData,sLenVname,sVname,c
389                sData+=sLenVname+sVname+OBJARR
390                nArrLength=float(c.getAttribute('length'))
391                sArrLength=pack('>L',nArrLength)
392                sData+=sArrLength
393                temp=c
394                c=c.firstChild
395                while c:
396                    if c.nodeType==1:#ELEMENT_NODE
397                        sVname=c.getAttribute('name')
398                        sVname=sVname.encode('utf-8')#
399                        nLenVname=len(sVname)
400                        sLenVname=pack('>H',nLenVname)
401                        type=c.getAttribute('type')
402                        if type=='number':
403                            x2num()
404                        elif type=='boolean':
405                            x2bol()
406                        elif type=='string':
407                            x2str()
408                        elif type=='object':
409                            x2obj()
410                        elif type=='array':
411                            x2arr()
412                        elif type=='date':
413                            x2dat()
414                        elif type=='xml':
415                            x2xml()
416                        elif type=='c_object':
417                            x2occ()
418                        elif type=='m_object':
419                            x2ojm()
420                        elif type=='null':
421                            x2nul()
422                        elif type=='undefined':
423                            x2und()
424                        else:
425                            raise s2xErr('Unexpected Data Type: '+type)
426                    c=c.nextSibling
427                sData+='\x00\x00\x09'
428                c=temp
429            def x2dat():
430                global sData,sLenVname,sVname,c
431                sData+=sLenVname+sVname+OBJDATE
432                nMsec=float(c.getAttribute('msec'))
433                nMinOffset=-60*int(c.getAttribute('utcoffset'))
434                sData+=pack('>dh',nMsec,nMinOffset)
435            def x2xml():
436                global sData,sLenVname,sVname,c
437                sData+=sLenVname+sVname+OBJXML
438                sCData=''
439                for cData in c.childNodes:
440                    if cData.nodeType==4:#CDATA_SECTION_NODE
441                        sCData=cData.nodeValue
442                        break
443                sCData=sCData.encode('utf-8')#
444                nLenCData=len(sCData)
445                sLenCData=pack('>L',nLenCData)
446                sData+=sLenCData+sCData
447            def x2occ():
448                global sData,sLenVname,sVname,c
449                sData+=sLenVname+sVname+OBJCC
450                sCname=c.getAttribute('class_name')
451                sCname=sCname.encode('utf-8')#
452                nLenCname=len(sCname)
453                sLenCname=pack('>H',nLenCname)
454                sData+=sLenCname+sCname
455                temp=c
456                c=c.firstChild
457                while c:
458                    if c.nodeType==1:#ELEMENT_NODE
459                        sVname=c.getAttribute('name')
460                        sVname=sVname.encode('utf-8')#
461                        nLenVname=len(sVname)
462                        sLenVname=pack('>H',nLenVname)
463                        type=c.getAttribute('type')
464                        if type=='number':
465                            x2num()
466                        elif type=='boolean':
467                            x2bol()
468                        elif type=='string':
469                            x2str()
470                        elif type=='object':
471                            x2obj()
472                        elif type=='array':
473                            x2arr()
474                        elif type=='date':
475                            x2dat()
476                        elif type=='xml':
477                            x2xml()
478                        elif type=='c_object':
479                            x2occ()
480                        elif type=='m_object':
481                            x2ojm()
482                        elif type=='null':
483                            x2nul()
484                        elif type=='undefined':
485                            x2und()
486                        else:
487                            raise s2xErr('Unexpected Data Type: '+type)
488                    c=c.nextSibling
489                sData+='\x00\x00\x09'
490                c=temp
491            def x2ojm():
492                global sData,sLenVname,sVname,c
493                sData+=sLenVname+sVname+OBJM
494            def x2nul():
495                global sData,sLenVname,sVname,c
496                sData+=sLenVname+sVname+NULL
497            def x2und():
498                global sData,sLenVname,sVname,c
499                sData+=sLenVname+sVname+UNDEF
500            try:
501                solxroot=d.firstChild
502                if solxroot.tagName!='solx' or float(solxroot.getAttribute('std_version'))>0.75:
503                    raise s2xErr('Not Solx File Or Incorrect File Version.')
504                sHeader='\x00\xBF'
505                sLenData='\x00\x00\x00\x00'
506                sFileType='TCSO'
507                sth1='\x00\x04\x00\x00\x00\x00'
508                solname=solxroot.getAttribute('sol_name')
509                solname=solname.encode('utf-8')#
510                nLenSoln=len(solname)
511                sLenSoln=pack('>H',nLenSoln)#2 bytes
512                sth2='\x00\x00\x00\x00'
513                sData=sFileType+sth1+sLenSoln+solname+sth2
514                c=solxroot.firstChild
515                while c:
516                    if c.nodeType==1:#ELEMENT_NODE
517                        sVname=c.getAttribute('name')
518                        sVname=sVname.encode('utf-8')#
519                        nLenVname=len(sVname)
520                        sLenVname=pack('>H',nLenVname)
521                        type=c.getAttribute('type')
522                        if type=='number':
523                            x2num()
524                        elif type=='boolean':
525                            x2bol()
526                        elif type=='string':
527                            x2str()
528                        elif type=='object':
529                            x2obj()
530                        elif type=='array':
531                            x2arr()
532                        elif type=='date':
533                            x2dat()
534                        elif type=='xml':
535                            x2xml()
536                        elif type=='c_object':
537                            x2occ()
538                        elif type=='m_object':
539                            x2ojm()
540                        elif type=='null':
541                            x2nul()
542                        elif type=='undefined':
543                            x2und()
544                        else:
545                            raise s2xErr('Unexpected Data Type: '+type)
546                        sData+='\x00'
547                    c=c.nextSibling
548                if argvOutFile=='':
549                    argvOutFile=argvInpFile[:argvInpFile.rfind('.')]+'.sol'
550                f=open(argvOutFile,'wb')
551                sLenData=pack('>L',len(sData))
552                f.write(sHeader+sLenData+sData)
553                f.close()
554                print 'Converted File: '+argvOutFile+' Was Successfully Created.'
555            except s2xErr,e:
556                print e.msg
557##            except:
558##                print 'Unexpected Error.'
559            d.unlink()#
560    else:
561        print 'Invalid Switch: '+argvSw
562