| 1 | #!/usr/bin/env python
|
---|
| 2 | """ Simple python server to allow Remote phonebook of ST2030 to work with
|
---|
| 3 | Asterisk server, using the phone and fullname settings of the config file
|
---|
| 4 | as input values, like
|
---|
| 5 | [20012]
|
---|
| 6 | fullname=Rick van der Zwet
|
---|
| 7 |
|
---|
| 8 |
|
---|
| 9 | In order to get it working alter HOST and PORT to the location of your webserver
|
---|
| 10 |
|
---|
| 11 | Next specify remote phone book URL to be http://HOST:PORT/search?q=#SEARCH
|
---|
| 12 | at Advanced -> Phone Lists -> Remote Phone Book in the webinterface
|
---|
| 13 |
|
---|
| 14 | OR
|
---|
| 15 |
|
---|
| 16 | In your autoprovising files the entries under the section [sys]
|
---|
| 17 | Phonebook1_url=http://HOST:PORT/search?q=#SEARCH
|
---|
| 18 | Phonebook1_name=example.com phone book
|
---|
| 19 |
|
---|
| 20 |
|
---|
| 21 |
|
---|
| 22 |
|
---|
| 23 | Original webserver template - Copyright Jon Berg , turtlemeat.com
|
---|
| 24 | """
|
---|
| 25 | from __future__ import with_statement
|
---|
| 26 | import string,cgi,time,os
|
---|
| 27 | from os import curdir, sep
|
---|
| 28 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
---|
| 29 | import urlparse, urllib
|
---|
| 30 | import ConfigParser
|
---|
| 31 |
|
---|
| 32 | __author__ = "Rick van der Zwet"
|
---|
| 33 | __copyright = "Copyright 2008, Rick van der Zwet"
|
---|
| 34 | __licence__ = "BSD"
|
---|
| 35 | __version__ = "0.0.2"
|
---|
| 36 | __maitainer__ = "Rick van der Zwet"
|
---|
| 37 | __email__ = "rick@wzoeterwoude.net"
|
---|
| 38 | __status__ = "Production"
|
---|
| 39 | __credits__ = [" Jon Berg , turtlemeat.com"]
|
---|
| 40 | __website__ = "http://rickvanderzwet.nl/svn/data/develop/pythonplaza/asterisk-remote-phonebook.py"
|
---|
| 41 |
|
---|
| 42 | #
|
---|
| 43 | # Specify your asterisk config file and the IP/host you like the mini-server to
|
---|
| 44 | # be running on
|
---|
| 45 | USERFILE='/etc/asterisk/users.conf'
|
---|
| 46 | LOGFILE='/var/log/phonebook.log'
|
---|
| 47 | HOST='192.168.50.10'
|
---|
| 48 | PORT=8000
|
---|
| 49 |
|
---|
| 50 | class MyHandler(BaseHTTPRequestHandler):
|
---|
| 51 | __base = BaseHTTPRequestHandler
|
---|
| 52 |
|
---|
| 53 | protocol_version = "HTTP/1.0"
|
---|
| 54 |
|
---|
| 55 | def log_message(self, format, *args):
|
---|
| 56 | """Log an arbitrary message., custom function, log to file, instead of stdout
|
---|
| 57 | """
|
---|
| 58 |
|
---|
| 59 | with open(LOGFILE,"a") as f:
|
---|
| 60 | f.write("%s - - [%s] %s\n" %
|
---|
| 61 | (self.address_string(),
|
---|
| 62 | self.log_date_time_string(),
|
---|
| 63 | format%args))
|
---|
| 64 |
|
---|
| 65 |
|
---|
| 66 | def do_GET(self):
|
---|
| 67 | parsed_path = urlparse.urlparse(self.path)
|
---|
| 68 | rpath = parsed_path.path
|
---|
| 69 | qdict = cgi.parse_qs(parsed_path.query,True)
|
---|
| 70 |
|
---|
| 71 | if rpath == '/search':
|
---|
| 72 | if qdict.has_key('q'):
|
---|
| 73 | searchkey = qdict['q'][0].lower()
|
---|
| 74 | else:
|
---|
| 75 | qdict['q'] = ' '
|
---|
| 76 | searchkey = ' '
|
---|
| 77 |
|
---|
| 78 | #Parse astrisk file, fetch phone number and Name
|
---|
| 79 | config = ConfigParser.ConfigParser()
|
---|
| 80 | try:
|
---|
| 81 | config.readfp(open(USERFILE))
|
---|
| 82 | except IOError:
|
---|
| 83 | self.send_error(404,'Config file not found/readable: %s' % USERFILE)
|
---|
| 84 | return
|
---|
| 85 |
|
---|
| 86 | #Do matching
|
---|
| 87 | results = []
|
---|
| 88 | for section in config.sections():
|
---|
| 89 | try:
|
---|
| 90 | if config.get(section, 'fullname').lower().find(searchkey) != -1:
|
---|
| 91 | results.append(([config.get(section, 'fullname')][0], section));
|
---|
| 92 | except ConfigParser.NoOptionError:
|
---|
| 93 | pass
|
---|
| 94 | results.sort()
|
---|
| 95 |
|
---|
| 96 | #Get right output part
|
---|
| 97 | if qdict.has_key('from'):
|
---|
| 98 | f = int(qdict['from'][0])
|
---|
| 99 | t = f + 31
|
---|
| 100 | if t > len(results):
|
---|
| 101 | t = len(results)
|
---|
| 102 | results = results[f:t]
|
---|
| 103 |
|
---|
| 104 |
|
---|
| 105 | output = ''
|
---|
| 106 | if (len(results) < 32):
|
---|
| 107 | output += '<ThomsonPhoneBook>\n'
|
---|
| 108 | #result smaller 32 hits
|
---|
| 109 | for name, phone in results:
|
---|
| 110 | output += '<DirectoryEntry>\n'
|
---|
| 111 | output += '\t<Name>%s</Name>\n' % name
|
---|
| 112 | output += '\t<Telephone>%s</Telephone>\n' % phone
|
---|
| 113 | output += '</DirectoryEntry>\n'
|
---|
| 114 | output += '</ThomsonPhoneBook>\n'
|
---|
| 115 | else:
|
---|
| 116 | output += '<ThomsonPhoneMenu>\n'
|
---|
| 117 | p = 0
|
---|
| 118 | while (p < len(results)):
|
---|
| 119 | # Damm phone, no & but & only
|
---|
| 120 | url = 'http://%s:%s/search?q=%s&from=%s' % (HOST, PORT, urllib.quote_plus(qdict['q'][0]), p)
|
---|
| 121 | #url = 'http://%s:%s/search' % (HOST, PORT)
|
---|
| 122 | name_start = results[p][0]
|
---|
| 123 | if (p + 31 < len(results)):
|
---|
| 124 | name_end = results[p+31][0]
|
---|
| 125 | else:
|
---|
| 126 | name_end = results[len(results) - 1][0]
|
---|
| 127 | output += '<MenuItem>\n'
|
---|
| 128 | output += '\t<Name>%s -> %s</Name>\n' % (name_start, name_end)
|
---|
| 129 | output += '\t<URL>%s</URL>\n' % url
|
---|
| 130 | output += '</MenuItem>\n'
|
---|
| 131 | p = p + 32
|
---|
| 132 | output += '</ThomsonPhoneMenu>\n'
|
---|
| 133 |
|
---|
| 134 | # Output file
|
---|
| 135 | # Broken Phone ST2030, requires \r on all headers
|
---|
| 136 | # Broken Phone ST2030 does not properly support HTTP/1.1 as keep-alive
|
---|
| 137 | # is not running properly , could _not_ be seperated into properly
|
---|
| 138 | # self.send_response(200), self.send_header('Connnection: close')
|
---|
| 139 |
|
---|
| 140 | # Allow easy XML debugging in Mozilla Firefox 3
|
---|
| 141 | # * Content-Type is don't care value, might as well text/plain
|
---|
| 142 | # * Connection: close is don't care value
|
---|
| 143 |
|
---|
| 144 | head = 'HTTP/1.0 200 OK\r\n'
|
---|
| 145 | head += 'Content-Length: %s\r\n' % len(output)
|
---|
| 146 | head += 'Content-Type: application/xml\r\n'
|
---|
| 147 | head += 'Connection: close\r\n'
|
---|
| 148 | head += '\r\n'
|
---|
| 149 | self.wfile.write(head + output + '\r\n');
|
---|
| 150 |
|
---|
| 151 | # Force connection closing
|
---|
| 152 | self.close_connection = 1
|
---|
| 153 | # Log succesfull request
|
---|
| 154 | self.log_request(200,len(output))
|
---|
| 155 |
|
---|
| 156 | def main():
|
---|
| 157 | server = HTTPServer((HOST, PORT), MyHandler)
|
---|
| 158 | try:
|
---|
| 159 | pid = os.fork()
|
---|
| 160 | except OSError, e:
|
---|
| 161 | raise Exception, "%s [%d]" % (e.strerror, e.errno)
|
---|
| 162 | if (pid==0):
|
---|
| 163 | os.setsid()
|
---|
| 164 | print 'started httpserver on %s:%s... (pid=%s)' % (HOST, PORT, os.getpid())
|
---|
| 165 | print 'Logfile at: %s' % LOGFILE
|
---|
| 166 | server.serve_forever()
|
---|
| 167 | # On any signal close socket
|
---|
| 168 | # server.socket.close()
|
---|
| 169 | else:
|
---|
| 170 | os._exit(0)
|
---|
| 171 |
|
---|
| 172 | if __name__ == '__main__':
|
---|
| 173 | main()
|
---|
| 174 |
|
---|