1
2
3 """
4 This file is part of the web2py Web Framework (Copyrighted, 2007-2008)
5 Developed in Python by Massimo Di Pierro <mdipierro@cs.depaul.edu>
6 """
7
8 import sys, cStringIO
9
10 if sys.version[:3]!='2.5':
11 sys.stderr.write('Warning: web2py requires Python 2.5 but, instead, you are running:\n%s' % sys.version)
12
13 ProgramName="web2py Enterprise Web Framework"
14 ProgramAuthor='Created by Massimo Di Pierro, Copyright 2007-2008'
15 ProgramVersion=open('VERSION','r').read().strip()
16
19 self.buffer=cStringIO.StringIO()
21 sys.__stdout__.write(data)
22 if hasattr(self,'callback'): self.callback(data)
23 else: self.buffer.write(data)
24
25 try:
26 import tkMessageBox, Tkinter
27 havetk=True
28 except:
29 havetk=False
30
31 print ProgramName
32 print ProgramAuthor
33 print ProgramVersion
34
35 from gluon.main import HttpServer, save_password
36 from gluon.fileutils import tar, untar
37 from optparse import *
38 from gluon.shell import run
39 import time, webbrowser, thread, re, cStringIO, os, stat, socket, signal, math
40
42 try: webbrowser.open(url)
43 except: print 'warning: unable to detect your browser'
44
46 print 'please visit:'
47 print '\thttp://%s:%s/welcome' % (ip,port)
48 print 'starting browser...in 5 seconds'
49 time.sleep(5)
50 try_start_browser('http://%s:%s/welcome'%(ip,port))
51
53 root.withdraw()
54 dx=root.winfo_screenwidth()
55 dy=root.winfo_screenheight()
56 dialog=Tkinter.Toplevel(root)
57 dialog.geometry('%ix%i+%i+%i' % (400,300,dx/2-200, dy/2-150))
58 dialog.overrideredirect(1)
59 dialog.focus_force()
60 canvas=Tkinter.Canvas(dialog, background='white', width=400, height=300)
61 canvas.pack()
62 root.update()
63 for counter in xrange(5):
64 if counter is 0:
65 canvas.create_text(200,50, text='Welcome to ...',
66 font=('Helvetica',12),
67 anchor=Tkinter.CENTER, fill='#195866')
68 elif counter is 1:
69 canvas.create_text(200,130, text=ProgramName,
70 font=('Helvetica',18),
71 anchor=Tkinter.CENTER, fill='#FF5C1F')
72 elif counter is 2:
73 canvas.create_text(200,170,
74 text=ProgramAuthor,
75 font=('Helvetica',12),
76 anchor=Tkinter.CENTER, fill='#195866')
77 elif counter is 3:
78 canvas.create_text(200,250, text=ProgramVersion,
79 font=('Helvetica',12),
80 anchor=Tkinter.CENTER, fill='#195866')
81 else:
82 dialog.destroy()
83 return
84 root.update()
85 time.sleep(1.5)
86 return root
87
90 root.title('web2py server')
91 self.root=Tkinter.Toplevel(root)
92 self.options=options
93 self.menu=Tkinter.Menu(self.root)
94 servermenu = Tkinter.Menu(self.menu,tearoff=0)
95 httplog=os.path.join(os.getcwd(),'httpserver.log')
96 servermenu.add_command(label='View httpserver.log',
97 command=lambda:try_start_browser(httplog))
98 servermenu.add_command(label='Quit (pid:%i)' % os.getpid(),
99 command=self.quit)
100 self.menu.add_cascade(label="Server", menu=servermenu)
101
102 self.pagesmenu = Tkinter.Menu(self.menu,tearoff=0)
103 self.menu.add_cascade(label="Pages", menu=self.pagesmenu)
104
105 helpmenu = Tkinter.Menu(self.menu,tearoff=0)
106 helpmenu.add_command(label="Home Page", command=lambda: try_start_browser('http://www.web2py.com'))
107 helpmenu.add_command(label="About", command=lambda:tkMessageBox.showinfo('About web2py','%s\n%s\n%s'%(ProgramName,ProgramAuthor,ProgramVersion)))
108 self.menu.add_cascade(label="Info", menu=helpmenu)
109
110 self.root.config(menu=self.menu)
111 self.root.protocol("WM_DELETE_WINDOW", self.quit)
112 sticky=Tkinter.NW
113 Tkinter.Label(self.root, text="Choose a password:",justify=Tkinter.LEFT).grid(row=0,column=0,sticky=sticky)
114 self.password = Tkinter.Entry(self.root,show='*')
115 self.password.grid(row=0, column=1,sticky=sticky)
116 Tkinter.Label(self.root, text="Running from host:",justify=Tkinter.LEFT).grid(row=1,column=0,sticky=sticky)
117 self.ip = Tkinter.Entry(self.root)
118 self.ip.insert(Tkinter.END,'127.0.0.1')
119 self.ip.grid(row=1, column=1,sticky=sticky)
120 Tkinter.Label(self.root, text="Running from port:",justify=Tkinter.LEFT).grid(row=2,column=0,sticky=sticky)
121 self.port_number = Tkinter.Entry(self.root)
122 self.port_number.insert(Tkinter.END,'8000')
123 self.port_number.grid(row=2, column=1,sticky=sticky)
124 self.canvas=Tkinter.Canvas(self.root,width=300,height=100,bg='black')
125 self.canvas.grid(row=3,column=0,columnspan=2)
126 self.canvas.after(1000,self.update_canvas)
127 frame=Tkinter.Frame(self.root)
128 frame.grid(row=4,column=0,columnspan=2)
129 self.button_start=Tkinter.Button(frame,text='start server',command=self.start)
130 self.button_start.grid(row=0, column=0)
131 self.button_stop=Tkinter.Button(frame,text='stop server',command=self.stop)
132 self.button_stop.grid(row=0, column=1)
133 self.button_stop.configure(state='disabled')
134
136 try:
137 self.text.configure(state='normal')
138 self.text.insert('end',text)
139 self.text.configure(state='disabled')
140 except: pass
141 - def connect_pages(self):
142 for file in os.listdir('applications/'):
143 if os.access('applications/%s/__init__.py' % file,os.R_OK):
144 url=self.url+'/'+file
145 self.pagesmenu.add_command(label=url, command=lambda u=url:try_start_browser(u))
147 try: self.server.stop()
148 except: pass
149 self.root.destroy()
150 sys.exit()
151 - def error(self,message):
152 tkMessageBox.showerror("web2py start server",message)
153 return
155 password=self.password.get()
156 if not password:
157 self.error('no password, no web admin interface')
158 ip=self.ip.get()
159 if ip and not re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}').match(ip):
160 return self.error('invalid host ip address')
161 try: port=int(self.port_number.get())
162 except:
163 return self.error('invalid port number')
164 self.url='http://%s:%s' % (ip,port)
165 self.connect_pages()
166 self.button_start.configure(state='disabled')
167 try:
168 options=self.options
169 self.server=HttpServer(ip,port,password,
170 pid_filename=options.pid_filename,
171 log_filename=options.log_filename,
172 ssl_certificate=options.ssl_certificate,
173 ssl_private_key=options.ssl_private_key,
174 numthreads=options.numthreads,
175 server_name=options.server_name,
176 request_queue_size=options.request_queue_size,
177 timeout=options.timeout,
178 shutdown_timeout=options.shutdown_timeout,
179 path=options.folder)
180 thread.start_new_thread(self.server.start,())
181 except BaseException, e:
182 self.button_start.configure(state='normal')
183 return self.error(str(e))
184 self.button_stop.configure(state='normal')
185 thread.start_new_thread(start_browser,(ip,port))
186 self.password.configure(state='readonly')
187 self.ip.configure(state='readonly')
188 self.port_number.configure(state='readonly')
190 self.button_start.configure(state='normal')
191 self.button_stop.configure(state='disabled')
192 self.password.configure(state='normal')
193 self.ip.configure(state='normal')
194 self.port_number.configure(state='normal')
195 self.server.stop()
197 try:
198 t1=os.stat('httpserver.log')[stat.ST_SIZE]
199 except:
200 self.canvas.after(1000, self.update_canvas )
201 return
202 try:
203 file=open('httpserver.log','r')
204 file.seek(self.t0)
205 data=file.read(t1-self.t0)
206 self.p0=self.p0[1:]+[10+90.0/math.sqrt(1+data.count('\n'))]
207 for i in xrange(len(self.p0)-1):
208 c=self.canvas.coords(self.q0[i])
209 self.canvas.coords(self.q0[i],
210 (c[0],self.p0[i],c[2],self.p0[i+1]))
211 self.t0=t1
212 except BaseException, e:
213 self.t0=time.time()
214 self.t0=t1
215 self.p0=[100]*300
216 self.q0=[self.canvas.create_line(i,100,i+1,100,fill='green') for i in xrange(len(self.p0)-1)]
217 self.canvas.after(1000, self.update_canvas )
218
220 usage="""python web2py.py"""
221 description="""web2py Web Framework startup script. ATTENTION: unless a password is specified (-a 'passwd') web2py will attempt to run a GUI. In this case command line options are ignored."""
222 parser=OptionParser(usage,None,Option,ProgramVersion)
223 parser.description=description
224 parser.add_option('-i','--ip',default='127.0.0.1',dest='ip',
225 help='the ip address of the server (127.0.0.1)')
226 parser.add_option('-p','--port',default='8000',dest='port',
227 help='the port for of server (8000)')
228 parser.add_option('-a','--password',default='<ask>',dest='password',
229 help='the password to be used for administration'+\
230 "(use -a '<recycle>' to reuse the last password)")
231 parser.add_option('-u','--upgrade',default='no',dest='upgrade',
232 help='upgrade applications')
233 parser.add_option('-c','--ssl_certificate',default='',
234 dest='ssl_certificate',
235 help='file that contains ssl certificate')
236 parser.add_option('-k','--ssl_private_key',default='',
237 dest='ssl_private_key',
238 help='file that contains ssl private key')
239 parser.add_option('-d','--pid_filename',default='httpserver.pid',
240 dest='pid_filename',
241 help='file where to store the pid of the server')
242 parser.add_option('-l','--log_filename',default='httpserver.log',
243 dest='log_filename',
244 help='file where to log connections')
245 parser.add_option('-n','--numthreads',default='10',
246 dest='numthreads',
247 help='number of threads')
248 parser.add_option('-s','--server_name',default=socket.gethostname(),
249 dest='server_name',
250 help='the server name for the web server')
251 parser.add_option('-q','--request_queue_size',default='5',
252 dest='request_queue_size',
253 help='max number of queued requests when server unavailable')
254 parser.add_option('-o','--timeout',default='10',
255 dest='timeout',
256 help='timeout for individual request')
257 parser.add_option('-z','--shutdown_timeout',default='5',
258 dest='shutdown_timeout',
259 help='timeout on shutdown of server')
260 parser.add_option('-f','--folder',default=os.getcwd(),
261 dest='folder',
262 help='the folder where to run web2py')
263 parser.add_option('-S', '--shell',
264 dest='shell', metavar='APPNAME',
265 help='run web2py in interactive shell or IPython(if installed) with specified appname')
266 parser.add_option('-P', '--plain', action='store_true', default=False,
267 dest='plain',
268 help='only use plain python shell, should be used with --shell option')
269 parser.add_option('-M', '--import_models', action='store_true', default=False,
270 dest='import_models',
271 help='auto import model files, default is False, should be used with --shell option')
272 parser.add_option('-R', '--run', dest='run', metavar='PYTHON_FILE', default='',
273 help='run PYTHON_FILE in web2py environment, should be used with --shell option')
274 (options, args) = parser.parse_args()
275 if not os.access('applications', os.F_OK): os.mkdir('applications')
276 if not os.access('deposit', os.F_OK): os.mkdir('deposit')
277 if not os.access('applications/__init__.py',os.F_OK) or options.upgrade=='yes':
278 print 'unpacking apps, this may take a few minutes...'
279 if not os.access('applications/admin', os.F_OK):
280 os.mkdir('applications/admin')
281 untar('admin.tar','applications/admin/')
282 if not os.access('applications/welcome', os.F_OK):
283 os.mkdir('applications/welcome')
284 untar('welcome.tar','applications/welcome/')
285 if not os.access('applications/examples', os.F_OK):
286 os.mkdir('applications/examples')
287 untar('examples.tar','applications/examples/')
288 open('applications/__init__.py','w').write('')
289 print 'default applications are now installed'
290 else:
291 print 'default applications appear to be installed already'
292 return options
293
295 options=console()
296 if options.shell:
297 run(options.shell, plain=options.plain, import_models=options.import_models,
298 startfile=options.run)
299 return
300 root=None
301 if options.password=='<ask>' and havetk:
302 try: root=Tkinter.Tk()
303 except: pass
304 if root:
305 root.focus_force()
306 presentation(root)
307 master=web2pyDialog(root,options)
308 signal.signal(signal.SIGTERM,lambda a,b: master.quit())
309 try: root.mainloop()
310 except: master.quit()
311 sys.exit()
312 if not root and options.password=='<ask>':
313 options.password=raw_input('choose a password:')
314 if not options.password:
315 print 'no password, no admin interface'
316 ip,port=options.ip,int(options.port)
317 print 'please visit:'
318 print '\thttp://%s:%s/welcome' % (ip,port)
319 print 'use "kill -SIGTERM %i" to shutdown the web2py server' % os.getpid()
320 server=HttpServer(ip=ip,port=port,password=options.password,
321 pid_filename=options.pid_filename,
322 log_filename=options.log_filename,
323 ssl_certificate=options.ssl_certificate,
324 ssl_private_key=options.ssl_private_key,
325 numthreads=options.numthreads,
326 server_name=options.server_name,
327 request_queue_size=options.request_queue_size,
328 timeout=options.timeout,
329 shutdown_timeout=options.shutdown_timeout,
330 path=options.folder)
331 try: server.start()
332 except KeyboardInterrupt: server.stop()
333