├── src └── PyEterm │ ├── __init__.py │ ├── utils.py │ ├── PyEtermLibrary.py │ └── matiplib.py ├── .gitignore ├── README.md ├── .settings └── org.eclipse.core.resources.prefs ├── .project ├── .pydevproject └── LICENSE /src/PyEterm/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /src/config.cgi 2 | /scr/*.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pyeterm 2 | ======= 3 | 4 | python实现eterm接口 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/PyEterm/PyEtermLibrary.py=utf-8 3 | encoding//src/PyEterm/matiplib.py=utf-8 4 | encoding//src/PyEterm/utils.py=utf-8 5 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | pyeterm 4 | 5 | 6 | 7 | 8 | 9 | org.python.pydev.PyDevBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.python.pydev.pythonNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.pydevproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /${PROJECT_DIR_NAME}/src 5 | 6 | python 2.7 7 | Default 8 | 9 | -------------------------------------------------------------------------------- /src/PyEterm/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | ''' 3 | Created on Oct 16, 2014 4 | 5 | @author: czl 6 | ''' 7 | import re 8 | 9 | def AscToHex(buf): 10 | strs = re.findall(r'\w{2}', buf) 11 | return ''.join(chr(int(strs))) 12 | 13 | def hex_format(text): 14 | return [('%02x' % (ord(ch))) for ch in text] 15 | 16 | def asc_format(text): 17 | res = [] 18 | for ch in text: 19 | if ch >=' ' and ch <= '~' : 20 | res.append(' %c' % ch) 21 | else: 22 | res.append(' .') 23 | return res 24 | 25 | def hex_print(text, colNumPerLine=16): 26 | hexText = hex_format(text) 27 | ascText = asc_format(text) 28 | assert(len(hexText) == len(ascText)) 29 | res = [] 30 | for index in range(0, len(hexText), colNumPerLine): 31 | res.append(' '.join(hexText[index:index+colNumPerLine])) 32 | res.append(' '.join(ascText[index:index+colNumPerLine])) 33 | print '\n'.join(res) 34 | 35 | if __name__ == '__main__': 36 | pass 37 | -------------------------------------------------------------------------------- /src/PyEterm/PyEtermLibrary.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | ''' 3 | Created on Oct 16, 2014 4 | 5 | @author: czl 6 | ''' 7 | 8 | from PyEterm.utils import hex_print 9 | import uuid 10 | import ConfigParser 11 | import codecs 12 | import os 13 | from PyEterm.matiplib import MATIP 14 | import re 15 | import logging 16 | 17 | class PyEtermLibrary(object): 18 | ''' 19 | classdocs 20 | ''' 21 | 22 | ver = 1 23 | debug_level = 0 24 | eterm_print_pattern = re.compile(r"([^\r]{80})") 25 | 26 | def __init__(self): 27 | ''' 28 | Constructor 29 | ''' 30 | self.matip = MATIP() 31 | self.ascus = [] 32 | self.currentSessionIndex = 0 33 | 34 | def connect(self, host, port): 35 | if not isinstance(port, int): 36 | port = int(port) 37 | self.matip.connect(host, port) 38 | return "connect success" 39 | 40 | def __getMac(self): 41 | node = uuid.getnode() 42 | mac = uuid.UUID(int=node) 43 | return mac.hex[-12:] 44 | 45 | def login(self, username, password): 46 | if isinstance(username, unicode): 47 | username = username.encode("ascii", "ignore") 48 | if isinstance(password, unicode): 49 | password = password.encode("ascii", "ignore") 50 | 51 | ## 构造登录报文 52 | content = chr(self.ver) # version 53 | content += chr(0xa2) # 内容长度162个字节 54 | 55 | assert(len(username) <= 16) 56 | assert(len(password) <= 32) 57 | content += username.ljust(16, chr(0)) 58 | content += password.ljust(32, chr(0)) 59 | 60 | mac = self.__getMac() 61 | content += mac.ljust(12, chr(0)) 62 | localip = self.matip.sock.getsockname()[0] 63 | content += localip.ljust(16, chr(0x20)) 64 | content += "3832010.000000" #the magic code 65 | content = content.ljust(162, chr(0)) 66 | 67 | ## 登录并记录session id 68 | 69 | h1s = [] 70 | while 1: 71 | self.matip.send(content) 72 | resp = self.matip.getreply() 73 | if ord(resp[0]) == 0 and ord(resp[1]) == len(resp) and ord(resp[2]) == 1: 74 | self.sessionCount = ord(resp[4]) 75 | for i in range(self.sessionCount): 76 | ind = 5 + 5 * i 77 | self.ascus.append(resp[ind:ind + 5]) # save the H1 H2 A1 A2 78 | if resp[ind] != chr(0): 79 | h1s.append(resp[ind]) 80 | break 81 | else: 82 | logging.error("login error") 83 | 84 | ## ascus open 85 | content = self.matip.getSessionOpenPacket(cd=4, styp=1, mpx=0, hdr=0, pres=2, h1=0, h2=0) 86 | self.matip.send(content) 87 | resp = self.matip.getreply() 88 | 89 | content = '' 90 | # for h1 in (chr(0x0c), chr(0x29), chr(0x20)): 91 | for h1 in h1s: 92 | content += self.matip.getSessionOpenPacket(cd=4, styp=1, mpx=0, hdr=0, pres=2, h1=ord(h1), h2=0) 93 | self.matip.send(content) 94 | resp = self.matip.getreply() 95 | resp = self.matip.getreply() 96 | return "login success" 97 | 98 | def changeToSession(self, index): 99 | if not isinstance(index, int): 100 | index = int(index) 101 | self.currentSessionIndex = index - 1 102 | 103 | def eterm_print(self, cmd, text): 104 | beginIndex = text.find("\x1b\x4d") + 2 105 | endIndex = text.rfind("\x1e\x1b\x62") 106 | content = ">" + cmd + "\r" + text[beginIndex:endIndex] + ">" 107 | content = self.eterm_print_pattern.sub(r"\1\r", content) 108 | content = content.replace('\x0d', os.linesep) 109 | print content 110 | return content 111 | 112 | def sendCmd(self, cmd): 113 | data = "\x02\x1b\x0b\x20\x20\x00\x0f\x1e" 114 | data += cmd.strip() 115 | data += "\x20" 116 | content = self.matip.getDataPacket(self.ascus[self.currentSessionIndex], data) 117 | 118 | if self.debug_level > 0: 119 | hex_print(content) 120 | self.matip.send(content) 121 | 122 | resp = self.matip.getreply() 123 | return self.eterm_print(cmd, resp) 124 | 125 | if __name__ == "__main__": 126 | logging.basicConfig(level=logging.DEBUG) 127 | logging.info("hello") 128 | 129 | config = ConfigParser.ConfigParser() 130 | config.readfp(codecs.open('../config.cgi', 'r', 'utf-8-sig')) 131 | 132 | server = config.get("eterm", "server") 133 | port = config.getint("eterm", "port") 134 | username = config.get("eterm", "username") 135 | password = config.get("eterm", "password") 136 | 137 | el = PyEtermLibrary() 138 | el.connect(server, port) 139 | el.login(username, password) 140 | resp = el.sendCmd("da") 141 | resp = el.sendCmd("av:canpek/30oct/cz") 142 | # el.sendCmd("IHD:CA") 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /src/PyEterm/matiplib.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | ''' 3 | Created on Oct 16, 2014 4 | 5 | @author: czl 6 | ''' 7 | 8 | import socket 9 | from sys import stderr 10 | import struct 11 | 12 | 13 | MATIP_PORT = 350 14 | 15 | class MATIPException(Exception): 16 | ''' 17 | Base class for all exceptions raised by this module. 18 | ''' 19 | 20 | 21 | class MATIPServerDisconnected(MATIPException): 22 | '''Not connected to any MATIP server. 23 | 24 | This exception is raised when the server unexpectedly disconnects, 25 | or when an attempt is made to use the SMTP instance before 26 | connecting it to a server. 27 | ''' 28 | 29 | class MATIPResponseException(MATIPException): 30 | """Base class for all exceptions that include an MATIP error code. 31 | """ 32 | 33 | class MATIP(object): 34 | ''' 35 | classdocs 36 | ''' 37 | 38 | debuglevel = 0 39 | file = None 40 | default_port = 350 41 | 42 | ver = 1 43 | 44 | def __init__(self, host='', port=0, 45 | timeout=socket._GLOBAL_DEFAULT_TIMEOUT): 46 | ''' 47 | Constructor 48 | ''' 49 | self.timeout = timeout 50 | if host: 51 | self.connect(host, port) 52 | 53 | 54 | def set_debuglevel(self, debuglevel): 55 | self.debuglevel = debuglevel 56 | 57 | def _get_socket(self, host, port, timeout): 58 | if self.debuglevel > 0: 59 | print>>stderr, 'create connect:', (host, port) 60 | return socket.create_connection((host, port), timeout) 61 | 62 | def connect(self, host='localhost', port=0): 63 | if not port and (host.find(':') == host.rfind(':')): 64 | i = host.rfind(':') 65 | if i >= 0: 66 | host, port = host[:i], host[i+1:] 67 | try: 68 | port = int(port) 69 | except ValueError: 70 | raise socket.error, "nonnumeric port" 71 | if not port: 72 | port = self.default_port 73 | if self.debuglevel > 0: 74 | print>>stderr, 'connect:', (host, port) 75 | self.sock = self._get_socket(host, port, self.timeout) 76 | 77 | def send(self, content): 78 | if self.debuglevel > 0: 79 | print>>stderr, 'send;', repr(content) 80 | if hasattr(self, 'sock') and self.sock: 81 | try: 82 | self.sock.sendall(content) 83 | except socket.error: 84 | self.close() 85 | raise MATIPServerDisconnected('Server not connected') 86 | else: 87 | raise MATIPServerDisconnected('Please run connect() first') 88 | 89 | def getreply(self): 90 | # if self.file is None: 91 | # self.file = self.sock.makefile('rb') 92 | try: 93 | # resp = self.file.readline() 94 | resp = self.sock.recv(4096) 95 | except socket.error as e: 96 | self.close() 97 | raise MATIPServerDisconnected("Connection unexpectedly closed: " 98 | + str(e)) 99 | if resp == '': 100 | self.close() 101 | raise MATIPServerDisconnected("Connection unexpectedly closed") 102 | if self.debuglevel > 0: 103 | print>>stderr, 'reply:', repr(resp) 104 | return resp 105 | 106 | 107 | def createPacket(self, version, cmd, content): 108 | msg = chr(version) 109 | msg += chr(cmd) 110 | msg += struct.pack("!H", len(content)+4) 111 | msg += content 112 | return msg 113 | 114 | def getSessionOpenPacket(self, cd, styp, mpx, hdr, pres, h1, h2, ascus=[]): 115 | ''' 116 | get the session open message 117 | 118 | 0 1 2 3 119 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 120 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 121 | |0|0|0|0|0| Ver |1|1 1 1 1 1 1 0| length | 122 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 123 | |0 0|0 1|0| CD | STYP |0 0 0 0| RFU |MPX|HDR| PRES. | 124 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 125 | | H1 | H2 | RFU | 126 | |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 127 | | Reserved | RFU | Nbr of ASCUs | 128 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 129 | | Nbr of ASCUs | ASCU list (opt) | 130 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 131 | 132 | CD 133 | This field specifies the Coding 134 | 000 : 5 bits (padded baudot) 135 | 010 : 6 bits (IPARS) 136 | 100 : 7 bits (ASCII) 137 | 110 : 8 bits (EBCDIC) 138 | xx1 : R.F.U 139 | 140 | STYP 141 | This is the traffic subtype (type being TYPE A). 142 | 0001 : TYPE A Conversational 143 | 144 | MPX 145 | This flag specifies the multiplexing used within the TCP session. 146 | Possible values are: 147 | 00 : Group of ASCU with 4 bytes identification per ASCU (H1H2A1A2) 148 | 01 : Group of ASCUs with 2 bytes identification per ASCU (A1A2) 149 | 10 : single ASCU inside the TCP session. 150 | 151 | HDR 152 | This field specifies which part of the airline’s specific address is 153 | placed ahead of the message texts transmitted over the session. 154 | Possible values are: 155 | 00 : ASCU header = H1+H2+A1+A2 156 | 01 : ASCU Header = A1+A2 157 | 10 : No Header 158 | 11 : Not used 159 | The MPX and HDR must be coherent. When ASCUs are multiplexed, the data 160 | must contain the ASCU identification. The table below summarizes the 161 | allowed combinations: 162 | +-----------------------+ 163 | | MPX | 00 | 01 | 10 | 164 | +-----------------------+ 165 | | HDR | | 166 | | 00 | Y | Y | Y | 167 | | 01 | N | Y | Y | 168 | | 10 | N | N | Y | 169 | +-----------------------+ 170 | 171 | PRES 172 | This field indicates the presentation format 173 | 0001 : P1024B presentation 174 | 0010 : P1024C presentation 175 | 0011 : 3270 presentation 176 | 177 | H1 H2 178 | These fields can logically identify the session if MPX is not equal to 179 | 00. When this field is not used, it must be set to 0. If used in 180 | session (MPX <> 0) with HDR=00, H1H2 in data packet must have the same 181 | value as set in SO command. 182 | 183 | Nbr of ASCUs 184 | Nbr_of_ASCUs field is mandatory and gives the number of ASCUs per 185 | session. A 0 (zero) value means unknown. In this case the ASCU list is 186 | not present in the ‘Open Session’ command and must be sent by the 187 | other end in the ‘Open Confirm’ command. 188 | 189 | ASCU LIST 190 | Contains the list of identifier for each ASCU. If MPX=00 it has a 191 | length of four bytes (H1H2A1A2) for each ASCU, otherwise it is two 192 | bytes (A1A2). 193 | ''' 194 | content = chr(1<<4 | cd) 195 | content += chr(styp<<4) 196 | content += chr(0) # RFU 197 | content += chr(mpx<<6 | hdr<<4 | pres) 198 | content += chr(h1) 199 | content += chr(h2) 200 | content += ''.ljust(2, chr(0)) # RFU 201 | content += chr(0) # Reserved 202 | content += ''.ljust(2, chr(0)) # RFU 203 | content += struct.pack("!H", len(ascus)) 204 | 205 | if mpx == 0: 206 | fmt = "4B" # 4个字节(H1H2A1A2) 207 | else: 208 | fmt = "2B" # 2个字节(A1A2) 209 | for ascu in ascus: 210 | content += struct.pack(fmt, *ascu) 211 | 212 | return self.createPacket(self.ver, 0xFE, content) 213 | 214 | def getDataPacket(self, ascu, data): 215 | content = ascu[:3]+chr(1)+ascu[3:] 216 | content += chr(0x70) 217 | content += data 218 | content += chr(0x3) 219 | return self.createPacket(self.ver, 0, content) 220 | 221 | def close(self): 222 | if self.file: 223 | self.file.close() 224 | self.file = None 225 | if self.sock: 226 | self.sock.close() 227 | self.sock = None 228 | 229 | 230 | if __name__ == "__main__": 231 | import ConfigParser 232 | import codecs 233 | config = ConfigParser.ConfigParser() 234 | config.readfp(codecs.open('config.cgi', 'r', 'utf-8-sig')) 235 | 236 | server = config.get("eterm", "server") 237 | port = config.getint("eterm", "port") 238 | username = config.get("eterm", "username") 239 | password = config.get("eterm", "password") 240 | 241 | el = MATIP() 242 | el.set_debuglevel(1) 243 | el.connect(server, port) 244 | 245 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. 204 | 205 | --------------------------------------------------------------------------------