-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Alvaro Videla
committed
Jan 21, 2010
0 parents
commit fc96564
Showing
6 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
Copyright (c) 2010 Alvaro Videla <videlalvaro@gmail.com> | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
|
||
|
||
PHPUnserialize taken from http://hurring.com/code/python/phpserialize/ | ||
with modified version of session_decode by me |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import types, string, re | ||
|
||
""" | ||
Unserialize class for the PHP serialization format. | ||
@version v0.4 BETA | ||
@author Scott Hurring; scott at hurring dot com | ||
@copyright Copyright (c) 2005 Scott Hurring | ||
@license http://opensource.org/licenses/gpl-license.php GNU Public License | ||
$Id: PHPUnserialize.py,v 1.1 2006/01/08 21:53:19 shurring Exp $ | ||
Most recent version can be found at: | ||
http://hurring.com/code/python/phpserialize/ | ||
Usage: | ||
# Create an instance of the unserialize engine | ||
u = PHPUnserialize() | ||
# unserialize some string into python data | ||
data = u.unserialize(serialized_string) | ||
Please see README.txt for more information. | ||
""" | ||
|
||
class PHPUnserialize(object): | ||
""" | ||
Class to unserialize something from the PHP Serialize format. | ||
Usage: | ||
u = PHPUnserialize() | ||
data = u.unserialize(serialized_string) | ||
""" | ||
|
||
def __init__(self): | ||
pass | ||
|
||
def session_decode(self, data): | ||
"""Thanks to Ken Restivo for suggesting the addition | ||
of session_encode | ||
""" | ||
session = {} | ||
while len(data) > 0: | ||
(offset, key) = self.read_until(data, 0, '|') | ||
if offset > 0: | ||
(dtype, dataoffset, value) = self._unserialize(data, offset+1) | ||
data = data[offset+1+dataoffset:] | ||
session[key] = value | ||
else: | ||
return session | ||
|
||
return session | ||
|
||
def unserialize(self, data): | ||
return self._unserialize(data, 0)[2] | ||
|
||
def _unserialize(self, data, offset=0): | ||
""" | ||
Find the next token and unserialize it. | ||
Recurse on array. | ||
offset = raw offset from start of data | ||
return (type, offset, value) | ||
""" | ||
|
||
buf = [] | ||
dtype = string.lower(data[offset:offset+1]) | ||
|
||
#print "# dtype =", dtype | ||
|
||
# 't:' = 2 chars | ||
dataoffset = offset + 2 | ||
typeconvert = lambda x : x | ||
chars = datalength = 0 | ||
|
||
# int => Integer | ||
if dtype == 'i': | ||
typeconvert = lambda x : int(x) | ||
(chars, readdata) = self.read_until(data, dataoffset, ';') | ||
# +1 for end semicolon | ||
dataoffset += chars + 1 | ||
|
||
# bool => Boolean | ||
elif dtype == 'b': | ||
typeconvert = lambda x : (int(x) == 1) | ||
(chars, readdata) = self.read_until(data, dataoffset, ';') | ||
# +1 for end semicolon | ||
dataoffset += chars + 1 | ||
|
||
# double => Floating Point | ||
elif dtype == 'd': | ||
typeconvert = lambda x : float(x) | ||
(chars, readdata) = self.read_until(data, dataoffset, ';') | ||
# +1 for end semicolon | ||
dataoffset += chars + 1 | ||
|
||
# n => None | ||
elif dtype == 'n': | ||
readdata = None | ||
|
||
# s => String | ||
elif dtype == 's': | ||
(chars, stringlength) = self.read_until(data, dataoffset, ':') | ||
# +2 for colons around length field | ||
dataoffset += chars + 2 | ||
|
||
# +1 for start quote | ||
(chars, readdata) = self.read_chars(data, dataoffset+1, int(stringlength)) | ||
# +2 for endquote semicolon | ||
dataoffset += chars + 2 | ||
|
||
if chars != int(stringlength) != int(readdata): | ||
raise Exception("String length mismatch") | ||
|
||
# array => Dict | ||
# If you originally serialized a Tuple or List, it will | ||
# be unserialized as a Dict. PHP doesn't have tuples or lists, | ||
# only arrays - so everything has to get converted into an array | ||
# when serializing and the original type of the array is lost | ||
elif dtype == 'a': | ||
readdata = {} | ||
|
||
# How many keys does this list have? | ||
(chars, keys) = self.read_until(data, dataoffset, ':') | ||
# +2 for colons around length field | ||
dataoffset += chars + 2 | ||
|
||
# Loop through and fetch this number of key/value pairs | ||
for i in range(0, int(keys)): | ||
# Read the key | ||
(ktype, kchars, key) = self._unserialize(data, dataoffset) | ||
dataoffset += kchars | ||
#print "Key(%i) = (%s, %i, %s) %i" % (i, ktype, kchars, key, dataoffset) | ||
|
||
# Read value of the key | ||
(vtype, vchars, value) = self._unserialize(data, dataoffset) | ||
dataoffset += vchars | ||
#print "Value(%i) = (%s, %i, %s) %i" % (i, vtype, vchars, value, dataoffset) | ||
|
||
# Set the list element | ||
readdata[key] = value | ||
|
||
# +1 for end semicolon | ||
dataoffset += 1 | ||
#chars = int(dataoffset) - start | ||
|
||
# I don't know how to unserialize this | ||
else: | ||
raise Exception("Unknown / Unhandled data type (%s)!" % dtype) | ||
|
||
|
||
return (dtype, dataoffset-offset, typeconvert(readdata)) | ||
|
||
def read_until(self, data, offset, stopchar): | ||
""" | ||
Read from data[offset] until you encounter some char 'stopchar'. | ||
""" | ||
buf = [] | ||
char = data[offset:offset+1] | ||
i = 2 | ||
while char != stopchar: | ||
# Consumed all the characters and havent found ';' | ||
if i+offset > len(data): | ||
raise Exception("Invalid") | ||
buf.append(char) | ||
char = data[offset+(i-1):offset+i] | ||
i += 1 | ||
|
||
# (chars_read, data) | ||
return (len(buf), "".join(buf)) | ||
|
||
def read_chars(self, data, offset, length): | ||
""" | ||
Read 'length' number of chars from data[offset]. | ||
""" | ||
buf = [] | ||
# Account for the starting quote char | ||
#offset += 1 | ||
for i in range(0, length): | ||
char = data[offset+(i-1):offset+i] | ||
buf.append(char) | ||
|
||
# (chars_read, data) | ||
return (len(buf), "".join(buf)) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
usage: | ||
|
||
python session_inspector.py | ||
|
||
Commands: | ||
isauth session_id1 session_id2 session_id3 | ||
|
||
returns 0 or 1 if the user of that session id is authenticated | ||
each line of the response corresponds to one of the key passed | ||
the lines are ended by \r\n | ||
|
||
quit | ||
closes the connection to the server | ||
|
||
>telnet localhost 3002 | ||
isauth session_id | ||
isauth session_ida session_idb session_idc | ||
quit |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
INSPECTOR_INTERFACE='0.0.0.0' | ||
INSPECTOR_PORT=3002 | ||
|
||
# if you have several servers with different weigths, then try something like: | ||
# sessServers = (['127.0.0.1:11211'] * 3) + (['127.0.0.1:11212'] * 5) | ||
# where 3 and 5 are the weigths defined for those servers in Memcache::addServer in PHP | ||
sessServers = ['127.0.0.1:11211'] | ||
|
||
#memcache key prefix, use '' if none set. | ||
prefix = '' | ||
|
||
# key inside the session array that stores if the user is authenticated or not | ||
# for example this is what symfony uses | ||
auth_key = 'symfony/user/sfUser/authenticated' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from twisted.internet import reactor | ||
from twisted.internet.protocol import Factory | ||
from twisted.internet.error import ConnectionDone | ||
from twisted.protocols.basic import LineOnlyReceiver | ||
import memcache | ||
import sys | ||
from PHPUnserialize import * | ||
from conf import * | ||
|
||
mc = memcache.Client(sessServers, debug=0) | ||
|
||
class InspectorReceiver(LineOnlyReceiver): | ||
delimiter = '\r\n' | ||
|
||
def connectionMade(self): | ||
self.peer = self.transport.getPeer() | ||
self.peerAddr = "%s:%d" % (self.peer.host, self.peer.port) | ||
print("%s connection with %s established" % (self.__class__.__name__, self.peerAddr)) | ||
|
||
def connectionLost(self, reason): | ||
if reason.check(ConnectionDone): | ||
print("%s connection with %s closed cleanly" % (self.__class__.__name__, self.peerAddr)) | ||
else: | ||
print("%s connection with %s lost: %s" % (self.__class__.__name__, self.peerAddr, reason.value)) | ||
|
||
def isAuth(self, is_auth): | ||
self.transport.write("%d\r\n" % (is_auth, )) | ||
|
||
def lineReceived(self, line): | ||
global mc, prefix, auth_key | ||
|
||
try: | ||
values = line.strip().split() | ||
|
||
if len(values) < 1: | ||
pass | ||
|
||
if values[0] == 'isauth' and len(values) > 1: | ||
for key in values[1:]: | ||
data = mc.get(prefix + key) | ||
if not data: | ||
self.isAuth(False) | ||
else: | ||
try: | ||
session = PHPUnserialize().session_decode(data) | ||
self.isAuth(session[auth_key]) | ||
except: | ||
self.isAuth(False) | ||
|
||
elif values[0] == 'quit': | ||
self.transport.loseConnection() | ||
else: | ||
raise Exception('Invalid command') | ||
except: | ||
print('invalid line received from client %s' % self.peerAddr) | ||
return | ||
|
||
def startListener(interface, port, protocol): | ||
factory = Factory() | ||
factory.protocol = protocol | ||
return reactor.listenTCP( int(port), factory, interface=interface ) | ||
|
||
startListener(INSPECTOR_INTERFACE, INSPECTOR_PORT, InspectorReceiver) | ||
|
||
reactor.run() |