From 2d097f07c21dfdacd3359c264ff1e0202d5d5014 Mon Sep 17 00:00:00 2001 From: "locklainn.linden" Date: Mon, 30 Jun 2008 13:21:26 +0000 Subject: [PATCH] put back all the files that were used in the old pyogp code for historical and referencing purposes --- pyogp/lib/base/client/__init__.py | 31 +++ pyogp/lib/base/client/legacylogin.py | 48 ++++ pyogp/lib/base/client/login.py | 82 +++++++ pyogp/lib/base/client/ogplogin.py | 208 ++++++++++++++++++ pyogp/lib/base/simulator/__init__.py | 31 +++ pyogp/lib/base/tests/test.py | 48 ++++ .../lib/base/tests/test_request_rez_avatar.py | 101 +++++++++ 7 files changed, 549 insertions(+) create mode 100644 pyogp/lib/base/client/__init__.py create mode 100644 pyogp/lib/base/client/legacylogin.py create mode 100644 pyogp/lib/base/client/login.py create mode 100644 pyogp/lib/base/client/ogplogin.py create mode 100644 pyogp/lib/base/simulator/__init__.py create mode 100644 pyogp/lib/base/tests/test.py create mode 100644 pyogp/lib/base/tests/test_request_rez_avatar.py diff --git a/pyogp/lib/base/client/__init__.py b/pyogp/lib/base/client/__init__.py new file mode 100644 index 0000000..4127571 --- /dev/null +++ b/pyogp/lib/base/client/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +""" +@file __init__.py +@author Linden Lab +@date 2008-06-13 +@brief Iniitializes path directories + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, Linden Research, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +$/LicenseInfo$ +""" + +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/pyogp/lib/base/client/legacylogin.py b/pyogp/lib/base/client/legacylogin.py new file mode 100644 index 0000000..9ddcfd0 --- /dev/null +++ b/pyogp/lib/base/client/legacylogin.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +""" +@file ogplogin.py +@author Linden Lab +@date 2008-06-13 +@brief Iniitializes path directories + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, Linden Research, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +$/LicenseInf +""" + +from urlparse import urlparse +import xmlrpclib +import httplib, urllib2 +import os.path + +from indra.base import llsd + +from pyogp.lib.agent import Agent +from pyogp.lib.capabilities import Capabilities +from pyogp.client.login import Login + +class LegacyLogin(Login): + + def onLogin(self): + """ logs in an agent to the ogp agent domain """ + + pass + + def legacyLogin(self, llsdloginparams, headers): + """ handles post to Second Life's legacy login uri """ + + pass + diff --git a/pyogp/lib/base/client/login.py b/pyogp/lib/base/client/login.py new file mode 100644 index 0000000..f15a3a4 --- /dev/null +++ b/pyogp/lib/base/client/login.py @@ -0,0 +1,82 @@ +#!/usr/bin/python +""" +@file login.py +@author Linden Lab +@date 2008-06-13 +@brief Iniitializes path directories + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, Linden Research, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +$/LicenseInfo$ +""" + +from urlparse import urlparse +import xmlrpclib +import httplib, urllib2 +import os.path + +if os.path.exists("../../../setup_path.py"): + execfile("../../../setup_path.py") + +from indra.base import llsd + +from pyogp.lib.agent import Agent +from pyogp.lib.capabilities import Capabilities + +class Login(): + + def __init__(self, agent=None): + """ initialize base login class """ + + self.agent = agent + self.loginstatus = False + self.loginparams = {} + self.loginuri = '' + + def login(self): + """ common api for logging in an agent to a grid """ + + self.loginparams = self.agent.getLoginParams() + + self.loginuri = self.agent.loginuri + + seedcap = self.onLogin() + + """urlbits = urlparse(self.agent.loginuri) + # support agent domain login and legacy login + + if (urlbits.path == '/cgi-bin/auth.cgi'): + seedcap = self.ogpLogin() + elif (urlbits.path == '/cgi-bin/login.cgi'): + seedcap = self.legacyLogin() + """ + + return seedcap + + def onLogin(self): + """ Just the abstract method that will do all the login work. To be derived. """ + + pass + + def loginStatus(self): + """ returns login status of agent """ + + return self.loginstatus + + def updateLoginStatus(self, status): + """ toggle the loginstatus var value """ + + self.loginstatus = status diff --git a/pyogp/lib/base/client/ogplogin.py b/pyogp/lib/base/client/ogplogin.py new file mode 100644 index 0000000..ee84ded --- /dev/null +++ b/pyogp/lib/base/client/ogplogin.py @@ -0,0 +1,208 @@ +#!/usr/bin/python +""" +@file ogplogin.py +@author Linden Lab +@date 2008-06-13 +@brief Iniitializes path directories + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, Linden Research, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +$/LicenseInf +""" + +import sys, struct +import socket +from urlparse import urlparse +import xmlrpclib +import httplib, urllib2 +import os.path +import pprint + +# linden provided libs +from indra.base import llsd +from indra.ipc import llsdhttp +from indra.base import lluuid + +# lib classes +from pyogp.lib.agent import Agent +from pyogp.lib.capabilities import Capabilities +from pyogp.client.login import Login + +# defaults for the purpose of this test script +debug = True + +class OGPLogin(Login): + + def onLogin(self): + """ logs in an agent to the ogp agent domain """ + + # todo: work with password or md5pass + loginparams={#'type' : 'agent', + 'password' : self.loginparams['password'], # md5-password '$1$' + md5hash + 'lastname' : self.loginparams['lastname'], + 'firstname' : self.loginparams['firstname'], + } + + # format the llsd to post to the loginuri + llsdloginparams = llsd.format_xml(loginparams) + + # define the header for the post + headers = {"Content-type" : "application/llsd+xml"} + + seedcap = self.postOGPLogin(llsdloginparams, headers) + + if seedcap == None: + print 'Login failed!' + return None + + if debug: + print 'Login complete, agent_seed_cap is: ' + seedcap + + # is this where we update loginstatus var? we are authenticated, i'm going to say yes + self.updateLoginStatus(True) + + capabilities = Capabilities(self.agent, 30) + + capabilities.appendCap('agent_seed_cap', seedcap) + + if debug: + print 'Logged in status = ' + str(self.loginStatus()) + print capabilities.printCaps() + + # post to seed cap a req for place avatar + headers = {"Content-type" : "application/llsd+xml"} + data = {'TESTINGPOST': None, 'caps':{'place_avatar':True, 'event_queue': True, 'rez_avatar':True}} + data = llsd.format_xml(data) + + if debug: + print '' + print 'Posting to seedcap for place_avatar_cap' + + result = capabilities.postToCap(capabilities.capabilities['agent_seed_cap'], headers, data) + + print 'Caps returned are: ' + str(llsd.parse(result)['caps']) + capabilities.updateCaps(llsd.parse(result)['caps']) + #capabilities.appendCap('place_avatar', llsd.parse(result)['caps']['place_avatar']) + + if debug: + print 'Result of seedcap post for place avatar = ' + print pprint.pprint(llsd.parse(result)) + print capabilities.printCaps() + print '' + + # post to event_queue_cap to set up reverse_HTTP + #headers = {"Upgrade" : "PTTH/0.9"} + #data = {} + #print 'Posting to event_queue' + #result = capabilities.postToCap(capabilities.capabilities['event_queue'], headers, data) + + #print "\nThe result of upgrade is: " + #print result + #print '' + + # post to place avatar cap with region uri + headers = {"Content-type" : "application/llsd+xml"} + data = {'region_url':self.agent.regionuri}#, 'position' : [0.0,0.0,0.0]} + data = llsd.format_xml(data) + + print 'Posting to seedcap place_avatar with region_url' + result = capabilities.postToCap(capabilities.capabilities['place_avatar'], headers, data) + if result == None: + print 'Post to place_avatar failed' + return + + if debug: + print 'Result of seedcap post to place avatar = ' + print pprint.pprint(llsd.parse(result)) + print capabilities.printCaps() + print '' + + capabilities.appendCap('sim_seed_cap', llsd.parse(result)['seed_capability']) + + #post to seed cap for sim to get placed + #from here, it is the same as legacy + +## print 'Posting to simulator to get placed' +## headers = {"Content-type" : "application/llsd+xml"} +## data = {'region_url':agent.regionuri} +## data = llsd.format_xml(data) +## +## result = capabilities.postToCap(capabilities.capabilities['sim_seed_cap'], headers, data) +## +## if debug: +## print 'Result of seedcap post for place_avatar = ' +## print pprint.pprint(llsd.parse(result)) + + results = llsd.parse(result) + print "Results" + pprint.pprint(results) + session_id = lluuid.UUID(results['session_id']) + secure_session_id = lluuid.UUID(results['secure_session_id']) + agent_id = lluuid.UUID(results['agent_id']) + + host = results['sim_ip'] + port = results['sim_port'] + circuit_code = struct.pack("I", results['circuit_code']) + seed_capability_url = results['seed_capability'] + + agent_movement_header = '\x40\x00\x00\x00\x03\x00\xff\xff\x00\xf9' + circuit_code_header = '\x40\x00\x00\x00\x01\x00\xff\xff\x00\x03' + + agent_move_packet = agent_movement_header + agent_id._bits + session_id._bits + circuit_code + circuit_use_packet = circuit_code_header + circuit_code + session_id._bits + agent_id._bits + + sim_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sim_udp.sendto(circuit_use_packet, (host, port)) + sim_udp.sendto(agent_move_packet, (host, port)) + #sim_udp.close() + + return results + + def postOGPLogin(self, llsdloginparams, headers): + """ handles the post to the Second Life's agent domain login uri, and the redirect upon success """ + + request = urllib2.Request(self.loginuri, llsdloginparams, headers) + + # todo: handle non 302 cases! there's plenty, and lots are test cases + # per the protocol, a successful authentication returns a 302 with the seedcap embedded in the headers + class RedirectHandler(urllib2.HTTPRedirectHandler): + + def http_error_302(self, req, fp, code, msg, headers): + #parse the redirect, grabbing the seed cap url from the headers + if True: + print '' + print 'contents of response = ' + print headers + print msg + print '' + + + # per the protocol, the seedcap is in the 'location' in headers + return headers['location'] + + # post to auth.cgi, ignoring the built in redirect + opener = urllib2.build_opener(RedirectHandler()) + + try: + seed_cap = opener.open(request) + return seed_cap + except urllib2.HTTPError, e: + print 'HTTP Error: ', e.code + except urllib2.URLError, e: + print 'URL Error: ', e.reason + + return None + diff --git a/pyogp/lib/base/simulator/__init__.py b/pyogp/lib/base/simulator/__init__.py new file mode 100644 index 0000000..4127571 --- /dev/null +++ b/pyogp/lib/base/simulator/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +""" +@file __init__.py +@author Linden Lab +@date 2008-06-13 +@brief Iniitializes path directories + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, Linden Research, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +$/LicenseInfo$ +""" + +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/pyogp/lib/base/tests/test.py b/pyogp/lib/base/tests/test.py new file mode 100644 index 0000000..af625d2 --- /dev/null +++ b/pyogp/lib/base/tests/test.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +""" +@file test.py +@author Linden Lab +@date 2008-06-13 +@brief Iniitializes path directories + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, Linden Research, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +$/LicenseInfo$ +""" + +# intend to build suites out of each of the subdirs, and to execute the suites... +# this is just getting started, as is a lot of the rest.... + +import unittest +import sys +import os + +suites = [] +# grab path and import all tests +for root, dirs, files in os.walk(os.getcwd): + + sys.path.append(dir) + + suites.append[dir] + + for file in files: + import file + + +# todo: um, make a test framework? + +if __name__ = '__main__': + unittest.main() diff --git a/pyogp/lib/base/tests/test_request_rez_avatar.py b/pyogp/lib/base/tests/test_request_rez_avatar.py new file mode 100644 index 0000000..0269950 --- /dev/null +++ b/pyogp/lib/base/tests/test_request_rez_avatar.py @@ -0,0 +1,101 @@ +#!/usr/bin/python + +import unittest +from indra.ipc import llsdhttp +from indra.base import lluuid + +class RequestRezAvatarTests(unittest.TestCase): + agent_id = '3d2b8256-12cd-40fd-abf8-6da4ad6739a2' + regionuri = 'http://sim2.vaak.lindenlab.com:12035' + # http://sim2.vaak.lindenlab.com:12035/agent/(uuid)/rez_avatar/request + request_rez_avatar_url = regionuri + '/agent/' + agent_id + '/rez_avatar/request' + default_arguments={ + 'agent_id' : agent_id, + 'first_name': 'Leyla', + 'last_name': 'Tester', + 'age_verified' : True, + 'agent_access' : True, + 'god_level': 200, + 'identified': True, + 'transacted': True, + 'limited_to_estate': 1, + 'sim_access' : 'Mature' + } + def check_successful_response(self, arguments): + print "ARGs", arguments + result = llsdhttp.post(self.request_rez_avatar_url, arguments) + print "RESULT", result + # check for existence of fields + self.assert_(result.has_key('connect') and + result.has_key('rez_avatar/rez') and + result.has_key('sim_ip') and + result.has_key('sim_port') and + result.has_key('region_x') and + result.has_key('region_y') and + result.has_key('region_id') and + result.has_key('sim_access') and + result.has_key('seed_capability')) + + self.assertEquals(result['connect'], True) + self.assert_(result['region_x'] < 256) + self.assert_(result['region_x'] < 256) + self.assert_(isUUID(result['region_id'])) + + def check_failure_response(self, arguments): + print "ARGs", arguments + try: + result = llsdhttp.post(self.request_rez_avatar_url, arguments) + print "RESULT", result + except Exception, e: + # supposed to be error + return + + self.assertEquals(result['connect'], False) + + def test0_simple(self): + self.check_successful_response(self.default_arguments) + + def test1_unverified(self): + """ Unverified agents should not be allowed """ + args = self.default_arguments + args['age_verified'] = False + self.check_failure_response(args) + + def test2_noaccess(self): + """ Agents without access cannot be allowed """ + args = self.default_arguments + args['agent_access'] = False + self.check_failure_response(args) + + def test3_unidentified(self): + """ Unidentified agents should not be allowed """ + args = self.default_arguments + args['identified'] = False + self.check_failure_response(args) + + def test4_godlevel(self): + """ Gods are allowed in teen regions """ + args = self.default_arguments + args['god_level'] = 0 + self.check_failure_response(args) + + def test5_untransacted(self): + """ Agents not transacted are not allowed in ____ regions """ + args = self.default_arguments + args['transacted'] = False + self.check_failure_response(args) + + def test6_limited_estate(self): + """ Teens limited to estate 5 cannot access adult regions """ + args = self.default_arguments + args['limited_to_estate'] = 5 + self.check_failure_response(args) + + def test7_sim_access(self): + """ Agents with PG access cannot access mature region """ + args = self.default_arguments + args['sim_access'] = 'PG' + self.check_failure_response(args) + +if __name__ == '__main__': + unittest.main()