diff options
-rw-r--r-- | share/python/matrix/matrix.py | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/share/python/matrix/matrix.py b/share/python/matrix/matrix.py new file mode 100644 index 0000000..0630a12 --- /dev/null +++ b/share/python/matrix/matrix.py | |||
@@ -0,0 +1,162 @@ | |||
1 | #!/usr/bin/python | ||
2 | # -*- encoding: utf-8 -*- | ||
3 | |||
4 | import xml.etree.ElementTree as ET | ||
5 | import re | ||
6 | import urllib | ||
7 | import urllib2 | ||
8 | import ConfigParser | ||
9 | import optparse | ||
10 | import os | ||
11 | import sys | ||
12 | |||
13 | reURI = re.compile(r'''^(?P<scheme>[a-zA-Z0-9]+):// # scheme | ||
14 | ((?P<avatar>[^:@]+)(:(?P<password>[^@]+))?@)? # avatar name and password (optional) | ||
15 | (?P<host>[^:/]+)(:(?P<port>\d+))? # host, port (optional) | ||
16 | (?P<path>/.*) # path | ||
17 | $''', re.IGNORECASE | re.VERBOSE) | ||
18 | reLOC = re.compile(r'''^/(?P<region>[^/]+)/ # region name | ||
19 | (?P<x>\d+)/ # X position | ||
20 | (?P<y>\d+)/ # Y position | ||
21 | (?P<z>\d+) # Z position | ||
22 | ''', re.IGNORECASE | re.VERBOSE) | ||
23 | |||
24 | if __name__ == '__main__': | ||
25 | parser = optparse.OptionParser() | ||
26 | parser.add_option('-c', '--config', dest = 'config', help = 'config file', metavar = 'CONFIG') | ||
27 | parser.add_option('-s', '--secondlife', dest = 'client', help = 'location of secondlife client', metavar = 'SL-CLIENT') | ||
28 | (options, args) = parser.parse_args() | ||
29 | |||
30 | # | ||
31 | # we using ~/.matrixcfg to store the location of the secondlife client | ||
32 | # | ||
33 | if not options.config: | ||
34 | options.config = '~/.matrixcfg' | ||
35 | |||
36 | cfgPath = os.path.expanduser(options.config) | ||
37 | |||
38 | # | ||
39 | # if ~/.matrixcfg does not exist we are in trouble... | ||
40 | # | ||
41 | if not os.path.exists(cfgPath) and not options.client: | ||
42 | print '''oops, i've no clue where your secondlife client lives around here. | ||
43 | i suggest you run me with the "--secondlife path-of-secondlife-client" argument.''' | ||
44 | sys.exit(1) | ||
45 | |||
46 | # | ||
47 | # ok, either ~/.matrixcfg does exist or we are asked to create it | ||
48 | # | ||
49 | config = ConfigParser.ConfigParser() | ||
50 | if os.path.exists(cfgPath): | ||
51 | config.readfp(open(cfgPath)) | ||
52 | |||
53 | if options.client: | ||
54 | if config.has_option('secondlife', 'client'): | ||
55 | config.remove_option('secondlife', 'client') | ||
56 | if not config.has_section('secondlife'): | ||
57 | config.add_section('secondlife') | ||
58 | config.set('secondlife', 'client', options.client) | ||
59 | |||
60 | cfg = open(cfgPath, mode = 'w+') | ||
61 | config.write(cfg) | ||
62 | cfg.close() | ||
63 | |||
64 | client = config.get('secondlife', 'client') | ||
65 | |||
66 | |||
67 | # | ||
68 | # sanity check: URI supplied? | ||
69 | # | ||
70 | if not sys.argv: | ||
71 | print 'missing opensim/matrix URI' | ||
72 | sys.exit(1) | ||
73 | |||
74 | # | ||
75 | # parse URI and extract scheme. host, port?, avatar?, password? | ||
76 | # | ||
77 | uri = sys.argv.pop() | ||
78 | match = reURI.match(uri) | ||
79 | if not match or not match.group('scheme') or not match.group('host'): | ||
80 | print 'hmm... cannot parse URI %s, giving up' % uri | ||
81 | sys.exit(1) | ||
82 | |||
83 | scheme = match.group('scheme') | ||
84 | host = match.group('host') | ||
85 | port = match.group('port') | ||
86 | avatar = match.group('avatar') | ||
87 | password = match.group('password') | ||
88 | path = match.group('path') | ||
89 | |||
90 | # | ||
91 | # sanity check: matrix: or opensim: scheme? | ||
92 | # | ||
93 | if scheme != 'matrix' and scheme != 'opensim': | ||
94 | print 'hmm...unknown scheme %s, calling it a day' % scheme | ||
95 | |||
96 | # | ||
97 | # get grid info from OpenSim server | ||
98 | # | ||
99 | gridname = None | ||
100 | gridnick = None | ||
101 | login = None | ||
102 | welcome = None | ||
103 | economy = None | ||
104 | |||
105 | # | ||
106 | # construct GridInfo URL | ||
107 | # | ||
108 | if port: | ||
109 | gridInfoURI = 'http://%s:%d/get_grid_info' % (host, int(port)) | ||
110 | else: | ||
111 | gridInfoURI = 'http://%s/get_grid_info' % (host) | ||
112 | |||
113 | # | ||
114 | # try to retrieve GridInfo | ||
115 | # | ||
116 | try: | ||
117 | gridInfoXml = ET.parse(urllib2.urlopen(gridInfoURI)) | ||
118 | |||
119 | gridname = gridInfoXml.findtext('/gridname') | ||
120 | gridnick = gridInfoXml.findtext('/gridnick') | ||
121 | login = gridInfoXml.findtext('/login') | ||
122 | welcome = gridInfoXml.findtext('/welcome') | ||
123 | economy = gridInfoXml.findtext('/economy') | ||
124 | |||
125 | except urllib2.URLError: | ||
126 | print 'oops, failed to retrieve grid info, proceeding with guestimates...' | ||
127 | |||
128 | # | ||
129 | # fallback: use supplied uri in case GridInfo drew a blank | ||
130 | # | ||
131 | if not login: login = uri | ||
132 | |||
133 | # | ||
134 | # ok, got everything, now construct the command line | ||
135 | # | ||
136 | clientArgs = ['matrix: %s' % gridnick] | ||
137 | clientArgs += ['-loginuri', login] | ||
138 | |||
139 | if welcome: clientArgs += ['-loginpage', welcome] | ||
140 | if economy: clientArgs += ['-helperuri', economy] | ||
141 | |||
142 | if avatar and password: | ||
143 | clientArgs += ['-login'] | ||
144 | clientArgs += urllib.unquote(avatar).split() | ||
145 | clientArgs += [password] | ||
146 | |||
147 | # | ||
148 | # take a closer look at path: if it's a /region/X/Y/Z pattern, use | ||
149 | # it as the "SLURL | ||
150 | # | ||
151 | match = reLOC.match(path) | ||
152 | if match: | ||
153 | loc = 'secondlife:///%s/%d/%d/%d' % (match.group('region'), | ||
154 | int(match.group('x')), | ||
155 | int(match.group('y')), | ||
156 | int(match.group('z'))) | ||
157 | clientArgs += [loc] | ||
158 | |||
159 | # | ||
160 | # all systems go | ||
161 | # | ||
162 | os.execv(client, clientArgs) | ||