Merge lp:~octy92/rapache/tray_icon into lp:rapache

Proposed by Alfred Maghi
Status: Needs review
Proposed branch: lp:~octy92/rapache/tray_icon
Merge into: lp:rapache
Diff against target: 7264 lines (+4013/-1697) (has conflicts)
42 files modified
Glade/connect. (+145/-0)
Glade/connect.glade (+175/-0)
Glade/edit_connection.glade (+162/-0)
Glade/main.glade (+784/-560)
Glade/progress.glade (+94/-0)
RapacheCore/Apache.py (+219/-21)
RapacheCore/ApacheError.py (+42/-0)
RapacheCore/Configuration.py (+6/-2)
RapacheCore/Core.py (+60/-0)
RapacheCore/Module.py (+14/-27)
RapacheCore/Network.py (+13/-0)
RapacheCore/PluginBase.py (+8/-9)
RapacheCore/PluginManager.py (+83/-0)
RapacheCore/Server.py (+42/-0)
RapacheCore/Shell.py (+21/-26)
RapacheCore/ShellSSH.py (+257/-0)
RapacheCore/Threads.py (+10/-0)
RapacheCore/Utils.py (+6/-0)
RapacheCore/VirtualHost.py (+84/-74)
RapacheGtk/CheckListView.py (+11/-4)
RapacheGtk/Connect.py (+83/-0)
RapacheGtk/DesktopEnvironment.py (+2/-2)
RapacheGtk/EditGeneric.py (+10/-10)
RapacheGtk/ModuleGui.py (+7/-8)
RapacheGtk/Progress.py (+74/-0)
RapacheGtk/RapacheGui.py (+397/-208)
RapacheGtk/Threads.py (+11/-0)
RapacheGtk/TrayIcon.py (+84/-0)
RapacheGtk/VhostsTreeView.py (+84/-197)
RapacheGtk/VirtualHostGui.py (+14/-57)
plugins/advanced/plugin.py (+4/-3)
plugins/basic_authentication/htpasswd.py (+10/-9)
plugins/basic_authentication/plugin.py (+8/-8)
plugins/error_document/__init__.py (+1/-0)
plugins/error_document/error_codes.py (+52/-0)
plugins/error_document/error_document.glade (+113/-0)
plugins/error_document/plugin.py (+221/-0)
plugins/ssl/certificate_request.py (+10/-9)
plugins/ssl/plugin.py (+60/-28)
plugins/ssl/ssl.glade (+512/-417)
plugins/ssl/text_display.py (+5/-5)
rapache (+15/-13)
Text conflict in RapacheCore/PluginManager.py
Text conflict in RapacheGtk/VhostsTreeView.py
To merge this branch: bzr merge lp:~octy92/rapache/tray_icon
Reviewer Review Type Date Requested Status
Rapache Developers Pending
Review via email: mp+25408@code.launchpad.net

Description of the change

That branch has a tray icon: a click on the tray icon hides or shows the Rapache window.

Exiting the Rapache window destroy the tray icon has well.

To post a comment you must log in.

Unmerged revisions

140. By octy <octy@octy-debian>

tray icon now really works

139. By octy <octy@octy-debian>

Exit from tray icon works

138. By octy <octy@octy-debian>

Tray icon working

137. By octy <octy@octy-debian>

tray icon. just the icon (and "exit" in the menu)

136. By octy <octy@octy-debian>

Networks.py shortened some lines

135. By octy <octy@octy-debian>

Fixed a bug (debian logs)

134. By octy <octy@octy-debian>

added class to sniff the network

133. By jason <jason@jason-laptop>

thread check for sudo first

132. By jason <jason@jason-laptop>

thread check boxs in lists

131. By jason <jason@jason-laptop>

add chain to ssl

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'Glade/connect.'
2--- Glade/connect. 1970-01-01 00:00:00 +0000
3+++ Glade/connect. 2010-05-16 23:57:26 +0000
4@@ -0,0 +1,145 @@
5+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
6+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
7+<!--Generated with glade3 3.4.5 on Wed Sep 17 16:06:20 2008 -->
8+<glade-interface>
9+ <widget class="GtkDialog" id="dialog1">
10+ <property name="border_width">5</property>
11+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
12+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
13+ <property name="has_separator">False</property>
14+ <child internal-child="vbox">
15+ <widget class="GtkVBox" id="dialog-vbox1">
16+ <property name="visible">True</property>
17+ <property name="spacing">2</property>
18+ <child>
19+ <widget class="GtkTable" id="table1">
20+ <property name="visible">True</property>
21+ <property name="n_rows">4</property>
22+ <property name="n_columns">2</property>
23+ <child>
24+ <widget class="GtkLabel" id="label11">
25+ <property name="visible">True</property>
26+ <property name="label" translatable="yes">Server</property>
27+ </widget>
28+ </child>
29+ <child>
30+ <widget class="GtkEntry" id="entry1">
31+ <property name="visible">True</property>
32+ <property name="can_focus">True</property>
33+ </widget>
34+ <packing>
35+ <property name="left_attach">1</property>
36+ <property name="right_attach">2</property>
37+ </packing>
38+ </child>
39+ <child>
40+ <widget class="GtkLabel" id="label12">
41+ <property name="visible">True</property>
42+ <property name="label" translatable="yes">Username</property>
43+ </widget>
44+ <packing>
45+ <property name="top_attach">2</property>
46+ <property name="bottom_attach">3</property>
47+ </packing>
48+ </child>
49+ <child>
50+ <widget class="GtkLabel" id="label13">
51+ <property name="visible">True</property>
52+ <property name="label" translatable="yes">Port (&lt;i&gt;default 22&lt;/i&gt;)</property>
53+ <property name="use_markup">True</property>
54+ </widget>
55+ <packing>
56+ <property name="top_attach">1</property>
57+ <property name="bottom_attach">2</property>
58+ </packing>
59+ </child>
60+ <child>
61+ <widget class="GtkSpinButton" id="spinbutton1">
62+ <property name="visible">True</property>
63+ <property name="can_focus">True</property>
64+ <property name="adjustment">0 0 100 1 10 10</property>
65+ </widget>
66+ <packing>
67+ <property name="left_attach">1</property>
68+ <property name="right_attach">2</property>
69+ <property name="top_attach">1</property>
70+ <property name="bottom_attach">2</property>
71+ <property name="x_options"></property>
72+ </packing>
73+ </child>
74+ <child>
75+ <widget class="GtkEntry" id="entry2">
76+ <property name="visible">True</property>
77+ <property name="can_focus">True</property>
78+ </widget>
79+ <packing>
80+ <property name="left_attach">1</property>
81+ <property name="right_attach">2</property>
82+ <property name="top_attach">2</property>
83+ <property name="bottom_attach">3</property>
84+ </packing>
85+ </child>
86+ <child>
87+ <widget class="GtkLabel" id="label14">
88+ <property name="visible">True</property>
89+ <property name="label" translatable="yes">Password</property>
90+ </widget>
91+ <packing>
92+ <property name="top_attach">3</property>
93+ <property name="bottom_attach">4</property>
94+ </packing>
95+ </child>
96+ <child>
97+ <widget class="GtkEntry" id="entry3">
98+ <property name="visible">True</property>
99+ <property name="can_focus">True</property>
100+ </widget>
101+ <packing>
102+ <property name="left_attach">1</property>
103+ <property name="right_attach">2</property>
104+ <property name="top_attach">3</property>
105+ <property name="bottom_attach">4</property>
106+ </packing>
107+ </child>
108+ </widget>
109+ <packing>
110+ <property name="position">1</property>
111+ </packing>
112+ </child>
113+ <child internal-child="action_area">
114+ <widget class="GtkHButtonBox" id="dialog-action_area1">
115+ <property name="visible">True</property>
116+ <property name="layout_style">GTK_BUTTONBOX_END</property>
117+ <child>
118+ <widget class="GtkButton" id="button2">
119+ <property name="visible">True</property>
120+ <property name="can_focus">True</property>
121+ <property name="receives_default">True</property>
122+ <property name="label" translatable="yes">gtk-cancel</property>
123+ <property name="use_stock">True</property>
124+ <property name="response_id">0</property>
125+ </widget>
126+ </child>
127+ <child>
128+ <widget class="GtkButton" id="button3">
129+ <property name="visible">True</property>
130+ <property name="can_focus">True</property>
131+ <property name="receives_default">True</property>
132+ <property name="label" translatable="yes">gtk-connect</property>
133+ <property name="use_stock">True</property>
134+ <property name="response_id">0</property>
135+ </widget>
136+ <packing>
137+ <property name="position">1</property>
138+ </packing>
139+ </child>
140+ </widget>
141+ <packing>
142+ <property name="expand">False</property>
143+ <property name="pack_type">GTK_PACK_END</property>
144+ </packing>
145+ </child>
146+ </widget>
147+ </child>
148+ </widget>
149+</glade-interface>
150
151=== added file 'Glade/connect.glade'
152--- Glade/connect.glade 1970-01-01 00:00:00 +0000
153+++ Glade/connect.glade 2010-05-16 23:57:26 +0000
154@@ -0,0 +1,175 @@
155+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
156+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
157+<!--Generated with glade3 3.4.5 on Mon Sep 22 22:04:48 2008 -->
158+<glade-interface>
159+ <widget class="GtkDialog" id="dialog_connect">
160+ <property name="border_width">5</property>
161+ <property name="title" translatable="yes">Connection Details</property>
162+ <property name="modal">True</property>
163+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
164+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
165+ <property name="has_separator">False</property>
166+ <child internal-child="vbox">
167+ <widget class="GtkVBox" id="dialog-vbox1">
168+ <property name="visible">True</property>
169+ <property name="spacing">2</property>
170+ <child>
171+ <placeholder/>
172+ </child>
173+ <child>
174+ <widget class="GtkTable" id="table1">
175+ <property name="visible">True</property>
176+ <property name="n_rows">3</property>
177+ <property name="n_columns">4</property>
178+ <child>
179+ <widget class="GtkLabel" id="label13">
180+ <property name="visible">True</property>
181+ <property name="label" translatable="yes">Port</property>
182+ <property name="use_markup">True</property>
183+ </widget>
184+ <packing>
185+ <property name="left_attach">2</property>
186+ <property name="right_attach">3</property>
187+ <property name="x_options"></property>
188+ <property name="y_options"></property>
189+ <property name="x_padding">8</property>
190+ </packing>
191+ </child>
192+ <child>
193+ <widget class="GtkEntry" id="entry_password">
194+ <property name="visible">True</property>
195+ <property name="can_focus">True</property>
196+ <property name="visibility">False</property>
197+ </widget>
198+ <packing>
199+ <property name="left_attach">1</property>
200+ <property name="right_attach">4</property>
201+ <property name="top_attach">2</property>
202+ <property name="bottom_attach">3</property>
203+ <property name="y_options"></property>
204+ <property name="y_padding">4</property>
205+ </packing>
206+ </child>
207+ <child>
208+ <widget class="GtkLabel" id="label14">
209+ <property name="visible">True</property>
210+ <property name="label" translatable="yes">Password</property>
211+ </widget>
212+ <packing>
213+ <property name="top_attach">2</property>
214+ <property name="bottom_attach">3</property>
215+ <property name="x_options"></property>
216+ <property name="y_options"></property>
217+ </packing>
218+ </child>
219+ <child>
220+ <widget class="GtkEntry" id="entry_username">
221+ <property name="visible">True</property>
222+ <property name="can_focus">True</property>
223+ </widget>
224+ <packing>
225+ <property name="left_attach">1</property>
226+ <property name="right_attach">4</property>
227+ <property name="top_attach">1</property>
228+ <property name="bottom_attach">2</property>
229+ <property name="y_options"></property>
230+ <property name="y_padding">4</property>
231+ </packing>
232+ </child>
233+ <child>
234+ <widget class="GtkSpinButton" id="spinbutton_port">
235+ <property name="visible">True</property>
236+ <property name="can_focus">True</property>
237+ <property name="adjustment">22 0 10000 1 10 10</property>
238+ </widget>
239+ <packing>
240+ <property name="left_attach">3</property>
241+ <property name="right_attach">4</property>
242+ <property name="x_options"></property>
243+ <property name="y_options"></property>
244+ <property name="y_padding">4</property>
245+ </packing>
246+ </child>
247+ <child>
248+ <widget class="GtkLabel" id="label12">
249+ <property name="visible">True</property>
250+ <property name="label" translatable="yes">Username</property>
251+ </widget>
252+ <packing>
253+ <property name="top_attach">1</property>
254+ <property name="bottom_attach">2</property>
255+ <property name="x_options"></property>
256+ <property name="y_options"></property>
257+ <property name="x_padding">8</property>
258+ </packing>
259+ </child>
260+ <child>
261+ <widget class="GtkEntry" id="entry_server">
262+ <property name="visible">True</property>
263+ <property name="can_focus">True</property>
264+ </widget>
265+ <packing>
266+ <property name="left_attach">1</property>
267+ <property name="right_attach">2</property>
268+ <property name="y_options"></property>
269+ <property name="y_padding">4</property>
270+ </packing>
271+ </child>
272+ <child>
273+ <widget class="GtkLabel" id="label11">
274+ <property name="visible">True</property>
275+ <property name="label" translatable="yes">Server</property>
276+ </widget>
277+ <packing>
278+ <property name="x_options"></property>
279+ <property name="y_options"></property>
280+ </packing>
281+ </child>
282+ </widget>
283+ <packing>
284+ <property name="position">2</property>
285+ </packing>
286+ </child>
287+ <child internal-child="action_area">
288+ <widget class="GtkHButtonBox" id="dialog-action_area1">
289+ <property name="visible">True</property>
290+ <property name="layout_style">GTK_BUTTONBOX_END</property>
291+ <child>
292+ <widget class="GtkButton" id="button_cancel">
293+ <property name="visible">True</property>
294+ <property name="can_focus">True</property>
295+ <property name="receives_default">True</property>
296+ <property name="label" translatable="yes">gtk-cancel</property>
297+ <property name="use_stock">True</property>
298+ <property name="response_id">0</property>
299+ <signal name="clicked" handler="on_button_cancel_clicked"/>
300+ </widget>
301+ </child>
302+ <child>
303+ <widget class="GtkButton" id="button_connect">
304+ <property name="visible">True</property>
305+ <property name="can_focus">True</property>
306+ <property name="has_focus">True</property>
307+ <property name="is_focus">True</property>
308+ <property name="can_default">True</property>
309+ <property name="has_default">True</property>
310+ <property name="receives_default">True</property>
311+ <property name="label" translatable="yes">gtk-connect</property>
312+ <property name="use_stock">True</property>
313+ <property name="response_id">0</property>
314+ <signal name="clicked" handler="on_button_connect_clicked"/>
315+ </widget>
316+ <packing>
317+ <property name="position">1</property>
318+ </packing>
319+ </child>
320+ </widget>
321+ <packing>
322+ <property name="expand">False</property>
323+ <property name="pack_type">GTK_PACK_END</property>
324+ </packing>
325+ </child>
326+ </widget>
327+ </child>
328+ </widget>
329+</glade-interface>
330
331=== added file 'Glade/edit_connection.glade'
332--- Glade/edit_connection.glade 1970-01-01 00:00:00 +0000
333+++ Glade/edit_connection.glade 2010-05-16 23:57:26 +0000
334@@ -0,0 +1,162 @@
335+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
336+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
337+<!--Generated with glade3 3.4.5 on Thu Sep 11 16:22:57 2008 -->
338+<glade-interface>
339+ <widget class="GtkDialog" id="dialog1">
340+ <property name="border_width">5</property>
341+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
342+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
343+ <property name="has_separator">False</property>
344+ <child internal-child="vbox">
345+ <widget class="GtkVBox" id="dialog-vbox1">
346+ <property name="visible">True</property>
347+ <property name="spacing">2</property>
348+ <child>
349+ <widget class="GtkTable" id="table1">
350+ <property name="visible">True</property>
351+ <property name="n_rows">5</property>
352+ <property name="n_columns">2</property>
353+ <child>
354+ <widget class="GtkEntry" id="entry3">
355+ <property name="visible">True</property>
356+ <property name="can_focus">True</property>
357+ </widget>
358+ <packing>
359+ <property name="left_attach">1</property>
360+ <property name="right_attach">2</property>
361+ <property name="top_attach">4</property>
362+ <property name="bottom_attach">5</property>
363+ </packing>
364+ </child>
365+ <child>
366+ <widget class="GtkLabel" id="label4">
367+ <property name="visible">True</property>
368+ <property name="label" translatable="yes">Password</property>
369+ </widget>
370+ <packing>
371+ <property name="top_attach">4</property>
372+ <property name="bottom_attach">5</property>
373+ </packing>
374+ </child>
375+ <child>
376+ <widget class="GtkLabel" id="label3">
377+ <property name="visible">True</property>
378+ <property name="label" translatable="yes">Username</property>
379+ </widget>
380+ <packing>
381+ <property name="top_attach">3</property>
382+ <property name="bottom_attach">4</property>
383+ </packing>
384+ </child>
385+ <child>
386+ <widget class="GtkEntry" id="entry2">
387+ <property name="visible">True</property>
388+ <property name="can_focus">True</property>
389+ </widget>
390+ <packing>
391+ <property name="left_attach">1</property>
392+ <property name="right_attach">2</property>
393+ <property name="top_attach">3</property>
394+ <property name="bottom_attach">4</property>
395+ </packing>
396+ </child>
397+ <child>
398+ <placeholder/>
399+ </child>
400+ <child>
401+ <placeholder/>
402+ </child>
403+ <child>
404+ <widget class="GtkAlignment" id="alignment1">
405+ <property name="visible">True</property>
406+ <property name="xalign">0</property>
407+ <child>
408+ <widget class="GtkSpinButton" id="spinbutton1">
409+ <property name="visible">True</property>
410+ <property name="can_focus">True</property>
411+ <property name="adjustment">0 0 10000 1 10 10</property>
412+ </widget>
413+ </child>
414+ </widget>
415+ <packing>
416+ <property name="left_attach">1</property>
417+ <property name="right_attach">2</property>
418+ <property name="top_attach">2</property>
419+ <property name="bottom_attach">3</property>
420+ <property name="x_options"></property>
421+ </packing>
422+ </child>
423+ <child>
424+ <widget class="GtkLabel" id="label2">
425+ <property name="visible">True</property>
426+ <property name="label" translatable="yes">Port</property>
427+ </widget>
428+ <packing>
429+ <property name="top_attach">2</property>
430+ <property name="bottom_attach">3</property>
431+ </packing>
432+ </child>
433+ <child>
434+ <widget class="GtkEntry" id="entry1">
435+ <property name="visible">True</property>
436+ <property name="can_focus">True</property>
437+ </widget>
438+ <packing>
439+ <property name="left_attach">1</property>
440+ <property name="right_attach">2</property>
441+ <property name="top_attach">1</property>
442+ <property name="bottom_attach">2</property>
443+ </packing>
444+ </child>
445+ <child>
446+ <widget class="GtkLabel" id="label1">
447+ <property name="visible">True</property>
448+ <property name="label" translatable="yes">Server</property>
449+ </widget>
450+ <packing>
451+ <property name="top_attach">1</property>
452+ <property name="bottom_attach">2</property>
453+ </packing>
454+ </child>
455+ </widget>
456+ <packing>
457+ <property name="position">1</property>
458+ </packing>
459+ </child>
460+ <child internal-child="action_area">
461+ <widget class="GtkHButtonBox" id="dialog-action_area1">
462+ <property name="visible">True</property>
463+ <property name="layout_style">GTK_BUTTONBOX_END</property>
464+ <child>
465+ <widget class="GtkButton" id="button2">
466+ <property name="visible">True</property>
467+ <property name="can_focus">True</property>
468+ <property name="receives_default">True</property>
469+ <property name="label" translatable="yes">gtk-close</property>
470+ <property name="use_stock">True</property>
471+ <property name="response_id">0</property>
472+ </widget>
473+ </child>
474+ <child>
475+ <widget class="GtkButton" id="button1">
476+ <property name="visible">True</property>
477+ <property name="can_focus">True</property>
478+ <property name="receives_default">True</property>
479+ <property name="label" translatable="yes">gtk-connect</property>
480+ <property name="use_stock">True</property>
481+ <property name="response_id">0</property>
482+ </widget>
483+ <packing>
484+ <property name="position">1</property>
485+ </packing>
486+ </child>
487+ </widget>
488+ <packing>
489+ <property name="expand">False</property>
490+ <property name="pack_type">GTK_PACK_END</property>
491+ </packing>
492+ </child>
493+ </widget>
494+ </child>
495+ </widget>
496+</glade-interface>
497
498=== modified file 'Glade/main.glade'
499--- Glade/main.glade 2008-09-15 04:55:10 +0000
500+++ Glade/main.glade 2010-05-16 23:57:26 +0000
501@@ -1,9 +1,9 @@
502 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
503 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
504-<!--Generated with glade3 3.4.5 on Mon Sep 15 06:53:14 2008 -->
505+<!--Generated with glade3 3.4.5 on Wed Sep 24 13:55:33 2008 -->
506 <glade-interface>
507 <widget class="GtkWindow" id="MainWindow">
508- <property name="width_request">500</property>
509+ <property name="width_request">700</property>
510 <property name="height_request">400</property>
511 <property name="visible">True</property>
512 <property name="title" translatable="yes">Rapache</property>
513@@ -11,6 +11,7 @@
514 <signal name="destroy" handler="on_MainWindow_destroy"/>
515 <child>
516 <widget class="GtkVBox" id="vbox7">
517+ <property name="width_request">700</property>
518 <property name="visible">True</property>
519 <child>
520 <widget class="GtkMenuBar" id="menubar1">
521@@ -25,6 +26,7 @@
522 <property name="visible">True</property>
523 <child>
524 <widget class="GtkImageMenuItem" id="menuitem_connect">
525+ <property name="visible">True</property>
526 <property name="sensitive">False</property>
527 <property name="label" translatable="yes">_Connect</property>
528 <property name="use_underline">True</property>
529@@ -38,6 +40,7 @@
530 </child>
531 <child>
532 <widget class="GtkImageMenuItem" id="menuitem_disconnect">
533+ <property name="visible">True</property>
534 <property name="sensitive">False</property>
535 <property name="label" translatable="yes">_Disconnect</property>
536 <property name="use_underline">True</property>
537@@ -51,6 +54,7 @@
538 </child>
539 <child>
540 <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
541+ <property name="visible">True</property>
542 </widget>
543 </child>
544 <child>
545@@ -93,6 +97,60 @@
546 </widget>
547 </child>
548 <child>
549+ <widget class="GtkMenuItem" id="menuitem_ookmarks">
550+ <property name="visible">True</property>
551+ <property name="label" translatable="yes">_Bookmarks</property>
552+ <property name="use_underline">True</property>
553+ <child>
554+ <widget class="GtkMenu" id="menu2">
555+ <property name="visible">True</property>
556+ <child>
557+ <widget class="GtkImageMenuItem" id="menuitem_add_bookmark">
558+ <property name="visible">True</property>
559+ <property name="sensitive">False</property>
560+ <property name="label" translatable="yes">_Add to bookmarks</property>
561+ <property name="use_underline">True</property>
562+ <child internal-child="image">
563+ <widget class="GtkImage" id="menu-item-image8">
564+ <property name="visible">True</property>
565+ <property name="stock">gtk-save</property>
566+ </widget>
567+ </child>
568+ </widget>
569+ </child>
570+ <child>
571+ <widget class="GtkImageMenuItem" id="menuitem_edit_bookmarks">
572+ <property name="visible">True</property>
573+ <property name="sensitive">False</property>
574+ <property name="label" translatable="yes">_Edit bookmark</property>
575+ <property name="use_underline">True</property>
576+ <child internal-child="image">
577+ <widget class="GtkImage" id="menu-item-image9">
578+ <property name="visible">True</property>
579+ <property name="stock">gtk-edit</property>
580+ </widget>
581+ </child>
582+ </widget>
583+ </child>
584+ <child>
585+ <widget class="GtkImageMenuItem" id="menuitem_delete_bookmark">
586+ <property name="visible">True</property>
587+ <property name="sensitive">False</property>
588+ <property name="label" translatable="yes">_Remove from bookmarks</property>
589+ <property name="use_underline">True</property>
590+ <child internal-child="image">
591+ <widget class="GtkImage" id="menu-item-image10">
592+ <property name="visible">True</property>
593+ <property name="stock">gtk-delete</property>
594+ </widget>
595+ </child>
596+ </widget>
597+ </child>
598+ </widget>
599+ </child>
600+ </widget>
601+ </child>
602+ <child>
603 <widget class="GtkMenuItem" id="toolsmenu">
604 <property name="visible">True</property>
605 <property name="label" translatable="yes">_Tools</property>
606@@ -103,6 +161,7 @@
607 <child>
608 <widget class="GtkImageMenuItem" id="menuitem_start_apache">
609 <property name="visible">True</property>
610+ <property name="sensitive">False</property>
611 <property name="label" translatable="yes">_Start Apache</property>
612 <property name="use_underline">True</property>
613 <signal name="activate" handler="please_restart"/>
614@@ -116,6 +175,7 @@
615 <child>
616 <widget class="GtkImageMenuItem" id="menuitem_restart_apache">
617 <property name="visible">True</property>
618+ <property name="sensitive">False</property>
619 <property name="label" translatable="yes">_Restart Apache</property>
620 <property name="use_underline">True</property>
621 <signal name="activate" handler="please_restart"/>
622@@ -129,6 +189,7 @@
623 <child>
624 <widget class="GtkImageMenuItem" id="menuitem_stop_apache">
625 <property name="visible">True</property>
626+ <property name="sensitive">False</property>
627 <property name="label" translatable="yes">_Stop Apache</property>
628 <property name="use_underline">True</property>
629 <signal name="activate" handler="on_menuitem_stop_apache_activate"/>
630@@ -189,598 +250,749 @@
631 </packing>
632 </child>
633 <child>
634- <widget class="GtkVBox" id="vbox1">
635+ <widget class="GtkHPaned" id="hpaned1">
636 <property name="visible">True</property>
637- <child>
638- <widget class="GtkHBox" id="hbox9">
639- <child>
640- <widget class="GtkLabel" id="label9">
641- <property name="visible">True</property>
642- <property name="label" translatable="yes">Server :</property>
643- </widget>
644- <packing>
645- <property name="expand">False</property>
646- <property name="fill">False</property>
647- <property name="padding">8</property>
648- </packing>
649- </child>
650- <child>
651- <widget class="GtkComboBoxEntry" id="comboboxentry1">
652- <property name="visible">True</property>
653- <property name="items" translatable="yes">localhost</property>
654- <child internal-child="entry">
655- <widget class="GtkEntry" id="comboboxentry-entry1">
656- <property name="visible">True</property>
657- <property name="can_focus">True</property>
658- </widget>
659- </child>
660- </widget>
661- <packing>
662- <property name="position">1</property>
663- </packing>
664- </child>
665- <child>
666- <widget class="GtkButton" id="button1">
667- <property name="visible">True</property>
668- <property name="can_focus">True</property>
669- <property name="receives_default">True</property>
670- <property name="label" translatable="yes">gtk-connect</property>
671- <property name="use_stock">True</property>
672- <property name="response_id">0</property>
673- </widget>
674- <packing>
675- <property name="expand">False</property>
676- <property name="fill">False</property>
677- <property name="padding">8</property>
678- <property name="position">2</property>
679- </packing>
680- </child>
681- </widget>
682- <packing>
683- <property name="expand">False</property>
684- <property name="fill">False</property>
685- <property name="padding">8</property>
686- </packing>
687- </child>
688- <child>
689- <widget class="GtkHBox" id="restart_apache_notice">
690- <child>
691- <widget class="GtkVBox" id="vbox5">
692- <property name="visible">True</property>
693- <child>
694- <widget class="GtkButton" id="restart_apache">
695- <property name="visible">True</property>
696- <property name="can_focus">True</property>
697- <property name="receives_default">True</property>
698- <property name="label" translatable="yes">gtk-refresh</property>
699- <property name="use_stock">True</property>
700- <property name="response_id">0</property>
701- <signal name="clicked" handler="please_restart"/>
702- </widget>
703- <packing>
704- <property name="expand">False</property>
705- <property name="padding">7</property>
706- </packing>
707- </child>
708- </widget>
709- <packing>
710- <property name="expand">False</property>
711- <property name="padding">7</property>
712- </packing>
713- </child>
714- <child>
715- <widget class="GtkLabel" id="label1">
716- <property name="visible">True</property>
717- <property name="label" translatable="yes">Applied changes will not take effect until
718-web server is restarted</property>
719- <property name="justify">GTK_JUSTIFY_CENTER</property>
720- <property name="wrap">True</property>
721- <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
722- <property name="width_chars">0</property>
723- </widget>
724- <packing>
725- <property name="padding">4</property>
726- <property name="position">1</property>
727- </packing>
728- </child>
729- <child>
730- <widget class="GtkVBox" id="vbox6">
731- <property name="visible">True</property>
732- <property name="homogeneous">True</property>
733- <child>
734- <widget class="GtkButton" id="button_hide_warning">
735+ <property name="can_focus">True</property>
736+ <property name="position_set">True</property>
737+ <child>
738+ <widget class="GtkVBox" id="vbox9">
739+ <child>
740+ <widget class="GtkHBox" id="hbox1">
741+ <property name="visible">True</property>
742+ <child>
743+ <widget class="GtkAlignment" id="alignment3">
744+ <property name="visible">True</property>
745+ <property name="xalign">0</property>
746+ <child>
747+ <widget class="GtkLabel" id="label1">
748+ <property name="visible">True</property>
749+ <property name="label" translatable="yes">Bookmarks</property>
750+ </widget>
751+ </child>
752+ </widget>
753+ <packing>
754+ <property name="padding">8</property>
755+ </packing>
756+ </child>
757+ <child>
758+ <widget class="GtkLabel" id="label8">
759+ <property name="visible">True</property>
760+ </widget>
761+ <packing>
762+ <property name="position">1</property>
763+ </packing>
764+ </child>
765+ <child>
766+ <widget class="GtkButton" id="button1">
767 <property name="visible">True</property>
768 <property name="can_focus">True</property>
769 <property name="receives_default">True</property>
770 <property name="relief">GTK_RELIEF_NONE</property>
771- <property name="focus_on_click">False</property>
772 <property name="response_id">0</property>
773- <signal name="clicked" handler="on_button_hide_warning_clicked"/>
774 <child>
775- <widget class="GtkImage" id="image2">
776+ <widget class="GtkImage" id="image6">
777 <property name="visible">True</property>
778 <property name="stock">gtk-close</property>
779+ <property name="icon_size">1</property>
780 </widget>
781 </child>
782 </widget>
783 <packing>
784 <property name="expand">False</property>
785 <property name="fill">False</property>
786+ <property name="position">2</property>
787 </packing>
788 </child>
789 </widget>
790 <packing>
791 <property name="expand">False</property>
792 <property name="fill">False</property>
793- <property name="padding">8</property>
794- <property name="position">2</property>
795+ <property name="padding">4</property>
796+ </packing>
797+ </child>
798+ <child>
799+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
800+ <property name="width_request">150</property>
801+ <property name="visible">True</property>
802+ <property name="can_focus">True</property>
803+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
804+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
805+ <child>
806+ <widget class="GtkTreeView" id="treeview_bookmarks">
807+ <property name="width_request">150</property>
808+ <property name="visible">True</property>
809+ <property name="can_focus">True</property>
810+ <property name="headers_visible">False</property>
811+ </widget>
812+ </child>
813+ </widget>
814+ <packing>
815+ <property name="position">1</property>
816 </packing>
817 </child>
818 </widget>
819 <packing>
820- <property name="expand">False</property>
821- <property name="position">1</property>
822+ <property name="resize">False</property>
823+ <property name="shrink">True</property>
824 </packing>
825 </child>
826 <child>
827- <widget class="GtkNotebook" id="notebook">
828+ <widget class="GtkVBox" id="vbox1">
829 <property name="visible">True</property>
830- <property name="can_focus">True</property>
831 <child>
832- <widget class="GtkVBox" id="vbox2">
833- <property name="visible">True</property>
834+ <widget class="GtkHBox" id="restart_apache_notice">
835 <child>
836- <widget class="GtkToolbar" id="toolbar6">
837+ <widget class="GtkVBox" id="vbox5">
838 <property name="visible">True</property>
839- <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
840 <child>
841- <widget class="GtkToolButton" id="button_resolve_errors">
842+ <widget class="GtkButton" id="restart_apache">
843 <property name="visible">True</property>
844- <property name="sensitive">False</property>
845- <property name="is_important">True</property>
846- <property name="label" translatable="yes">Resolve Errors</property>
847- <property name="stock_id">gtk-apply</property>
848- <signal name="clicked" handler="on_button_resolve_errors_clicked"/>
849+ <property name="can_focus">True</property>
850+ <property name="receives_default">True</property>
851+ <property name="label" translatable="yes">gtk-refresh</property>
852+ <property name="use_stock">True</property>
853+ <property name="response_id">0</property>
854+ <signal name="clicked" handler="please_restart"/>
855 </widget>
856 <packing>
857 <property name="expand">False</property>
858+ <property name="padding">7</property>
859 </packing>
860 </child>
861 </widget>
862 <packing>
863 <property name="expand">False</property>
864- <property name="fill">False</property>
865- </packing>
866- </child>
867- <child>
868- <widget class="GtkScrolledWindow" id="scrolledwindow1">
869- <property name="visible">True</property>
870- <property name="can_focus">True</property>
871- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
872- <child>
873- <widget class="GtkViewport" id="viewport_errors">
874- <property name="visible">True</property>
875- <property name="resize_mode">GTK_RESIZE_QUEUE</property>
876- <property name="shadow_type">GTK_SHADOW_NONE</property>
877- <child>
878- <placeholder/>
879- </child>
880- </widget>
881- </child>
882- </widget>
883- <packing>
884- <property name="position">1</property>
885- </packing>
886- </child>
887- </widget>
888- </child>
889- <child>
890- <widget class="GtkHBox" id="hbox3">
891- <property name="visible">True</property>
892- <child>
893- <widget class="GtkImage" id="image5">
894- <property name="visible">True</property>
895- <property name="stock">gtk-dialog-warning</property>
896- </widget>
897- </child>
898- <child>
899- <widget class="GtkLabel" id="label6">
900- <property name="visible">True</property>
901- <property name="label" translatable="yes">Problems</property>
902- </widget>
903- <packing>
904- <property name="padding">5</property>
905- <property name="position">1</property>
906- </packing>
907- </child>
908- </widget>
909- <packing>
910- <property name="type">tab</property>
911- <property name="tab_fill">False</property>
912- </packing>
913- </child>
914- <child>
915- <widget class="GtkVBox" id="vbox4">
916- <property name="visible">True</property>
917- <child>
918- <widget class="GtkHBox" id="hbox4">
919- <property name="visible">True</property>
920- <child>
921- <widget class="GtkToolbar" id="toolbar1">
922- <property name="visible">True</property>
923- <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
924- <child>
925- <widget class="GtkMenuToolButton" id="new_button">
926- <property name="visible">True</property>
927- <property name="is_important">True</property>
928- <property name="use_underline">True</property>
929- <property name="stock_id">gtk-new</property>
930- <signal name="clicked" handler="new_button_clicked"/>
931- </widget>
932- <packing>
933- <property name="expand">False</property>
934- <property name="homogeneous">False</property>
935- </packing>
936- </child>
937- <child>
938- <widget class="GtkToolButton" id="edit_button">
939- <property name="visible">True</property>
940- <property name="sensitive">False</property>
941- <property name="is_important">True</property>
942- <property name="use_underline">True</property>
943- <property name="stock_id">gtk-edit</property>
944- <signal name="clicked" handler="edit_button_clicked"/>
945- </widget>
946- <packing>
947- <property name="expand">False</property>
948- </packing>
949- </child>
950- <child>
951- <widget class="GtkToolButton" id="delete_button">
952- <property name="visible">True</property>
953- <property name="sensitive">False</property>
954- <property name="is_important">True</property>
955- <property name="stock_id">gtk-delete</property>
956- <signal name="clicked" handler="on_delete"/>
957- </widget>
958- <packing>
959- <property name="expand">False</property>
960- </packing>
961- </child>
962- <child>
963- <widget class="GtkSeparatorToolItem" id="toolbutton1">
964- <property name="visible">True</property>
965- </widget>
966- <packing>
967- <property name="expand">False</property>
968- <property name="homogeneous">False</property>
969- </packing>
970- </child>
971- <child>
972- <widget class="GtkToolButton" id="browse_button">
973- <property name="visible">True</property>
974- <property name="sensitive">False</property>
975- <property name="is_important">True</property>
976- <property name="label" translatable="yes">Browse Files</property>
977- <property name="stock_id">gtk-open</property>
978- <signal name="clicked" handler="browse_button_clicked"/>
979- </widget>
980- <packing>
981- <property name="expand">False</property>
982- </packing>
983- </child>
984- <child>
985- <widget class="GtkToolButton" id="surf_this_button">
986- <property name="visible">True</property>
987- <property name="sensitive">False</property>
988- <property name="is_important">True</property>
989- <property name="label" translatable="yes">Open Site</property>
990- <property name="icon_name">applications-internet</property>
991- <signal name="clicked" handler="surf_this_button_clicked"/>
992- </widget>
993- <packing>
994- <property name="expand">False</property>
995- </packing>
996- </child>
997- </widget>
998- </child>
999- <child>
1000- <placeholder/>
1001- </child>
1002- </widget>
1003- <packing>
1004- <property name="expand">False</property>
1005- </packing>
1006- </child>
1007- <child>
1008- <widget class="GtkScrolledWindow" id="vhosts_scroll_box">
1009- <property name="visible">True</property>
1010- <property name="can_focus">True</property>
1011- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1012- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1013- <child>
1014- <widget class="GtkViewport" id="viewport1">
1015- <property name="visible">True</property>
1016- <property name="resize_mode">GTK_RESIZE_QUEUE</property>
1017- <property name="shadow_type">GTK_SHADOW_NONE</property>
1018- <child>
1019- <widget class="GtkVBox" id="vhost_container">
1020- <property name="visible">True</property>
1021- <child>
1022- <placeholder/>
1023- </child>
1024- <child>
1025- <placeholder/>
1026- </child>
1027- <child>
1028- <placeholder/>
1029- </child>
1030- </widget>
1031- </child>
1032- </widget>
1033- </child>
1034- </widget>
1035- <packing>
1036- <property name="position">1</property>
1037- </packing>
1038- </child>
1039- </widget>
1040- <packing>
1041- <property name="position">1</property>
1042- </packing>
1043- </child>
1044- <child>
1045- <widget class="GtkHBox" id="hbox1">
1046- <property name="visible">True</property>
1047- <child>
1048- <widget class="GtkImage" id="image3">
1049- <property name="visible">True</property>
1050- <property name="icon_name">applications-internet</property>
1051- </widget>
1052+ <property name="padding">7</property>
1053+ </packing>
1054 </child>
1055 <child>
1056 <widget class="GtkLabel" id="label2">
1057 <property name="visible">True</property>
1058- <property name="label" translatable="yes">Web Sites</property>
1059+ <property name="label" translatable="yes">Applied changes will not take effect until
1060+web server is restarted</property>
1061+ <property name="justify">GTK_JUSTIFY_CENTER</property>
1062+ <property name="wrap">True</property>
1063+ <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
1064+ <property name="width_chars">0</property>
1065 </widget>
1066 <packing>
1067- <property name="padding">5</property>
1068+ <property name="padding">4</property>
1069 <property name="position">1</property>
1070 </packing>
1071 </child>
1072+ <child>
1073+ <widget class="GtkVBox" id="vbox6">
1074+ <property name="visible">True</property>
1075+ <property name="homogeneous">True</property>
1076+ <child>
1077+ <widget class="GtkButton" id="button_hide_warning">
1078+ <property name="visible">True</property>
1079+ <property name="can_focus">True</property>
1080+ <property name="receives_default">True</property>
1081+ <property name="relief">GTK_RELIEF_NONE</property>
1082+ <property name="focus_on_click">False</property>
1083+ <property name="response_id">0</property>
1084+ <signal name="clicked" handler="on_button_hide_warning_clicked"/>
1085+ <child>
1086+ <widget class="GtkImage" id="image2">
1087+ <property name="visible">True</property>
1088+ <property name="stock">gtk-close</property>
1089+ </widget>
1090+ </child>
1091+ </widget>
1092+ <packing>
1093+ <property name="expand">False</property>
1094+ <property name="fill">False</property>
1095+ </packing>
1096+ </child>
1097+ </widget>
1098+ <packing>
1099+ <property name="expand">False</property>
1100+ <property name="fill">False</property>
1101+ <property name="padding">8</property>
1102+ <property name="position">2</property>
1103+ </packing>
1104+ </child>
1105 </widget>
1106 <packing>
1107- <property name="type">tab</property>
1108+ <property name="expand">False</property>
1109 <property name="position">1</property>
1110- <property name="tab_fill">False</property>
1111 </packing>
1112 </child>
1113 <child>
1114- <widget class="GtkVBox" id="vbox3">
1115+ <widget class="GtkHBox" id="hbox9">
1116 <property name="visible">True</property>
1117 <child>
1118- <widget class="GtkHBox" id="hbox5">
1119+ <widget class="GtkLabel" id="label9">
1120 <property name="visible">True</property>
1121- <child>
1122- <widget class="GtkToolbar" id="toolbar2">
1123- <property name="visible">True</property>
1124- <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
1125- <child>
1126- <widget class="GtkToolButton" id="edit_module_button">
1127- <property name="visible">True</property>
1128- <property name="sensitive">False</property>
1129- <property name="is_important">True</property>
1130- <property name="use_underline">True</property>
1131- <property name="stock_id">gtk-edit</property>
1132- <signal name="clicked" handler="edit_module_button_clicked"/>
1133- </widget>
1134- <packing>
1135- <property name="expand">False</property>
1136- </packing>
1137- </child>
1138- <child>
1139- <widget class="GtkToolButton" id="open_doc_button">
1140- <property name="visible">True</property>
1141- <property name="sensitive">False</property>
1142- <property name="is_important">True</property>
1143- <property name="label" translatable="yes">Documentation</property>
1144- <property name="stock_id">gtk-help</property>
1145- <signal name="clicked" handler="open_doc_button_clicked"/>
1146- </widget>
1147- <packing>
1148- <property name="expand">False</property>
1149- </packing>
1150- </child>
1151- </widget>
1152- </child>
1153- <child>
1154- <widget class="GtkToolbar" id="toolbar3">
1155- <property name="visible">True</property>
1156- <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
1157- <property name="show_arrow">False</property>
1158- </widget>
1159- <packing>
1160- <property name="expand">False</property>
1161- <property name="pack_type">GTK_PACK_END</property>
1162- <property name="position">1</property>
1163- </packing>
1164- </child>
1165+ <property name="label" translatable="yes">Server :</property>
1166 </widget>
1167 <packing>
1168 <property name="expand">False</property>
1169- </packing>
1170- </child>
1171- <child>
1172- <widget class="GtkScrolledWindow" id="modules_scroll_box">
1173+ <property name="fill">False</property>
1174+ <property name="padding">8</property>
1175+ </packing>
1176+ </child>
1177+ <child>
1178+ <widget class="GtkComboBoxEntry" id="comboboxentry_server">
1179+ <property name="visible">True</property>
1180+ <property name="items" translatable="yes"></property>
1181+ <child internal-child="entry">
1182+ <widget class="GtkEntry" id="comboboxentry-entry1">
1183+ <property name="visible">True</property>
1184+ <property name="can_focus">True</property>
1185+ </widget>
1186+ </child>
1187+ </widget>
1188+ <packing>
1189+ <property name="position">1</property>
1190+ </packing>
1191+ </child>
1192+ <child>
1193+ <widget class="GtkProgressBar" id="progressbar">
1194+ <property name="visible">True</property>
1195+ <property name="sensitive">False</property>
1196+ <property name="show_text">True</property>
1197+ <property name="pulse_step">0.050000000000000003</property>
1198+ <property name="text" translatable="yes"> </property>
1199+ </widget>
1200+ <packing>
1201+ <property name="position">2</property>
1202+ </packing>
1203+ </child>
1204+ <child>
1205+ <widget class="GtkButton" id="button_connection">
1206 <property name="visible">True</property>
1207 <property name="can_focus">True</property>
1208- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1209- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1210- <child>
1211- <widget class="GtkViewport" id="viewport2">
1212- <property name="visible">True</property>
1213- <property name="resize_mode">GTK_RESIZE_QUEUE</property>
1214- <property name="shadow_type">GTK_SHADOW_NONE</property>
1215- <child>
1216- <widget class="GtkVBox" id="modules_container">
1217- <property name="visible">True</property>
1218- <child>
1219- <placeholder/>
1220- </child>
1221- <child>
1222- <placeholder/>
1223- </child>
1224- <child>
1225- <placeholder/>
1226- </child>
1227- </widget>
1228- </child>
1229- </widget>
1230- </child>
1231+ <property name="receives_default">True</property>
1232+ <property name="label" translatable="yes">gtk-connect</property>
1233+ <property name="use_stock">True</property>
1234+ <property name="response_id">0</property>
1235+ <signal name="clicked" handler="on_button_connection_clicked"/>
1236 </widget>
1237 <packing>
1238- <property name="position">1</property>
1239+ <property name="expand">False</property>
1240+ <property name="fill">False</property>
1241+ <property name="padding">8</property>
1242+ <property name="position">3</property>
1243 </packing>
1244 </child>
1245 </widget>
1246 <packing>
1247+ <property name="expand">False</property>
1248+ <property name="fill">False</property>
1249+ <property name="padding">8</property>
1250 <property name="position">1</property>
1251 </packing>
1252 </child>
1253 <child>
1254- <widget class="GtkHBox" id="hbox2">
1255- <property name="visible">True</property>
1256- <child>
1257- <widget class="GtkImage" id="image4">
1258- <property name="visible">True</property>
1259- <property name="pixbuf">modules.png</property>
1260- </widget>
1261- </child>
1262- <child>
1263- <widget class="GtkLabel" id="label3">
1264- <property name="visible">True</property>
1265- <property name="label" translatable="yes">Modules</property>
1266- </widget>
1267- <packing>
1268- <property name="padding">5</property>
1269- <property name="position">1</property>
1270- </packing>
1271- </child>
1272- </widget>
1273- <packing>
1274- <property name="type">tab</property>
1275- <property name="position">2</property>
1276- <property name="tab_fill">False</property>
1277- </packing>
1278- </child>
1279- <child>
1280- <widget class="GtkHBox" id="hbox8">
1281- <property name="visible">True</property>
1282- <child>
1283- <widget class="GtkVBox" id="vbox8">
1284+ <widget class="GtkNotebook" id="notebook">
1285+ <property name="visible">True</property>
1286+ <property name="sensitive">False</property>
1287+ <property name="can_focus">True</property>
1288+ <child>
1289+ <widget class="GtkVBox" id="vbox2">
1290 <property name="visible">True</property>
1291 <child>
1292- <widget class="GtkHBox" id="hbox10">
1293+ <widget class="GtkToolbar" id="toolbar6">
1294 <property name="visible">True</property>
1295- <child>
1296- <widget class="GtkLabel" id="label7">
1297- <property name="visible">True</property>
1298- <property name="label" translatable="yes">Log File</property>
1299- </widget>
1300- <packing>
1301- <property name="expand">False</property>
1302- <property name="fill">False</property>
1303- </packing>
1304- </child>
1305- <child>
1306- <widget class="GtkComboBox" id="combobox_log">
1307- <property name="visible">True</property>
1308- <property name="items" translatable="yes"></property>
1309- </widget>
1310- <packing>
1311- <property name="padding">8</property>
1312- <property name="position">1</property>
1313- </packing>
1314- </child>
1315- <child>
1316- <widget class="GtkButton" id="button_open_log">
1317- <property name="visible">True</property>
1318- <property name="can_focus">True</property>
1319- <property name="receives_default">True</property>
1320- <property name="label" translatable="yes">gtk-open</property>
1321- <property name="use_stock">True</property>
1322- <property name="response_id">0</property>
1323- <signal name="clicked" handler="on_button_open_log_clicked"/>
1324- </widget>
1325- <packing>
1326- <property name="expand">False</property>
1327- <property name="fill">False</property>
1328- <property name="position">2</property>
1329+ <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
1330+ <child>
1331+ <widget class="GtkToolButton" id="button_resolve_errors">
1332+ <property name="visible">True</property>
1333+ <property name="sensitive">False</property>
1334+ <property name="is_important">True</property>
1335+ <property name="label" translatable="yes">Resolve Errors</property>
1336+ <property name="stock_id">gtk-apply</property>
1337+ <signal name="clicked" handler="on_button_resolve_errors_clicked"/>
1338+ </widget>
1339+ <packing>
1340+ <property name="expand">False</property>
1341 </packing>
1342 </child>
1343 </widget>
1344 <packing>
1345 <property name="expand">False</property>
1346 <property name="fill">False</property>
1347- <property name="padding">8</property>
1348 </packing>
1349 </child>
1350 <child>
1351- <widget class="GtkScrolledWindow" id="scroll_window_log">
1352+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
1353 <property name="visible">True</property>
1354 <property name="can_focus">True</property>
1355 <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1356- <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
1357+ <child>
1358+ <widget class="GtkViewport" id="viewport_errors">
1359+ <property name="visible">True</property>
1360+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
1361+ <property name="shadow_type">GTK_SHADOW_NONE</property>
1362+ <child>
1363+ <placeholder/>
1364+ </child>
1365+ </widget>
1366+ </child>
1367+ </widget>
1368+ <packing>
1369+ <property name="position">1</property>
1370+ </packing>
1371+ </child>
1372+ </widget>
1373+ </child>
1374+ <child>
1375+ <widget class="GtkHBox" id="hbox3">
1376+ <property name="visible">True</property>
1377+ <child>
1378+ <widget class="GtkImage" id="image5">
1379+ <property name="visible">True</property>
1380+ <property name="stock">gtk-dialog-warning</property>
1381+ </widget>
1382+ </child>
1383+ <child>
1384+ <widget class="GtkLabel" id="label6">
1385+ <property name="visible">True</property>
1386+ <property name="label" translatable="yes">Problems</property>
1387+ </widget>
1388+ <packing>
1389+ <property name="padding">5</property>
1390+ <property name="position">1</property>
1391+ </packing>
1392+ </child>
1393+ </widget>
1394+ <packing>
1395+ <property name="type">tab</property>
1396+ <property name="tab_fill">False</property>
1397+ </packing>
1398+ </child>
1399+ <child>
1400+ <widget class="GtkVBox" id="vbox4">
1401+ <property name="visible">True</property>
1402+ <child>
1403+ <widget class="GtkHBox" id="hbox4">
1404+ <property name="visible">True</property>
1405+ <child>
1406+ <widget class="GtkToolbar" id="toolbar1">
1407+ <property name="visible">True</property>
1408+ <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
1409+ <child>
1410+ <widget class="GtkMenuToolButton" id="new_button">
1411+ <property name="visible">True</property>
1412+ <property name="is_important">True</property>
1413+ <property name="use_underline">True</property>
1414+ <property name="stock_id">gtk-new</property>
1415+ <signal name="clicked" handler="new_button_clicked"/>
1416+ </widget>
1417+ <packing>
1418+ <property name="expand">False</property>
1419+ <property name="homogeneous">False</property>
1420+ </packing>
1421+ </child>
1422+ <child>
1423+ <widget class="GtkToolButton" id="edit_button">
1424+ <property name="visible">True</property>
1425+ <property name="sensitive">False</property>
1426+ <property name="is_important">True</property>
1427+ <property name="use_underline">True</property>
1428+ <property name="stock_id">gtk-edit</property>
1429+ <signal name="clicked" handler="edit_button_clicked"/>
1430+ </widget>
1431+ <packing>
1432+ <property name="expand">False</property>
1433+ </packing>
1434+ </child>
1435+ <child>
1436+ <widget class="GtkToolButton" id="delete_button">
1437+ <property name="visible">True</property>
1438+ <property name="sensitive">False</property>
1439+ <property name="is_important">True</property>
1440+ <property name="stock_id">gtk-delete</property>
1441+ <signal name="clicked" handler="on_delete"/>
1442+ </widget>
1443+ <packing>
1444+ <property name="expand">False</property>
1445+ </packing>
1446+ </child>
1447+ <child>
1448+ <widget class="GtkSeparatorToolItem" id="toolbutton1">
1449+ <property name="visible">True</property>
1450+ </widget>
1451+ <packing>
1452+ <property name="expand">False</property>
1453+ <property name="homogeneous">False</property>
1454+ </packing>
1455+ </child>
1456+ <child>
1457+ <widget class="GtkToolButton" id="browse_button">
1458+ <property name="visible">True</property>
1459+ <property name="sensitive">False</property>
1460+ <property name="is_important">True</property>
1461+ <property name="label" translatable="yes">Browse Files</property>
1462+ <property name="stock_id">gtk-open</property>
1463+ <signal name="clicked" handler="browse_button_clicked"/>
1464+ </widget>
1465+ <packing>
1466+ <property name="expand">False</property>
1467+ </packing>
1468+ </child>
1469+ <child>
1470+ <widget class="GtkToolButton" id="surf_this_button">
1471+ <property name="visible">True</property>
1472+ <property name="sensitive">False</property>
1473+ <property name="is_important">True</property>
1474+ <property name="label" translatable="yes">Open Site</property>
1475+ <property name="icon_name">applications-internet</property>
1476+ <signal name="clicked" handler="surf_this_button_clicked"/>
1477+ </widget>
1478+ <packing>
1479+ <property name="expand">False</property>
1480+ </packing>
1481+ </child>
1482+ </widget>
1483+ </child>
1484 <child>
1485 <placeholder/>
1486 </child>
1487 </widget>
1488 <packing>
1489- <property name="position">1</property>
1490- </packing>
1491- </child>
1492- <child>
1493- <widget class="GtkHBox" id="hbox11">
1494- <property name="visible">True</property>
1495- <child>
1496- <widget class="GtkAlignment" id="alignment1">
1497- <property name="visible">True</property>
1498- <property name="xalign">0</property>
1499- <child>
1500- <widget class="GtkLabel" id="label_log_path">
1501- <property name="visible">True</property>
1502- <property name="use_markup">True</property>
1503- <property name="selectable">True</property>
1504- </widget>
1505- </child>
1506+ <property name="expand">False</property>
1507+ </packing>
1508+ </child>
1509+ <child>
1510+ <widget class="GtkScrolledWindow" id="vhosts_scroll_box">
1511+ <property name="visible">True</property>
1512+ <property name="can_focus">True</property>
1513+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1514+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1515+ <child>
1516+ <widget class="GtkViewport" id="viewport1">
1517+ <property name="visible">True</property>
1518+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
1519+ <property name="shadow_type">GTK_SHADOW_NONE</property>
1520+ <child>
1521+ <widget class="GtkVBox" id="vhost_container">
1522+ <property name="visible">True</property>
1523+ <child>
1524+ <placeholder/>
1525+ </child>
1526+ <child>
1527+ <placeholder/>
1528+ </child>
1529+ <child>
1530+ <placeholder/>
1531+ </child>
1532+ </widget>
1533+ </child>
1534+ </widget>
1535+ </child>
1536+ </widget>
1537+ <packing>
1538+ <property name="position">1</property>
1539+ </packing>
1540+ </child>
1541+ </widget>
1542+ <packing>
1543+ <property name="position">1</property>
1544+ </packing>
1545+ </child>
1546+ <child>
1547+ <widget class="GtkHBox" id="hbox2">
1548+ <property name="visible">True</property>
1549+ <child>
1550+ <widget class="GtkImage" id="image3">
1551+ <property name="visible">True</property>
1552+ <property name="icon_name">applications-internet</property>
1553+ </widget>
1554+ </child>
1555+ <child>
1556+ <widget class="GtkLabel" id="label3">
1557+ <property name="visible">True</property>
1558+ <property name="label" translatable="yes">Web Sites</property>
1559+ </widget>
1560+ <packing>
1561+ <property name="padding">5</property>
1562+ <property name="position">1</property>
1563+ </packing>
1564+ </child>
1565+ </widget>
1566+ <packing>
1567+ <property name="type">tab</property>
1568+ <property name="position">1</property>
1569+ <property name="tab_fill">False</property>
1570+ </packing>
1571+ </child>
1572+ <child>
1573+ <widget class="GtkVBox" id="vbox3">
1574+ <property name="visible">True</property>
1575+ <child>
1576+ <widget class="GtkHBox" id="hbox5">
1577+ <property name="visible">True</property>
1578+ <child>
1579+ <widget class="GtkToolbar" id="toolbar2">
1580+ <property name="visible">True</property>
1581+ <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
1582+ <child>
1583+ <widget class="GtkToolButton" id="edit_module_button">
1584+ <property name="visible">True</property>
1585+ <property name="sensitive">False</property>
1586+ <property name="is_important">True</property>
1587+ <property name="use_underline">True</property>
1588+ <property name="stock_id">gtk-edit</property>
1589+ <signal name="clicked" handler="edit_module_button_clicked"/>
1590+ </widget>
1591+ <packing>
1592+ <property name="expand">False</property>
1593+ </packing>
1594+ </child>
1595+ <child>
1596+ <widget class="GtkToolButton" id="open_doc_button">
1597+ <property name="visible">True</property>
1598+ <property name="sensitive">False</property>
1599+ <property name="is_important">True</property>
1600+ <property name="label" translatable="yes">Documentation</property>
1601+ <property name="stock_id">gtk-help</property>
1602+ <signal name="clicked" handler="open_doc_button_clicked"/>
1603+ </widget>
1604+ <packing>
1605+ <property name="expand">False</property>
1606+ </packing>
1607+ </child>
1608+ </widget>
1609+ </child>
1610+ <child>
1611+ <widget class="GtkToolbar" id="toolbar3">
1612+ <property name="visible">True</property>
1613+ <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
1614+ <property name="show_arrow">False</property>
1615 </widget>
1616 <packing>
1617 <property name="expand">False</property>
1618- <property name="fill">False</property>
1619- </packing>
1620- </child>
1621- <child>
1622- <widget class="GtkLabel" id="label4">
1623- <property name="visible">True</property>
1624- </widget>
1625- <packing>
1626+ <property name="pack_type">GTK_PACK_END</property>
1627 <property name="position">1</property>
1628 </packing>
1629 </child>
1630- <child>
1631- <widget class="GtkAlignment" id="alignment2">
1632- <property name="visible">True</property>
1633- <property name="xalign">1</property>
1634- <child>
1635- <widget class="GtkLinkButton" id="linkbutton_documentation">
1636+ </widget>
1637+ <packing>
1638+ <property name="expand">False</property>
1639+ </packing>
1640+ </child>
1641+ <child>
1642+ <widget class="GtkScrolledWindow" id="modules_scroll_box">
1643+ <property name="visible">True</property>
1644+ <property name="can_focus">True</property>
1645+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1646+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1647+ <child>
1648+ <widget class="GtkViewport" id="viewport2">
1649+ <property name="visible">True</property>
1650+ <property name="resize_mode">GTK_RESIZE_QUEUE</property>
1651+ <property name="shadow_type">GTK_SHADOW_NONE</property>
1652+ <child>
1653+ <widget class="GtkVBox" id="modules_container">
1654+ <property name="visible">True</property>
1655+ <child>
1656+ <placeholder/>
1657+ </child>
1658+ <child>
1659+ <placeholder/>
1660+ </child>
1661+ <child>
1662+ <placeholder/>
1663+ </child>
1664+ </widget>
1665+ </child>
1666+ </widget>
1667+ </child>
1668+ </widget>
1669+ <packing>
1670+ <property name="position">1</property>
1671+ </packing>
1672+ </child>
1673+ </widget>
1674+ <packing>
1675+ <property name="position">1</property>
1676+ </packing>
1677+ </child>
1678+ <child>
1679+ <widget class="GtkHBox" id="hbox6">
1680+ <property name="visible">True</property>
1681+ <child>
1682+ <widget class="GtkImage" id="image4">
1683+ <property name="visible">True</property>
1684+ <property name="pixbuf">modules.png</property>
1685+ </widget>
1686+ </child>
1687+ <child>
1688+ <widget class="GtkLabel" id="label4">
1689+ <property name="visible">True</property>
1690+ <property name="label" translatable="yes">Modules</property>
1691+ </widget>
1692+ <packing>
1693+ <property name="padding">5</property>
1694+ <property name="position">1</property>
1695+ </packing>
1696+ </child>
1697+ </widget>
1698+ <packing>
1699+ <property name="type">tab</property>
1700+ <property name="position">2</property>
1701+ <property name="tab_fill">False</property>
1702+ </packing>
1703+ </child>
1704+ <child>
1705+ <widget class="GtkHBox" id="hbox8">
1706+ <property name="visible">True</property>
1707+ <child>
1708+ <widget class="GtkVBox" id="vbox8">
1709+ <property name="visible">True</property>
1710+ <child>
1711+ <widget class="GtkTable" id="table1">
1712+ <property name="visible">True</property>
1713+ <property name="n_rows">2</property>
1714+ <property name="n_columns">3</property>
1715+ <child>
1716+ <placeholder/>
1717+ </child>
1718+ <child>
1719+ <widget class="GtkButton" id="button_open_log">
1720+ <property name="visible">True</property>
1721 <property name="can_focus">True</property>
1722 <property name="receives_default">True</property>
1723- <property name="label" translatable="yes">virtualhost documentation</property>
1724- <property name="relief">GTK_RELIEF_NONE</property>
1725- <property name="focus_on_click">False</property>
1726+ <property name="label" translatable="yes">gtk-open</property>
1727+ <property name="use_stock">True</property>
1728 <property name="response_id">0</property>
1729- <property name="uri">http://httpd.apache.org/docs/2.0/mod/core.html#virtualhost</property>
1730- </widget>
1731+ <signal name="clicked" handler="on_button_open_log_clicked"/>
1732+ </widget>
1733+ <packing>
1734+ <property name="left_attach">2</property>
1735+ <property name="right_attach">3</property>
1736+ <property name="top_attach">1</property>
1737+ <property name="bottom_attach">2</property>
1738+ <property name="x_options"></property>
1739+ <property name="y_options"></property>
1740+ <property name="x_padding">8</property>
1741+ <property name="y_padding">4</property>
1742+ </packing>
1743+ </child>
1744+ <child>
1745+ <widget class="GtkSpinButton" id="spinbutton_log_limit">
1746+ <property name="visible">True</property>
1747+ <property name="can_focus">True</property>
1748+ <property name="adjustment">100 10 100000 10 100 10</property>
1749+ </widget>
1750+ <packing>
1751+ <property name="left_attach">1</property>
1752+ <property name="right_attach">2</property>
1753+ <property name="top_attach">1</property>
1754+ <property name="bottom_attach">2</property>
1755+ <property name="y_options"></property>
1756+ <property name="x_padding">8</property>
1757+ </packing>
1758+ </child>
1759+ <child>
1760+ <widget class="GtkLabel" id="label12">
1761+ <property name="visible">True</property>
1762+ <property name="tooltip_text">Limit the log file to last N number of lines</property>
1763+ <property name="label" translatable="yes">Line Limit</property>
1764+ </widget>
1765+ <packing>
1766+ <property name="top_attach">1</property>
1767+ <property name="bottom_attach">2</property>
1768+ <property name="x_options"></property>
1769+ <property name="y_options"></property>
1770+ </packing>
1771+ </child>
1772+ <child>
1773+ <widget class="GtkComboBox" id="combobox_log">
1774+ <property name="visible">True</property>
1775+ <property name="row_span_column">0</property>
1776+ <property name="items" translatable="yes"></property>
1777+ </widget>
1778+ <packing>
1779+ <property name="left_attach">1</property>
1780+ <property name="right_attach">2</property>
1781+ <property name="y_options"></property>
1782+ <property name="x_padding">8</property>
1783+ </packing>
1784+ </child>
1785+ <child>
1786+ <widget class="GtkLabel" id="label7">
1787+ <property name="visible">True</property>
1788+ <property name="label" translatable="yes">Log File</property>
1789+ </widget>
1790+ <packing>
1791+ <property name="x_options"></property>
1792+ </packing>
1793+ </child>
1794+ </widget>
1795+ <packing>
1796+ <property name="expand">False</property>
1797+ <property name="fill">False</property>
1798+ <property name="padding">8</property>
1799+ </packing>
1800+ </child>
1801+ <child>
1802+ <widget class="GtkScrolledWindow" id="scroll_window_log">
1803+ <property name="visible">True</property>
1804+ <property name="can_focus">True</property>
1805+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
1806+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
1807+ <child>
1808+ <placeholder/>
1809+ </child>
1810+ </widget>
1811+ <packing>
1812+ <property name="position">1</property>
1813+ </packing>
1814+ </child>
1815+ <child>
1816+ <widget class="GtkHBox" id="hbox11">
1817+ <property name="visible">True</property>
1818+ <child>
1819+ <widget class="GtkAlignment" id="alignment1">
1820+ <property name="visible">True</property>
1821+ <property name="xalign">0</property>
1822+ <child>
1823+ <widget class="GtkLabel" id="label_log_path">
1824+ <property name="visible">True</property>
1825+ <property name="use_markup">True</property>
1826+ <property name="selectable">True</property>
1827+ </widget>
1828+ </child>
1829+ </widget>
1830+ <packing>
1831+ <property name="expand">False</property>
1832+ <property name="fill">False</property>
1833+ </packing>
1834+ </child>
1835+ <child>
1836+ <widget class="GtkLabel" id="label5">
1837+ <property name="visible">True</property>
1838+ </widget>
1839+ <packing>
1840+ <property name="position">1</property>
1841+ </packing>
1842+ </child>
1843+ <child>
1844+ <widget class="GtkAlignment" id="alignment2">
1845+ <property name="visible">True</property>
1846+ <property name="xalign">1</property>
1847+ <child>
1848+ <widget class="GtkLinkButton" id="linkbutton_documentation">
1849+ <property name="can_focus">True</property>
1850+ <property name="receives_default">True</property>
1851+ <property name="label" translatable="yes">virtualhost documentation</property>
1852+ <property name="relief">GTK_RELIEF_NONE</property>
1853+ <property name="focus_on_click">False</property>
1854+ <property name="response_id">0</property>
1855+ <property name="uri">http://httpd.apache.org/docs/2.0/mod/core.html#virtualhost</property>
1856+ </widget>
1857+ </child>
1858+ </widget>
1859+ <packing>
1860+ <property name="expand">False</property>
1861+ <property name="fill">False</property>
1862+ <property name="padding">8</property>
1863+ <property name="position">2</property>
1864+ </packing>
1865 </child>
1866 </widget>
1867 <packing>
1868@@ -792,86 +1004,98 @@
1869 </child>
1870 </widget>
1871 <packing>
1872- <property name="expand">False</property>
1873- <property name="fill">False</property>
1874 <property name="padding">8</property>
1875- <property name="position">2</property>
1876- </packing>
1877- </child>
1878- </widget>
1879- <packing>
1880- <property name="padding">8</property>
1881- </packing>
1882- </child>
1883- </widget>
1884- <packing>
1885- <property name="position">3</property>
1886- </packing>
1887- </child>
1888- <child>
1889- <widget class="GtkHBox" id="hbox7">
1890- <property name="visible">True</property>
1891- <child>
1892- <widget class="GtkImage" id="image1">
1893- <property name="visible">True</property>
1894- <property name="stock">gtk-justify-fill</property>
1895- </widget>
1896- </child>
1897- <child>
1898- <widget class="GtkLabel" id="label10">
1899- <property name="visible">True</property>
1900- <property name="label" translatable="yes">Log Files</property>
1901- </widget>
1902- <packing>
1903- <property name="padding">5</property>
1904- <property name="position">1</property>
1905- </packing>
1906- </child>
1907- </widget>
1908- <packing>
1909- <property name="type">tab</property>
1910- <property name="position">3</property>
1911- <property name="tab_fill">False</property>
1912- </packing>
1913- </child>
1914+ </packing>
1915+ </child>
1916+ </widget>
1917+ <packing>
1918+ <property name="position">3</property>
1919+ </packing>
1920+ </child>
1921+ <child>
1922+ <widget class="GtkHBox" id="hbox7">
1923+ <property name="visible">True</property>
1924+ <child>
1925+ <widget class="GtkImage" id="image1">
1926+ <property name="visible">True</property>
1927+ <property name="stock">gtk-justify-fill</property>
1928+ </widget>
1929+ </child>
1930+ <child>
1931+ <widget class="GtkLabel" id="label10">
1932+ <property name="visible">True</property>
1933+ <property name="label" translatable="yes">Log Files</property>
1934+ </widget>
1935+ <packing>
1936+ <property name="padding">5</property>
1937+ <property name="position">1</property>
1938+ </packing>
1939+ </child>
1940+ </widget>
1941+ <packing>
1942+ <property name="type">tab</property>
1943+ <property name="position">3</property>
1944+ <property name="tab_fill">False</property>
1945+ </packing>
1946+ </child>
1947+ </widget>
1948+ <packing>
1949+ <property name="position">2</property>
1950+ </packing>
1951+ </child>
1952+ </widget>
1953+ <packing>
1954+ <property name="resize">False</property>
1955+ <property name="shrink">True</property>
1956+ </packing>
1957+ </child>
1958+ </widget>
1959+ <packing>
1960+ <property name="padding">2</property>
1961+ <property name="position">1</property>
1962+ </packing>
1963+ </child>
1964+ <child>
1965+ <widget class="GtkHBox" id="hbox12">
1966+ <property name="visible">True</property>
1967+ <child>
1968+ <widget class="GtkImage" id="image_apache_status">
1969+ <property name="visible">True</property>
1970+ <property name="stock">gtk-media-stop</property>
1971+ <property name="icon_size">1</property>
1972+ </widget>
1973+ <packing>
1974+ <property name="expand">False</property>
1975+ <property name="fill">False</property>
1976+ <property name="padding">2</property>
1977+ </packing>
1978+ </child>
1979+ <child>
1980+ <widget class="GtkLabel" id="label_server_status">
1981+ <property name="visible">True</property>
1982+ </widget>
1983+ <packing>
1984+ <property name="expand">False</property>
1985+ <property name="fill">False</property>
1986+ <property name="position">1</property>
1987+ </packing>
1988+ </child>
1989+ <child>
1990+ <widget class="GtkLabel" id="label11">
1991+ <property name="visible">True</property>
1992 </widget>
1993 <packing>
1994 <property name="position">2</property>
1995 </packing>
1996 </child>
1997 <child>
1998- <widget class="GtkHBox" id="hbox6">
1999- <property name="visible">True</property>
2000- <child>
2001- <widget class="GtkImage" id="image_apache_status">
2002- <property name="visible">True</property>
2003- <property name="stock">gtk-no</property>
2004- <property name="icon_size">1</property>
2005- </widget>
2006- <packing>
2007- <property name="expand">False</property>
2008- <property name="fill">False</property>
2009- <property name="padding">2</property>
2010- </packing>
2011- </child>
2012- <child>
2013- <widget class="GtkStatusbar" id="statusbar_server_status">
2014- <property name="visible">True</property>
2015- <property name="spacing">2</property>
2016- </widget>
2017- <packing>
2018- <property name="position">1</property>
2019- </packing>
2020- </child>
2021- </widget>
2022- <packing>
2023- <property name="expand">False</property>
2024- <property name="position">3</property>
2025- </packing>
2026+ <placeholder/>
2027 </child>
2028 </widget>
2029 <packing>
2030- <property name="position">1</property>
2031+ <property name="expand">False</property>
2032+ <property name="padding">2</property>
2033+ <property name="position">2</property>
2034 </packing>
2035 </child>
2036 </widget>
2037
2038=== added file 'Glade/progress.glade'
2039--- Glade/progress.glade 1970-01-01 00:00:00 +0000
2040+++ Glade/progress.glade 2010-05-16 23:57:26 +0000
2041@@ -0,0 +1,94 @@
2042+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2043+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
2044+<!--Generated with glade3 3.4.5 on Wed Sep 17 10:13:51 2008 -->
2045+<glade-interface>
2046+ <widget class="GtkDialog" id="dialog_progress">
2047+ <property name="border_width">5</property>
2048+ <property name="title" translatable="yes">Communicating with Server</property>
2049+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
2050+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
2051+ <property name="has_separator">False</property>
2052+ <child internal-child="vbox">
2053+ <widget class="GtkVBox" id="dialog-vbox1">
2054+ <property name="visible">True</property>
2055+ <property name="spacing">2</property>
2056+ <child>
2057+ <widget class="GtkVBox" id="vbox2">
2058+ <property name="visible">True</property>
2059+ <child>
2060+ <widget class="GtkLabel" id="label2">
2061+ <property name="visible">True</property>
2062+ <property name="label" translatable="yes">Please standby....</property>
2063+ </widget>
2064+ <packing>
2065+ <property name="expand">False</property>
2066+ <property name="fill">False</property>
2067+ <property name="padding">8</property>
2068+ </packing>
2069+ </child>
2070+ <child>
2071+ <widget class="GtkProgressBar" id="progressbar1">
2072+ <property name="visible">True</property>
2073+ <property name="activity_mode">True</property>
2074+ <property name="show_text">True</property>
2075+ <property name="text" translatable="yes"></property>
2076+ </widget>
2077+ <packing>
2078+ <property name="expand">False</property>
2079+ <property name="fill">False</property>
2080+ <property name="position">1</property>
2081+ </packing>
2082+ </child>
2083+ <child>
2084+ <widget class="GtkExpander" id="expander1">
2085+ <property name="can_focus">True</property>
2086+ <child>
2087+ <placeholder/>
2088+ </child>
2089+ <child>
2090+ <widget class="GtkLabel" id="label1">
2091+ <property name="visible">True</property>
2092+ <property name="label" translatable="yes">expander</property>
2093+ </widget>
2094+ <packing>
2095+ <property name="type">label_item</property>
2096+ </packing>
2097+ </child>
2098+ </widget>
2099+ <packing>
2100+ <property name="expand">False</property>
2101+ <property name="fill">False</property>
2102+ <property name="padding">8</property>
2103+ <property name="position">2</property>
2104+ </packing>
2105+ </child>
2106+ </widget>
2107+ <packing>
2108+ <property name="position">1</property>
2109+ </packing>
2110+ </child>
2111+ <child internal-child="action_area">
2112+ <widget class="GtkHButtonBox" id="dialog-action_area1">
2113+ <property name="visible">True</property>
2114+ <property name="layout_style">GTK_BUTTONBOX_END</property>
2115+ <child>
2116+ <widget class="GtkButton" id="button_cancel">
2117+ <property name="visible">True</property>
2118+ <property name="can_focus">True</property>
2119+ <property name="receives_default">True</property>
2120+ <property name="label" translatable="yes">gtk-cancel</property>
2121+ <property name="use_stock">True</property>
2122+ <property name="response_id">0</property>
2123+ <signal name="clicked" handler="on_button_cancel_clicked"/>
2124+ </widget>
2125+ </child>
2126+ </widget>
2127+ <packing>
2128+ <property name="expand">False</property>
2129+ <property name="pack_type">GTK_PACK_END</property>
2130+ </packing>
2131+ </child>
2132+ </widget>
2133+ </child>
2134+ </widget>
2135+</glade-interface>
2136
2137=== modified file 'RapacheCore/Apache.py'
2138--- RapacheCore/Apache.py 2008-09-15 04:16:47 +0000
2139+++ RapacheCore/Apache.py 2010-05-16 23:57:26 +0000
2140@@ -4,31 +4,225 @@
2141 import urllib2
2142
2143 from RapacheCore import Shell
2144+from RapacheCore import ShellSSH
2145+from RapacheCore import Configuration
2146+from RapacheCore.VirtualHost import *
2147+from RapacheCore.Module import *
2148+from RapacheCore.ApacheError import *
2149
2150 class Apache2():
2151-
2152- def __init__(self):
2153- self.server = "localhost"
2154+ def __init__(self, server):
2155+ self.server = server
2156+
2157+ self.__virtual_hosts = None
2158+ self.__modules = None
2159+ self.__errors = None
2160+ self.__logs = None
2161+
2162+ self.__module_descriptions = get_module_descriptions()
2163+
2164+ def count(self):
2165+ total = 0
2166+ if self.__virtual_hosts: total = total + len(self.__virtual_hosts)
2167+ if self.__modules: total = total + len(self.__modules)
2168+ if self.__errors: total = total + len(self.__errors)
2169+ return total
2170+
2171+ def __get_enabled_virtual_hosts(self):
2172+ print "__get_enabled_virtual_hosts"
2173+ dir_enabled_all = self.server.command.listdir( Configuration.SITES_ENABLED_DIR )
2174+ dir_enabled_all = [x for x in dir_enabled_all if not re.match( "(.*[~]\s*$)|(.*.swp$)", x )]
2175+
2176+ # get list of files in available that are enabled
2177+ dir_enabled = []
2178+ for fname in dir_enabled_all:
2179+ flink = self.server.command.readlink( os.path.join(Configuration.SITES_ENABLED_DIR, fname) )
2180+ if flink:
2181+ flink = os.path.join(os.path.dirname( Configuration.SITES_ENABLED_DIR +"/" ), flink)
2182+ # please note debian features a nice set of
2183+ # mixed absolute and relative links. FREAKS !
2184+ # the added "/" is also necessary
2185+ flink = os.path.normpath(flink)
2186+ dir_enabled.append(flink)
2187+ return dir_enabled
2188+
2189+ def get_virtual_hosts(self, ReloadChange=False, Force=False):
2190+
2191+ # force caching by default
2192+ if self.__virtual_hosts and not Force:
2193+ print "Loading cached hosts"
2194+ if ReloadChange:
2195+ dir_enabled = None
2196+ for key in self.__virtual_hosts:
2197+ host = self.__virtual_hosts[key]
2198+ if host.changed:
2199+ print key
2200+ # Need to reload this module and check enabled status
2201+ if not dir_enabled: dir_enabled = self.__get_enabled_virtual_hosts()
2202+ host.load()
2203+ host.enabled = host.get_source_filename() in dir_enabled
2204+
2205+ return self.__virtual_hosts
2206+
2207+ self.__virtual_hosts = {}
2208+
2209+ dir_available = self.server.command.listdir( Configuration.SITES_AVAILABLE_DIR )
2210+ dir_available = [x for x in dir_available if not re.match( "(.*[~]\s*$)|(.*.swp$)", x )]
2211+
2212+ dir_enabled = self.__get_enabled_virtual_hosts()
2213+
2214+ for fname in dir_available :
2215+ enabled = os.path.join(Configuration.SITES_AVAILABLE_DIR, fname) in dir_enabled
2216+ site = VirtualHostModel( fname, self, enabled )
2217+ if not site.is_new:
2218+ self.__virtual_hosts[ fname ] = site
2219+
2220+ return self.__virtual_hosts
2221+
2222+
2223+
2224+ def __get_enabled_modules(self):
2225+ # get list of files in available that are enabled
2226+ dir_enabled = []
2227+ for fname in self.server.command.listdir( Configuration.MODS_ENABLED_DIR ):
2228+
2229+ if fname.endswith( ".load"):
2230+
2231+ flink = self.server.command.readlink( os.path.join(Configuration.MODS_ENABLED_DIR, fname) )
2232+ flink = os.path.join(os.path.dirname( Configuration.MODS_ENABLED_DIR +"/" ), flink)
2233+ # please note debian brilliantly features a nice set of
2234+ # mixed absolute and relative links. FREAKS !
2235+ # the added "/" is also necessary
2236+ flink = os.path.normpath( flink )
2237+
2238+ dir_enabled.append( flink )
2239+
2240+ return dir_enabled
2241+
2242+ def get_modules(self, ReloadChanges=False, Force=False):
2243+
2244+ # force caching by default
2245+ if self.__modules and not Force:
2246+ if ReloadChanges:
2247+ dir_enabled = None
2248+ # check modules that have been saved and need updating...
2249+ for key in self.__modules:
2250+ mod = self.__modules[key]
2251+ if mod.changed:
2252+ # Need to reload this module and check enabled status
2253+ if not dir_enabled: dir_enabled = self.__get_enabled_modules()
2254+ mod.load()
2255+ mod.data['enabled'] = os.path.join(Configuration.MODS_AVAILABLE_DIR, key + ".load") in dir_enabled
2256+ return self.__modules
2257+
2258+ self.__modules = {}
2259+
2260+ dir_available = self.server.command.listdir( Configuration.MODS_AVAILABLE_DIR )
2261+ dir_available = [x for x in dir_available if not re.match( "(.*[~]\s*$)|(.*.swp$)", x ) ]
2262+
2263+ dir_enabled = self.__get_enabled_modules()
2264+
2265+ for fname in dir_available :
2266+ tokens = os.path.splitext( fname )
2267+ if tokens[1] == '.load':
2268+ description = None
2269+
2270+ # find a description
2271+ if self.__module_descriptions.has_key(tokens[0]):
2272+ description = self.__module_descriptions[tokens[0]]
2273+ elif self.__module_descriptions.has_key("mod_" + tokens[0]):
2274+ description = self.__module_descriptions["mod_" + tokens[0]]
2275+
2276+ enabled = os.path.join(Configuration.MODS_AVAILABLE_DIR, fname) in dir_enabled
2277+ mod = ModuleModel( tokens[0], self, enabled)
2278+ mod.data[ 'description' ] = description
2279+ try:
2280+ mod.load( )
2281+ except "VhostUnparsable":
2282+ pass
2283+
2284+ self.__modules[ tokens[0] ] = mod
2285+ mod = None
2286+ return self.__modules
2287+
2288+ def get_logs(self, Force = False):
2289+
2290+ # force caching by default
2291+ if self.__logs and not Force:
2292+ return self.__logs
2293+
2294+ self.__logs = self.server.command.listdir( Configuration.LOG_PATH )
2295+ self.__logs = [x for x in self.__logs if x.endswith(".log") ]
2296+ return self.__logs
2297+
2298+ def get_errors(self, Force = False):
2299+
2300+ if self.__errors and not Force:
2301+ return self.__errors
2302+
2303+ self.__errors = []
2304+
2305+ # only do this if we have sudo auth
2306+ if not self.server.command.is_auth_needed():
2307+ result, text = self.test_config()
2308+ if not result:
2309+ self.__errors.append( ApacheConfigError( text ) )
2310+
2311+ # Check for ssl module and vhost have specifed ports
2312+ if self.get_modules()["ssl"].data['enabled']:
2313+ for key in self.get_virtual_hosts():
2314+ vhost = self.get_virtual_hosts()[key]
2315+ if vhost.enabled and not vhost.has_port():
2316+ self.__errors.append( ApachePortRequiredVhostError( vhost ) )
2317+
2318+ # Check unnormalised vhosts
2319+ for key in self.get_virtual_hosts():
2320+ vhost = self.get_virtual_hosts()[key]
2321+ if vhost.is_denormalized_vhost():
2322+ self.__errors.append( ApacheDenomalisedVhostError( vhost ) )
2323+
2324+ print "Errors - ", len(self.__errors)
2325+
2326+ return self.__errors
2327+
2328+ def get_fixable_error_count(self):
2329+ count = 0
2330+ for error in self.__errors:
2331+ if error.fixable:
2332+ count = count + 1
2333+ return count
2334+
2335+ def apply_fixable_errors(self):
2336+ for error in self.__errors:
2337+ if error.fixable:
2338+ error.apply_fix( self )
2339+ return True
2340
2341 def get_status(self):
2342 # -1 no ssh connection, 0 not running, 1 service started, 2 can get an http connection
2343 #TODO: ssh
2344- if not self.is_running():
2345- return 0
2346- if not self.is_reachable():
2347- return 1
2348- return 2
2349+ result = self.is_process_running()
2350+ if result == -1:
2351+ return -1 # error communicating with apache process
2352+ if result == 0 :
2353+ return 0 # apache not running
2354+ if not self.is_http_reachable():
2355+ return 1 # cant connect via http
2356+ return 2 # running
2357
2358 # is service running
2359- def is_running(self):
2360+ def is_process_running(self):
2361 # Check if python2 is running
2362- returncode, output, error = Shell.command.execute(["pidof", "apache2"])
2363- return len(output.strip()) > 0
2364+ try:
2365+ returncode, output, error = self.server.command.execute(["pidof", "apache2"])
2366+ return len(output.strip())
2367+ except:
2368+ return -1
2369
2370 # is http reachable
2371- def is_reachable(self):
2372+ def is_http_reachable(self):
2373 try:
2374- p = urllib2.urlopen( "http://" + self.server )
2375+ p = urllib2.urlopen( "http://" + self.server.name )
2376 info = p.geturl()
2377 p.close()
2378 return True
2379@@ -40,26 +234,30 @@
2380 return False
2381
2382 def start(self):
2383- Shell.command.sudo_execute(["apache2ctl", "start"])
2384+ self.server.command.sudo_execute(["apache2ctl", "start"])
2385 return
2386
2387 def stop(self):
2388- #Shell.command.sudo_execute(["apache2ctl", "-k", "graceful"])
2389- Shell.command.sudo_execute(["apache2ctl", "stop"])
2390+ #self.server.command.sudo_execute(["apache2ctl", "-k", "graceful"])
2391+ self.server.command.sudo_execute(["apache2ctl", "stop"])
2392 return
2393
2394- def restart(self):
2395- Shell.command.sudo_execute(["apache2ctl", "graceful"])
2396+ def restart(self, graceful=True):
2397+ if graceful:
2398+ self.server.command.sudo_execute(["apache2ctl", "graceful"])
2399+ else:
2400+ self.stop()
2401+ self.start()
2402 return
2403
2404 def test_config(self):
2405- returncode, output, error = Shell.command.sudo_execute(["apache2ctl", "-S"])
2406+ returncode, output, error = self.server.command.sudo_execute(["apache2ctl", "-S"])
2407 error = error.strip()
2408 return error.endswith("Syntax OK"), error
2409
2410 def enable_site(self, path):
2411- Shell.command.execute(["a2ensite", path])
2412+ self.server.command.execute(["a2ensite", path])
2413
2414 def disable_site(self, path):
2415- Shell.command.execute(["a2dissite", path])
2416+ self.server.command.execute(["a2dissite", path])
2417
2418
2419=== added file 'RapacheCore/ApacheError.py'
2420--- RapacheCore/ApacheError.py 1970-01-01 00:00:00 +0000
2421+++ RapacheCore/ApacheError.py 2010-05-16 23:57:26 +0000
2422@@ -0,0 +1,42 @@
2423+class ApacheError():
2424+ def __init__(self, title, description, object = None, fixable = False):
2425+ self.title = title
2426+ self.description = description
2427+ self.object = object
2428+ self.fixable = fixable
2429+
2430+ def apply_fix(self, apache):
2431+ return
2432+
2433+class ApacheConfigError(ApacheError):
2434+ def __init__(self, description):
2435+ ApacheError.__init__(self, "Apache Config", description)
2436+
2437+class ApachePortRequiredVhostError(ApacheError):
2438+ def __init__(self, vhost):
2439+ ApacheError.__init__(self, "No port specified : " + vhost.get_server_name(), "When using SSL with apache every virtual host must have a port specified", vhost, True)
2440+
2441+ def apply_fix(self, apache):
2442+ # insure port is set on vhost / object, default to 80 if there is none...
2443+ default_port = 80
2444+ vhosts = apache.get_virtual_hosts()
2445+ if vhosts.has_key('default'):
2446+ vhost = vhosts['default']
2447+ if vhost.has_port() and vhost.get_port() != 443:
2448+ default_port = vhost.get_port()
2449+
2450+ vhost = self.object
2451+ if not vhost.has_port():
2452+ vhost.set_port(default_port)
2453+ vhost.save()
2454+ return
2455+
2456+class ApacheDenomalisedVhostError(ApacheError):
2457+ def __init__(self, vhost):
2458+ ApacheError.__init__(self, vhost.get_server_name() + " - needs normalising", "why you need to do this", vhost, True)
2459+
2460+ def apply_fix(self, apache):
2461+ # normalise vhost / object
2462+ self.object.normalize()
2463+ return
2464+
2465
2466=== modified file 'RapacheCore/Configuration.py'
2467--- RapacheCore/Configuration.py 2008-07-30 21:14:51 +0000
2468+++ RapacheCore/Configuration.py 2010-05-16 23:57:26 +0000
2469@@ -21,7 +21,11 @@
2470 SITES_AVAILABLE_DIR = SYSCONFDIR + '/sites-available'
2471 MODS_ENABLED_DIR = SYSCONFDIR + '/mods-enabled'
2472 MODS_AVAILABLE_DIR = SYSCONFDIR + '/mods-available'
2473+
2474+NUMBER_OF_BACKUPS = 10
2475+TEST_CONNECTION_INTERVAL = 3
2476+LOG_PATH = "/var/log/apache2"
2477+CONFIG_PATH = "~/.config/rapache"
2478+
2479 APPPATH = '/usr/bin' #please fill at run-time
2480 GLADEPATH = '/usr/share/rapache/Glade' #please fill at run-time
2481-NUMBER_OF_BACKUPS = 10
2482-TEST_CONNECTION_INTERVAL = 30
2483
2484=== added file 'RapacheCore/Core.py'
2485--- RapacheCore/Core.py 1970-01-01 00:00:00 +0000
2486+++ RapacheCore/Core.py 2010-05-16 23:57:26 +0000
2487@@ -0,0 +1,60 @@
2488+import os
2489+from RapacheCore.Server import Server
2490+from RapacheCore.PluginManager import PluginManager
2491+from RapacheCore import Configuration
2492+
2493+class RapacheCore():
2494+
2495+ def __init__(self):
2496+ self.servers = {}
2497+ self.plugin_manager = PluginManager(self)
2498+
2499+ self.current_server = None
2500+ self.localhost = None
2501+ self.load_all_servers()
2502+
2503+ def set_new_server(self, server, port, username, password):
2504+ ls = Server(self, server, port, username, password)
2505+ self.servers[ls.name] = ls
2506+ self.current_server = ls
2507+
2508+ def save(self):
2509+ content = []
2510+
2511+ path = os.path.join(Configuration.CONFIG_PATH, "servers.txt")
2512+ print "SAVE ", path
2513+ f = open(path, "w")
2514+ for key in self.servers:
2515+ if key != "localhost":
2516+ s = self.servers[key]
2517+ if s.creditials_verified or s.saved:
2518+ f.write(s.name + " " + str(s.ssh_port) + " " + s.username +"\n")
2519+ f.close()
2520+
2521+
2522+ def load_all_servers(self):
2523+
2524+ # TODO: Load saved configs....
2525+ path = os.path.join(Configuration.CONFIG_PATH, "servers.txt")
2526+ if os.path.exists(path):
2527+ f = open(path, "r")
2528+ for line in f.readlines():
2529+ parts = line.strip().split(' ')
2530+ if len(parts) > 0:
2531+ server = parts[0]
2532+ port = 22
2533+ username = None
2534+ if len(parts) > 1: port = int(parts[1])
2535+ if len(parts) > 2: username = parts[2]
2536+ s = Server(self, server, port, username)
2537+ s.saved = True
2538+ self.servers[parts[0]] = s
2539+
2540+ # local apache
2541+ if self.servers.has_key("localhost"):
2542+ del self.servers["localhost"]
2543+ if( os.path.isdir( Configuration.SITES_AVAILABLE_DIR ) and os.path.isdir( Configuration.SITES_ENABLED_DIR )):
2544+ self.current_server = Server(self)
2545+ self.servers["localhost"] = self.current_server
2546+
2547+ return
2548
2549=== modified file 'RapacheCore/Module.py'
2550--- RapacheCore/Module.py 2008-07-29 10:08:23 +0000
2551+++ RapacheCore/Module.py 2010-05-16 23:57:26 +0000
2552@@ -123,7 +123,8 @@
2553 return list
2554 class ModuleModel:
2555
2556- def __init__(self, name = None):
2557+ def __init__(self, name = None, apache = None, enabled = False):
2558+ self.apache = apache
2559 self.defaults = {
2560 'enabled' : False
2561 , 'name' : None
2562@@ -137,8 +138,9 @@
2563
2564 self.data = self.defaults
2565 if ( name != None ):
2566+ path = os.path.join(Configuration.MODS_AVAILABLE_DIR, name + ".load" )
2567 self.data[ 'name' ] = name
2568- self.data[ 'enabled' ] = self.is_enabled()
2569+ self.data[ 'enabled' ] = enabled
2570
2571 def load (self, name = False):
2572 try:
2573@@ -154,6 +156,7 @@
2574 content = self.get_source()
2575 self.__get_dependecies(content)
2576 self.parsable = True
2577+ self.changed = False
2578 except:
2579 #print "Unparsable by me - unsupported"
2580 raise "ModuleUnparsable"
2581@@ -174,26 +177,9 @@
2582 dependancy = match.groups()[0].strip()
2583 if dependancy != "" : dependancies.append( dependancy )
2584 self.data[ 'dependancies' ] = dependancies
2585- def is_enabled ( self ):
2586- orig = self.data[ 'name' ] + ".load"
2587- dirList = Shell.command.listdir( Configuration.MODS_ENABLED_DIR )
2588- for fname in dirList:
2589- try:
2590- flink = Shell.command.readlink( os.path.join(Configuration.MODS_ENABLED_DIR, fname) )
2591- flink = os.path.join(os.path.dirname( Configuration.MODS_ENABLED_DIR +"/" ), flink)
2592- #please note debian brilliantly features a nice set of
2593- # mixed absolute and relative links. FREAKS !
2594- # the added "/" is also necessary
2595- flink = os.path.normpath(flink)
2596- if ( flink == os.path.join(Configuration.MODS_AVAILABLE_DIR, orig )):
2597- return True
2598- except:
2599- pass
2600-
2601- return False
2602
2603 def _write(self, complete_path, content ):
2604- Shell.command.write_file( complete_path, content )
2605+ self.apache.server.command.write_file( complete_path, content )
2606
2607 def toggle(self, status ):
2608 "status = True|False"
2609@@ -206,10 +192,10 @@
2610 #del tokens[ len( tokens ) -1 ]
2611 #name = ".".join(tokens)
2612 name = self.data['name']
2613- Shell.command.sudo_execute( [command_name, name] )
2614- self.data['enabled'] = self.is_enabled()
2615+ self.apache.server.command.sudo_execute( [command_name, name] )
2616+ self.data['enabled'] = status # assume status worked it will be updated after reload
2617 self.changed = True
2618-
2619+ print "TOGGLE"
2620
2621 def get_description(self):
2622 name = self.data['name']
2623@@ -228,16 +214,17 @@
2624 return os.path.join(Configuration.MODS_AVAILABLE_DIR, self.data['name']+".conf")
2625
2626 def get_backup_files(self):
2627- return Shell.command.get_backup_files( os.path.join(Configuration.MODS_AVAILABLE_DIR, self.data['name']+".conf"))
2628+ return self.apache.server.command.get_backup_files( os.path.join(Configuration.MODS_AVAILABLE_DIR, self.data['name']+".conf"))
2629
2630 def get_source ( self ):
2631- return Shell.command.read_file( os.path.join(Configuration.MODS_AVAILABLE_DIR, self.data['name']+".load"))
2632+ return self.apache.server.command.read_file( os.path.join(Configuration.MODS_AVAILABLE_DIR, self.data['name']+".load"))
2633
2634 def get_configuration ( self ):
2635- return Shell.command.read_file( self.get_configuration_file_name() )
2636+ return self.apache.server.command.read_file( self.get_configuration_file_name() )
2637
2638 def get_configuration_version( self, date_stamp):
2639- return Shell.command.read_file_version(self.get_configuration_file_name() , date_stamp)
2640+ return self.apache.server.command.read_file_version(self.get_configuration_file_name() , date_stamp)
2641
2642 def save_configuration (self, content):
2643 self._write(self.get_configuration_file_name(), content)
2644+ self.changed = True
2645
2646=== added file 'RapacheCore/Network.py'
2647--- RapacheCore/Network.py 1970-01-01 00:00:00 +0000
2648+++ RapacheCore/Network.py 2010-05-16 23:57:26 +0000
2649@@ -0,0 +1,13 @@
2650+#!/usr/bin/env python
2651+
2652+from os import popen4
2653+
2654+class Networks:
2655+ def networks_list(self):
2656+ networks = popen4("""nmap --iflist | grep "[(]" | grep "[(]SHORT[)]" -v | grep "[(]lo[)]" -v | grep "Starting Nmap" -iv | awk '{ print $1 " " $3 }'""")[1].read().split('\n')[:-1]
2657+ for a in networks:
2658+ networks[networks.index(a)] = ' '.join(a.split('/')).split()
2659+ return networks
2660+
2661+ def get_computers(self, ip, range = "24"):
2662+ return popen4('nmap '+ip+'/'+range+" -p22 -v | grep discovered -i | awk '{ print $6 }'")[1].read().split('\n')[:-1]
2663
2664=== modified file 'RapacheCore/PluginBase.py'
2665--- RapacheCore/PluginBase.py 2008-09-10 03:25:06 +0000
2666+++ RapacheCore/PluginBase.py 2010-05-16 23:57:26 +0000
2667@@ -32,19 +32,18 @@
2668 # Number set when plugin UI is added to notebook
2669 self._tab_number = -1
2670
2671- def is_module_enabled(self):
2672+ def is_module_enabled(self, modules):
2673 if self.module:
2674- module = ModuleModel(self.module)
2675- module.load()
2676- #print "STATUS : " + self.module + " - " + str( module.is_enabled())
2677- return module.is_enabled()
2678+ if modules.has_key(self.module):
2679+ module = modules[ self.module ]
2680+ #print "STATUS : " + self.module + " - " + str( module.is_enabled())
2681+ return module.data['enabled']
2682+ return False
2683 return True
2684
2685- def is_enabled(self):
2686- enabled = self.is_module_enabled()
2687-
2688+ def is_enabled(self, modules):
2689+ enabled = self.is_module_enabled(modules)
2690 #TODO: Method of activating / deactivating plugins
2691-
2692 return enabled
2693
2694 # Add item to tools menu
2695
2696=== modified file 'RapacheCore/PluginManager.py'
2697--- RapacheCore/PluginManager.py 2008-09-16 13:58:17 +0000
2698+++ RapacheCore/PluginManager.py 2010-05-16 23:57:26 +0000
2699@@ -19,8 +19,11 @@
2700 import imp
2701 import sys
2702 import traceback
2703+import Configuration
2704+
2705 class PluginManager():
2706
2707+<<<<<<< TREE
2708 def __init__(self):
2709
2710 print "-- Loading plugins --"
2711@@ -51,3 +54,83 @@
2712 traceback.print_exc(file=sys.stdout)
2713
2714
2715+=======
2716+ def __init__(self, core):
2717+
2718+ self.__core = core
2719+
2720+ print "-- Loading plugins --"
2721+ self.plugins = []
2722+ self.__add(os.path.join(sys.path[0], "plugins"))
2723+ self.__add(os.path.join(Configuration.CONFIG_PATH, "plugins"))
2724+ print ""
2725+
2726+ def __add(self, pluginpath):
2727+
2728+ print "checking plugin folder : " + pluginpath
2729+
2730+ if not pluginpath in sys.path:
2731+ sys.path.insert(0, pluginpath)
2732+
2733+ if os.path.exists(pluginpath):
2734+ for folder in os.listdir(pluginpath):
2735+ path = os.path.join(pluginpath,folder)
2736+ if os.path.isdir(path):
2737+ try:
2738+ module = __import__(folder + ".plugin")
2739+ obj = module.plugin.register(self.__core, path)
2740+ self.plugins.append(obj)
2741+ print "loaded plugin : " + folder
2742+ except:
2743+ print "error loading plugin " + folder
2744+ traceback.print_exc(file=sys.stdout)
2745+ print len(self.plugins), " Plugins loaded"
2746+
2747+ def init_main_window(self, rapache_window):
2748+ for plugin in self.__core.plugin_manager.plugins:
2749+ try:
2750+ if plugin.is_enabled(self.__core.current_server.apache.get_modules()):
2751+ menu_item = plugin.init_main_window(rapache_window)
2752+ if menu_item != None:
2753+ rapache_window.menu_tools.add(menu_item)
2754+ menu_item.show()
2755+ except Exception:
2756+ traceback.print_exc(file=sys.stdout)
2757+
2758+
2759+ def init_vhost_properties(self, store, label, notebook):
2760+ for plugin in self.__core.plugin_manager.plugins:
2761+ try:
2762+ print plugin
2763+ if plugin.is_enabled(self.__core.current_server.apache.get_modules()):
2764+ print "enabled"
2765+ content, title, pixbuf = plugin.init_vhost_properties()
2766+ tab_count = notebook.get_n_pages() - 1
2767+ plugin._tab_number = notebook.insert_page(content, label(title), tab_count)
2768+ store.append((pixbuf, title, tab_count))
2769+ content.show()
2770+ except Exception:
2771+ traceback.print_exc(file=sys.stdout)
2772+
2773+
2774+ def update_vhost_properties(self, vhost, tab):
2775+ result = True
2776+ error = ""
2777+ for plugin in self.__core.plugin_manager.plugins:
2778+ try:
2779+ if plugin.is_enabled(self.__core.current_server.apache.get_modules()) and plugin._tab_number == tab:
2780+ result, error = plugin.update_vhost_properties(vhost)
2781+ except Exception:
2782+ traceback.print_exc(file=sys.stdout)
2783+ return result, error
2784+
2785+
2786+ def load_vhost_properties(self, vhost, tab):
2787+ for plugin in self.__core.plugin_manager.plugins:
2788+ try:
2789+ if plugin.is_enabled(self.__core.current_server.apache.get_modules()) and plugin._tab_number == tab:
2790+ plugin.load_vhost_properties(vhost)
2791+ except Exception:
2792+ traceback.print_exc(file=sys.stdout)
2793+
2794+>>>>>>> MERGE-SOURCE
2795
2796=== added file 'RapacheCore/Server.py'
2797--- RapacheCore/Server.py 1970-01-01 00:00:00 +0000
2798+++ RapacheCore/Server.py 2010-05-16 23:57:26 +0000
2799@@ -0,0 +1,42 @@
2800+from RapacheCore import Apache
2801+from RapacheCore import Shell
2802+from RapacheCore import ShellSSH
2803+import Configuration
2804+
2805+class Server():
2806+ def __init__(self, core, server_name="", ssh_port="", username="", password=""):
2807+
2808+ self.__core = core
2809+ self.__localhost = False
2810+
2811+ # SSH connection details
2812+ self.name = server_name
2813+ self.ssh_port = ssh_port
2814+ self.username = username
2815+ self.password = password
2816+
2817+ self.creditials_verified = False
2818+ self.saved = False
2819+
2820+ if self.name:
2821+ self.creditials_verified = False
2822+ self.command = ShellSSH.CommandHandler(self, server_name, ssh_port, username, password)
2823+ else:
2824+ self.__localhost = True
2825+ self.creditials_verified = True
2826+ self.name = "localhost"
2827+ self.command = Shell.CommandHandler(self)
2828+
2829+ self.apache = Apache.Apache2(self)
2830+
2831+ def get_display_name(self):
2832+ if not self.__localhost:
2833+ return self.name #self.username +"@" + self.name + ":" + str(self.ssh_port)
2834+ else:
2835+ return "< Local Machine >"
2836+
2837+ def get_nautilus_browse_string(self, path):
2838+ if self.__localhost:
2839+ return path
2840+ else:
2841+ return "ssh://%s@%s:%s%s" % (self.username, self.name, self.ssh_port, path)
2842
2843=== modified file 'RapacheCore/Shell.py'
2844--- RapacheCore/Shell.py 2008-09-08 00:18:34 +0000
2845+++ RapacheCore/Shell.py 2010-05-16 23:57:26 +0000
2846@@ -43,40 +43,32 @@
2847 import glob
2848 import operator
2849 import Configuration
2850-
2851-class CommandLogEntry:
2852-
2853- def __init__(self, command):
2854- self.command = subprocess.list2cmdline(command)
2855- self.returncode = None
2856- self.output = None
2857- self.error = None
2858-
2859+import paramiko
2860
2861 class CommandHandler:
2862
2863- def __init__(self, ssh_server="localhost", ssh_port=None, ssh_username=None, ssh_password=None):
2864+ def __init__(self, server):
2865
2866+ self.__server = server
2867 # Verboseness
2868 # 0 = No output
2869 # 1 = prints the command and its return code
2870 # 2 = Command output
2871 self.auto_backup = False
2872- self.verbose = 0
2873+ self.verbose = 2
2874 self.command_log = []
2875 # let's make the object stateful, no duplicate password
2876 # typing needed for our users
2877 self.__password = None
2878+
2879+ def test(self):
2880+ return True
2881+ def close(self):
2882+ return True
2883
2884- # SSH connection details
2885- self.ssh_server = ssh_server
2886- self.ssh_port = ssh_port
2887- self.ssh_username = ssh_username
2888- self.ssh_password = ssh_password
2889-
2890 def __get_backup_path(self, path):
2891 # ~/.rapache/backup/server/file_path/datestamp.bak
2892- backup_path = os.path.expanduser(os.path.join("~/.rapache/backup", self.ssh_server, path[1:]))
2893+ backup_path = os.path.expanduser(os.path.join(Configuration.CONFIG_PATH, "backup", self.__server.get_display_name(), path[1:]))
2894 if not os.path.exists( os.path.dirname(backup_path) ):
2895 os.makedirs(os.path.dirname(backup_path))
2896 return backup_path
2897@@ -175,7 +167,11 @@
2898 os.remove(local_path)
2899
2900 def listdir(self, path):
2901- return os.listdir(path)
2902+ try:
2903+ return os.listdir(path)
2904+ except OSError:
2905+ dir_list = os.popen4('gksu ls '+path)[1].read().split('\n')[:-1]
2906+ return dir_list
2907
2908 def create_complete_path ( self, complete_path ):
2909 if not self.exists( complete_path ):
2910@@ -203,7 +199,7 @@
2911
2912 def move(self, source, destination):
2913 self.sudo_execute( ["mv", source, destination] )
2914-
2915+
2916 def __get_password(self, description, prompt="Password: "):
2917
2918 ctx = gksu2.Context()
2919@@ -256,7 +252,10 @@
2920 else:
2921 self.__password = None
2922 return True
2923-
2924+
2925+
2926+
2927+
2928 # Description will be discarded
2929 def execute(self, command, description = None ):
2930 returncode = 0
2931@@ -352,10 +351,6 @@
2932 return output.split("\n")
2933 return []
2934
2935-# Look ma'! A singleton !
2936-command = CommandHandler()
2937-#command.verbose = 1
2938-
2939 if __name__ == "__main__":
2940 c = CommandHandler()
2941 c.verbose = 2
2942@@ -364,4 +359,4 @@
2943 print c.sudo_reset()
2944 code, out, err = c.sudo_execute(["head", "/var/log/syslog"], "Pwd FTW !")
2945 code, out, err = c.sudo_execute(["head", "/var/log/syslog"], "Pwd FTW !")
2946-
2947+
2948
2949=== added file 'RapacheCore/ShellSSH.py'
2950--- RapacheCore/ShellSSH.py 1970-01-01 00:00:00 +0000
2951+++ RapacheCore/ShellSSH.py 2010-05-16 23:57:26 +0000
2952@@ -0,0 +1,257 @@
2953+# Rapache - Apache Configuration Tool
2954+# Copyright (C) 2008 Stefano Forenza, Jason Taylor, Emanuele Gentili
2955+#
2956+# This program is free software: you can redistribute it and/or modify
2957+# it under the terms of the GNU General Public License as published by
2958+# the Free Software Foundation, either version 3 of the License, or
2959+# (at your option) any later version.
2960+#
2961+# This program is distributed in the hope that it will be useful,
2962+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2963+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2964+# GNU General Public License for more details.
2965+#
2966+# You should have received a copy of the GNU General Public License
2967+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2968+
2969+import os
2970+
2971+
2972+import sys
2973+import gksu2
2974+import tempfile
2975+import getpass
2976+import subprocess
2977+import sys
2978+from subprocess import *
2979+import traceback
2980+import time
2981+import glob
2982+import operator
2983+import Configuration
2984+import paramiko
2985+import Shell
2986+
2987+# http://www.lag.net/paramiko/docs/
2988+
2989+class CommandHandler(Shell.CommandHandler):
2990+
2991+ def __init__(self, server, ssh_server, ssh_port, ssh_username, ssh_password):
2992+ Shell.CommandHandler.__init__ (self, server)
2993+
2994+ self.server = server
2995+ self.__sftp = None
2996+ self.__transport = None
2997+
2998+
2999+ def __open(self):
3000+ paramiko.util.log_to_file(os.path.join(Configuration.CONFIG_PATH,'paramiko.log'))
3001+
3002+ if not self.__transport or not self.__transport.is_active():
3003+ self.__server.creditials_verified = False
3004+ self.__sftp = None
3005+ print "SSH Opening connection to ", self.server.name, self.server.ssh_port
3006+ self.__transport = paramiko.Transport((self.server.name, self.server.ssh_port))
3007+ if self.__transport:
3008+ try:
3009+ self.__transport.connect(username=self.server.username, password=self.server.password)
3010+ except:
3011+ self.close()
3012+ return
3013+ try:
3014+ self.__sftp = paramiko.SFTPClient.from_transport(self.__transport)
3015+ except:
3016+ self.close()
3017+ return
3018+ self.__server.creditials_verified = True
3019+
3020+ def close(self):
3021+ if self.__transport.is_active():
3022+ print "SSH close connection"
3023+ self.__transport.close()
3024+
3025+ def test(self):
3026+ try:
3027+ self.__open()
3028+ return self.__server.creditials_verified
3029+ except Exception, Text:
3030+ print Text
3031+ return False
3032+
3033+ def exists(self, path):
3034+ print "SSH file exists ", path
3035+ self.__open()
3036+ try:
3037+ r = self.__sftp.stat( path )
3038+ except IOError:
3039+ return False
3040+ return True
3041+
3042+ def move(self, source, destination):
3043+ print "SSH move ", path
3044+ self.__open()
3045+ self.sudo_execute( ["mv", source, destination] )
3046+
3047+ def readlink(self, path):
3048+ print "SSH read link ", path
3049+ self.__open()
3050+ try:
3051+ return self.__sftp.readlink(path)
3052+ except:
3053+ return None
3054+
3055+ def listdir(self, path):
3056+ print "SSH listdir ", path
3057+ self.__open()
3058+ return self.__sftp.listdir(path)
3059+
3060+ def write_file(self, path, content, backup=True):
3061+
3062+ if not backup or self.create_backup(path, content):
3063+
3064+ if self.verbose >= 1:
3065+ print "WRITING : " + path
3066+
3067+ # Update local backup copy
3068+ if backup:
3069+ local_path = self.__get_backup_path(path)
3070+ else:
3071+ f, local_path = tempfile.mkstemp()
3072+
3073+ f = open(local_path, "w")
3074+ f.write(content)
3075+ f.close()
3076+
3077+ temppath = os.path.join("/tmp/rapache_upload_" + os.path.basename(path))
3078+
3079+ print "SSH write file ", path
3080+ print local_path
3081+ print temppath
3082+ self.__open()
3083+ self.__sftp.put(local_path, temppath)
3084+ self.sudo_execute(["mv", temppath, path])
3085+
3086+ # remove the local copy if no backups
3087+ if not backup:
3088+ os.remove(local_path)
3089+
3090+
3091+ def read_file(self, path):
3092+ print "SSH read file " , path
3093+ try:
3094+ self.__open()
3095+ f = self.__sftp.open(path, 'r')
3096+ data = f.read()
3097+ f.close()
3098+ return data
3099+ except:
3100+ return None
3101+
3102+
3103+ def sudo_execute(self, command):
3104+ return self.execute(["sudo", "-S"] + command, subprocess.list2cmdline(["echo", self.server.password]) + " | ")
3105+
3106+ def execute(self, command, precommand=""):
3107+ print "SSH execute ", command
3108+ self.__open()
3109+ chan = self.__transport.open_session()
3110+ chan.exec_command(precommand + subprocess.list2cmdline(command))
3111+ return_code = chan.recv_exit_status()
3112+
3113+ read_size = 100
3114+
3115+ stdout = ""
3116+ chunk = chan.recv(read_size)
3117+ while len(chunk) > 0:
3118+ stdout = stdout + chunk
3119+ chunk = chan.recv(read_size)
3120+
3121+ stderr = ""
3122+ chunk = chan.recv_stderr(read_size)
3123+ while len(chunk) > 0:
3124+ stderr = stderr + chunk
3125+ chunk = chan.recv_stderr(read_size)
3126+
3127+ chan.close()
3128+
3129+ return (return_code, stdout, stderr)
3130+
3131+ def __get_password(self, description, prompt="Password: "):
3132+
3133+ ctx = gksu2.Context()
3134+ ctx.set_message(description)
3135+ ctx.set_command(subprocess.list2cmdline(["ls","/root"]))
3136+ ctx.set_grab(True)
3137+
3138+ return gksu2.ask_password_full(ctx, prompt) # how does su_full invoke keychain options?
3139+
3140+ def __sudo_popen (self, command, password ):
3141+ #don't enable the following line
3142+ #print "using password:", password
3143+
3144+ # prepend sudo to command and allow piping in
3145+ command.insert(0, "sudo")
3146+ command.insert(1, "-S")
3147+ p = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE)
3148+ #we need a try catch to avoid tracebacks to be printed
3149+ #as they would show the password
3150+ try:
3151+ if p.stdin and not p.stdin.closed:
3152+ p.stdin.write( password )
3153+ except IOError:
3154+ pass # catch the IOError as its meaningless
3155+ except:
3156+ #don't enable the following line as you password
3157+ #will be printed out
3158+ #traceback.print_exc() #<-- CAUTION !
3159+
3160+ print "ERROR: in __sudo_popen()"
3161+ pass
3162+ return p
3163+
3164+ def is_auth_needed (self):
3165+ return False
3166+
3167+ def sudo_reset (self):
3168+ self.__password = None
3169+ command = ['sudo', '-K' ]
3170+ p = Popen( command, stdout=PIPE, stderr=PIPE, stdin=PIPE)
3171+ output, error = p.communicate()
3172+ returncode = p.returncode
3173+ self.__output(command, returncode, output, error)
3174+
3175+ def ask_password(self, description='' ):
3176+ return True
3177+
3178+ def sudo_read_file(self, path):
3179+ returncode, output, error = self.sudo_execute( ["cat", path] )
3180+ if returncode == 0:
3181+ return output
3182+ return ""
3183+
3184+ def sudo_exists(self, path):
3185+ returncode, output, error = self.sudo_execute( ["ls", path] )
3186+ return returncode == 0
3187+
3188+ def sudo_listdir(self, path):
3189+ returncode, output, error = self.sudo_execute( ["ls", "-1", path] )
3190+ if returncode == 0:
3191+ return output.split("\n")
3192+ return []
3193+
3194+if __name__ == "__main__":
3195+ c = CommandHandler()
3196+ c.verbose = 2
3197+ #print c.is_auth_needed()
3198+
3199+ print c.sudo_reset()
3200+ code, out, err = c.sudo_execute(["head", "/var/log/syslog"], "Pwd FTW !")
3201+ code, out, err = c.sudo_execute(["head", "/var/log/syslog"], "Pwd FTW !")
3202+
3203+
3204+
3205+
3206+
3207+
3208+
3209+
3210
3211=== added file 'RapacheCore/Threads.py'
3212--- RapacheCore/Threads.py 1970-01-01 00:00:00 +0000
3213+++ RapacheCore/Threads.py 2010-05-16 23:57:26 +0000
3214@@ -0,0 +1,10 @@
3215+import threading
3216+import time
3217+
3218+# Define threaded attribute
3219+def threaded(f):
3220+ def wrapper(*args):
3221+ t = threading.Thread(target=f, args=args)
3222+ t.setDaemon(True) # wont keep app alive
3223+ t.start()
3224+ return wrapper
3225
3226=== added file 'RapacheCore/Utils.py'
3227--- RapacheCore/Utils.py 1970-01-01 00:00:00 +0000
3228+++ RapacheCore/Utils.py 2010-05-16 23:57:26 +0000
3229@@ -0,0 +1,6 @@
3230+
3231+
3232+def match_backup_files ( fname ):
3233+ if re.match( '.*[~]\s*$', fname ) != None : return True
3234+ if re.match( '.*.swp$', fname ) != None : return True
3235+ return False
3236
3237=== modified file 'RapacheCore/VirtualHost.py'
3238--- RapacheCore/VirtualHost.py 2008-09-15 11:25:35 +0000
3239+++ RapacheCore/VirtualHost.py 2010-05-16 23:57:26 +0000
3240@@ -32,8 +32,10 @@
3241 from RapacheCore import Shell
3242
3243 VHOST_TEMPLATE = """#created for you by Rapache
3244-<VirtualHost *:80>
3245-
3246+<VirtualHost *>
3247+ #ServerAdmin webmaster@example.com
3248+ ServerName example
3249+ DocumentRoot /var/www/examplepath
3250 </VirtualHost>"""
3251
3252
3253@@ -44,6 +46,7 @@
3254
3255 def is_denormalized_vhost ( fname ):
3256 try:
3257+ print "is_denormalized_vhost"
3258 flink = Shell.command.readlink( os.path.join(Configuration.SITES_ENABLED_DIR, fname))
3259 flink = os.path.join(os.path.dirname( Configuration.SITES_AVAILABLE_DIR ), flink)
3260 #no exceptions ? Means it's a link
3261@@ -55,33 +58,25 @@
3262 dest = os.path.join(Configuration.SITES_AVAILABLE_DIR, fname)
3263 return Shell.command.exists( dest )
3264
3265-def normalize_vhost( fname ):
3266- print "Normalizing:", fname
3267- orig = os.path.join(Configuration.SITES_ENABLED_DIR, fname)
3268- dest = os.path.join(Configuration.SITES_AVAILABLE_DIR, fname)
3269- if ( Shell.command.exists( dest ) == True ):
3270- print fname, "already exists in available dir. not even trying"
3271- return False
3272- command = ['mv',orig,dest]
3273- code, output, error = Shell.command.sudo_execute( command )
3274- return ( code == 0 )
3275- return Shell.command.exists( dest )
3276
3277
3278 # Replacment that uses new parser.....
3279 class VirtualHostModel():
3280- def __init__(self, name = None, plugin_manager = None):
3281+ def __init__(self, name = None, apache = None, enabled = False):
3282 self.__name = name
3283 self.__parser = Parser()
3284+ self.apache = apache
3285+ self.__is_default = name == "default"
3286 self.__server_alias = []
3287- self.__is_default = name == "default"
3288- self.is_new = name == "" or not Shell.command.exists( self.get_source_filename() )
3289+ self.is_new = name == "" or not self.apache.server.command.exists( self.get_source_filename() )
3290 self.data = None
3291 self.parsable = True
3292- self.enabled = self.is_enabled()
3293+ self.enabled = enabled
3294 self.hack_hosts = False
3295 self.config = None
3296
3297+ self.changed = False
3298+
3299 if self.is_new:
3300 self.__parser = Parser()
3301 self.__parser.set_from_str( VHOST_TEMPLATE )
3302@@ -89,8 +84,8 @@
3303 else:
3304 try:
3305 self.load(None)
3306+ self.__server_alias = self.get_text-server_alias()
3307 self.parsable = True
3308- self.__server_alias = self.get_server_alias()
3309
3310 if self.__name != self.get_server_name():
3311 print "FILE NAME MISMATCH"
3312@@ -102,8 +97,10 @@
3313 def load(self, name = False):
3314 try:
3315 self.__parser = Parser()
3316- self.__parser.load( self.get_source_filename() )
3317+ content = self.apache.server.command.read_file(self.get_source_filename())
3318+ self.__parser.set_from_str( content )
3319 self.config = self.__parser.rsearch("VirtualHost")[0]
3320+ self.changed = False
3321 return True
3322 except:
3323 self.parsable = False
3324@@ -113,6 +110,7 @@
3325 current_parser = self.__parser
3326 try:
3327 self.__parser = Parser()
3328+
3329 self.__parser.set_from_str( content )
3330 self.config = self.__parser.rsearch("VirtualHost")[0]
3331 return True
3332@@ -121,7 +119,7 @@
3333 return False
3334
3335 def save(self, content=None):
3336- if not Shell.command.ask_password(): return
3337+ if not self.apache.server.command.ask_password(): return
3338
3339 # Get parser content
3340 if not content: content = self.__parser.get_as_str()
3341@@ -132,11 +130,11 @@
3342 print "Creating virtualhost: " + ServerName
3343 print "Folder: " + DocumentRoot
3344
3345- if ( Shell.command.exists( DocumentRoot ) == False ):
3346+ if ( self.apache.server.command.exists( DocumentRoot ) == False ):
3347 print "Folder " + DocumentRoot + " does not exist"
3348- Shell.command.create_complete_path( DocumentRoot )
3349+ self.apache.server.command.create_complete_path( DocumentRoot )
3350
3351- if ( Shell.command.exists( DocumentRoot ) == False ):
3352+ if ( self.apache.server.command.exists( DocumentRoot ) == False ):
3353 self.error( "Could not create target folder" ) #TODO fix this
3354 return False
3355
3356@@ -147,22 +145,19 @@
3357 # if new then make sure to update name before saving
3358 if self.is_new: self.__name = ServerName
3359
3360- Shell.command.write_file(self.get_source_filename(), content)
3361-
3362- #not needed anymore (nor invoked)
3363+ self.apache.server.command.write_file(self.get_source_filename(), content)
3364+
3365+ self.changed = True
3366+
3367 if self.hack_hosts:
3368- # remove old one
3369- Shell.command.sudo_execute ( [os.path.join(Configuration.APPPATH, "hosts-manager"), '-r', self.__name ] )
3370-
3371- Shell.command.sudo_execute ( [os.path.join(Configuration.APPPATH, "hosts-manager"), '-a', ServerName ] )
3372+ self.apache.server.command.sudo_execute ( [os.path.join(Configuration.APPPATH, "hosts-manager"), '-r', self.__name ] )
3373+ self.apache.server.command.sudo_execute ( [os.path.join(Configuration.APPPATH, "hosts-manager"), '-a', ServerName ] )
3374
3375 for alias in self.__server_alias:
3376- Shell.command.sudo_execute ( [os.path.join(Configuration.APPPATH, 'hosts-manager'), '-r', alias ])
3377+ self.apache.server.command.sudo_execute ( [os.path.join(Configuration.APPPATH, 'hosts-manager'), '-r', alias ])
3378
3379- for alias in self.get_server_alias():
3380- Shell.command.sudo_execute ( [os.path.join(Configuration.APPPATH, 'hosts-manager'), '-a', alias ])
3381-
3382- self.__server_alias = self.get_server_alias()
3383+ for alias in self.config.ServerAlias:
3384+ self.apache.server.command.sudo_execute ( [os.path.join(Configuration.APPPATH, 'hosts-manager'), '-a', alias ])
3385
3386 if self.is_new:
3387 self.toggle( True ) #activate by default
3388@@ -170,7 +165,7 @@
3389 else:
3390 # If already existed may need to rename the file
3391
3392- old_enabled = self.is_enabled()
3393+ old_enabled = self.enabled
3394
3395 new_name = os.path.join(Configuration.SITES_AVAILABLE_DIR, ServerName)
3396 old_name = os.path.join(Configuration.SITES_AVAILABLE_DIR, self.__name)
3397@@ -178,11 +173,11 @@
3398 print "old name", old_name
3399 print "new name", new_name
3400
3401- if old_name != new_name and Shell.command.exists( new_name ) == False:
3402+ if old_name != new_name and self.apache.server.command.exists( new_name ) == False:
3403 print "Server name changed, updating conf filename"
3404 self.toggle( False )
3405- Shell.command.move( old_name, new_name )
3406- if Shell.command.exists( new_name ) == True:
3407+ self.apache.server.command.move( old_name, new_name )
3408+ if self.apache.server.command.exists( new_name ) == True:
3409 # success ! we need to reload vhost with the new name
3410 self.__name = ServerName
3411 self.load()
3412@@ -198,7 +193,7 @@
3413 return True
3414
3415 def get_source ( self ):
3416- return Shell.command.read_file(self.get_source_filename())
3417+ return self.apache.server.command.read_file(self.get_source_filename())
3418
3419 def get_source_generated( self ):
3420 return self.__parser.get_as_str()
3421@@ -209,40 +204,21 @@
3422 return os.path.join(Configuration.SITES_AVAILABLE_DIR, self.__name)
3423
3424 def get_backup_files(self):
3425- return Shell.command.get_backup_files( os.path.join(Configuration.SITES_AVAILABLE_DIR, self.__name))
3426+ return self.apache.server.command.get_backup_files( os.path.join(Configuration.SITES_AVAILABLE_DIR, self.__name))
3427 def get_source_version ( self, timestamp ):
3428- return Shell.command.read_file_version(self.get_source_filename(), timestamp)
3429+ return self.apache.server.command.read_file_version(self.get_source_filename(), timestamp)
3430
3431 def delete( self ):
3432 "Deletes a VirtualHost configuration file"
3433 if not self.is_new:
3434- if ( self.is_enabled() ):
3435- self.toggle( False )
3436- Shell.command.sudo_execute( [ 'rm', self.get_source_filename() ])
3437+ self.toggle( False )
3438+ self.apache.server.command.sudo_execute( [ 'rm', self.get_source_filename() ])
3439
3440 def is_default( self ):
3441 return self.__is_default
3442
3443 def is_editable( self ):
3444 return (self.parsable and not self.config == None)
3445-
3446- def is_enabled ( self ):
3447- orig = self.get_source_filename()
3448- dirList = Shell.command.listdir( Configuration.SITES_ENABLED_DIR )
3449- for fname in dirList:
3450- try:
3451- flink = Shell.command.readlink( os.path.join(Configuration.SITES_ENABLED_DIR, fname) )
3452- flink = os.path.join(os.path.dirname( Configuration.SITES_ENABLED_DIR +"/" ), flink)
3453- # please note debian features a nice set of
3454- # mixed absolute and relative links. FREAKS !
3455- # the added "/" is also necessary
3456- flink = os.path.normpath(flink)
3457- if ( flink == orig ):
3458- return True
3459- except:
3460- pass
3461-
3462- return False
3463
3464 def toggle( self, status ):
3465 "status = True|False"
3466@@ -252,8 +228,8 @@
3467 command = "a2dissite"
3468
3469 # set new value
3470- Shell.command.sudo_execute( [ command, self.__name ] )
3471- self.enabled = self.is_enabled()
3472+ self.apache.server.command.sudo_execute( [ command, self.__name ] )
3473+ self.enabled = status
3474 self.changed = True
3475
3476
3477@@ -265,7 +241,7 @@
3478 except:
3479 pass
3480 return self.__name
3481-
3482+
3483 def get_document_root(self):
3484 try:
3485 if self.config.DocumentRoot:
3486@@ -285,14 +261,16 @@
3487 def get_icon(self):
3488 # TODO: This MUST return a local path...
3489 # TODO: Try url for a favicon as well
3490- DocumentRoot = self.get_document_root()
3491- if DocumentRoot != None:
3492- favicon = os.path.join(DocumentRoot, "favicon.ico")
3493- if ( os.path.exists( favicon ) ):
3494- return favicon
3495- return os.path.join( Configuration.GLADEPATH, 'browser.png' )
3496-
3497-
3498+ if self.parsable:
3499+ DocumentRoot = self.get_document_root()
3500+ if DocumentRoot != None:
3501+ favicon = os.path.join(DocumentRoot, "favicon.ico")
3502+ if ( os.path.exists( favicon ) ):
3503+ return favicon
3504+ return os.path.join( Configuration.GLADEPATH, 'browser.png' )
3505+ return None
3506+
3507+
3508 def has_port(self):
3509 if self.parsable and self.config:
3510 value = self.config.value
3511@@ -309,6 +287,7 @@
3512 if len(tokens) < 2: return None
3513 if tokens[-1] =="*": return None
3514 return int(tokens[-1])
3515+
3516
3517 def set_port(self, portnumber):
3518 value = self.config.value
3519@@ -330,3 +309,34 @@
3520 tokens[-1] = str( portnumber )
3521 value = ":".join( tokens[:-1] )
3522 self.config.value = value
3523+
3524+ def clone(self):
3525+ return VirtualHostModel(self.__name, self.apache, self.enabled)
3526+
3527+
3528+ def is_denormalized_vhost ( self ):
3529+ if self.is_new: return False
3530+ try:
3531+ flink = self.apache.server.command.readlink( os.path.join(Configuration.SITES_ENABLED_DIR, self.__name))
3532+ return True
3533+ except:
3534+ return False
3535+ return False
3536+
3537+ def normalize():
3538+ print "Normalizing:", self.__name
3539+ orig = os.path.join(Configuration.SITES_ENABLED_DIR, self.__name)
3540+ dest = os.path.join(Configuration.SITES_AVAILABLE_DIR, self.__name)
3541+ if ( self.apache.server.command.exists( dest ) == True ):
3542+ print fname, "already exists in available dir. not even trying"
3543+ return False
3544+ command = ['mv', orig, dest]
3545+ code, output, error = self.apache.server.command.sudo_execute( command )
3546+ return ( code == 0 )
3547+
3548+ #if fixed:
3549+ # Shell.command.sudo_execute ( [Configuration.APPPATH+'/hosts-manager', '-a',name])
3550+ #else :
3551+ # Shell.command.sudo_execute ( [Configuration.APPPATH+'/hosts-manager', '-r',name])
3552+ # set new value
3553+
3554
3555=== modified file 'RapacheGtk/CheckListView.py'
3556--- RapacheGtk/CheckListView.py 2008-08-07 22:16:32 +0000
3557+++ RapacheGtk/CheckListView.py 2010-05-16 23:57:26 +0000
3558@@ -21,8 +21,9 @@
3559 COLUMN_FIXED,
3560 COLUMN_ICON,
3561 COLUMN_SEVERITY,
3562- COLUMN_MARKUP
3563-) = range(4)
3564+ COLUMN_MARKUP,
3565+ COLUMN_OBJECT
3566+) = range(5)
3567
3568 from RapacheCore import Configuration
3569 import RapacheCore.Observer
3570@@ -59,6 +60,9 @@
3571 def load (self):
3572 raise "AbstractMethod", "Please override this"
3573
3574+ def clear(self):
3575+ self._reset_model()
3576+
3577 def _reset_model (self):
3578 lstore = self.get_model()
3579 if ( lstore == None ):
3580@@ -72,7 +76,8 @@
3581 gobject.TYPE_BOOLEAN,
3582 gtk.gdk.Pixbuf,
3583 gobject.TYPE_STRING,
3584- gobject.TYPE_STRING)
3585+ gobject.TYPE_STRING,
3586+ object)
3587 return lstore
3588
3589 def __toggled(self, *args, **kwargs):
3590@@ -123,7 +128,9 @@
3591 rows = selection.get_selected_rows()[1][0]
3592 num_row = rows[0]
3593 model = self.get_model()
3594- name = model[ num_row ][COLUMN_SEVERITY]
3595+ #if model[ num_row ][COLUMN_OBJECT]:
3596+ return model[ num_row ][COLUMN_OBJECT]
3597+ #name = model[ num_row ][COLUMN_SEVERITY]
3598 except IndexError:
3599 return None
3600 return name
3601
3602=== added file 'RapacheGtk/Connect.py'
3603--- RapacheGtk/Connect.py 1970-01-01 00:00:00 +0000
3604+++ RapacheGtk/Connect.py 2010-05-16 23:57:26 +0000
3605@@ -0,0 +1,83 @@
3606+#!/usr/bin/env python
3607+
3608+# Rapache - Apache Configuration Tool
3609+# Copyright (C) 2008 Stefano Forenza, Jason Taylor, Emanuele Gentili
3610+#
3611+# This program is free software: you can redistribute it and/or modify
3612+# it under the terms of the GNU General Public License as published by
3613+# the Free Software Foundation, either version 3 of the License, or
3614+# (at your option) any later version.
3615+#
3616+# This program is distributed in the hope that it will be useful,
3617+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3618+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3619+# GNU General Public License for more details.
3620+#
3621+# You should have received a copy of the GNU General Public License
3622+# along with this program. If not, see <http://www.gnu.org/licenses/>.
3623+
3624+import sys
3625+try:
3626+ import pygtk
3627+ pygtk.require("2.0")
3628+except:
3629+ pass
3630+try:
3631+ import gtk
3632+ import gtk.glade
3633+except:
3634+ sys.exit(1)
3635+
3636+import os
3637+from RapacheCore import Configuration
3638+
3639+class ConnectionDetails:
3640+
3641+ def __init__(self):
3642+
3643+
3644+ gladefile = os.path.join(Configuration.GLADEPATH, "connect.glade")
3645+ wtree = gtk.glade.XML(gladefile)
3646+
3647+ self.window = wtree.get_widget("dialog_connect")
3648+
3649+ self.entry_server = wtree.get_widget("entry_server")
3650+ self.entry_username = wtree.get_widget("entry_username")
3651+ self.entry_password = wtree.get_widget("entry_password")
3652+ self.spinbutton_port = wtree.get_widget("spinbutton_port")
3653+
3654+ signals = {
3655+ "on_button_connect_clicked" : self.on_button_connect_clicked,
3656+ "on_button_cancel_clicked" : self.on_button_cancel_clicked
3657+ }
3658+ wtree.signal_autoconnect(signals)
3659+ # add on destroy to quit loop
3660+ self.window.connect("destroy", self.on_destroy)
3661+
3662+ self.return_value = None
3663+
3664+ def on_button_connect_clicked(self, widget):
3665+
3666+ self.return_value = self.entry_server.get_text(), self.spinbutton_port.get_value_as_int(), self.entry_username.get_text(), self.entry_password.get_text()
3667+ self.window.destroy()
3668+ return
3669+
3670+ def on_button_cancel_clicked(self, widget):
3671+ self.window.destroy()
3672+ return
3673+
3674+ def run(self):
3675+ self.window.show()
3676+ gtk.main()
3677+ return self.return_value
3678+
3679+ def load (self, server, port, username):
3680+ self.entry_server.set_text(server)
3681+ self.entry_username.set_text(username)
3682+ self.spinbutton_port.set_value( port )
3683+
3684+ return
3685+
3686+ def on_destroy(self, widget, data=None):
3687+ gtk.main_quit()
3688+
3689
3690=== modified file 'RapacheGtk/DesktopEnvironment.py'
3691--- RapacheGtk/DesktopEnvironment.py 2008-09-10 02:24:24 +0000
3692+++ RapacheGtk/DesktopEnvironment.py 2010-05-16 23:57:26 +0000
3693@@ -43,8 +43,8 @@
3694 def open_dir( path ):
3695 # just call this locally as it wont apply over ssh
3696 command = ['nautilus', path, '--no-desktop']
3697-
3698- if os.access(path, os.W_OK):
3699+ print path
3700+ if path.startswith("ssh://") or os.access(path, os.W_OK):
3701 subprocess.Popen( command )
3702 else:
3703 subprocess.Popen( ['gksu', subprocess.list2cmdline(command)] )
3704
3705=== modified file 'RapacheGtk/EditGeneric.py'
3706--- RapacheGtk/EditGeneric.py 2008-09-08 03:31:45 +0000
3707+++ RapacheGtk/EditGeneric.py 2010-05-16 23:57:26 +0000
3708@@ -32,12 +32,12 @@
3709 import RapacheGtk.GuiUtils
3710 from RapacheCore.Module import *
3711 from RapacheGtk import GuiUtils
3712-import RapacheCore.Shell
3713
3714 class EditGenericWindow:
3715
3716- def __init__(self):
3717-
3718+ def __init__(self, core):
3719+ self.core = core
3720+
3721 gladefile = os.path.join(Configuration.GLADEPATH, "edit_generic.glade")
3722 wtree = gtk.glade.XML(gladefile)
3723
3724@@ -64,7 +64,7 @@
3725
3726 def on_button_restore_version_clicked(self, widget):
3727 buf = self.text_view_source.get_buffer()
3728- buf.set_text( Shell.command.read_file( self.file_path ) )
3729+ buf.set_text( self.core.current_server.command.read_file( self.file_path ) )
3730
3731 if self.text_view_source.get_buffer().get_modified():
3732 md = gtk.MessageDialog(self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Are you sure, you will lose all your current changes")
3733@@ -76,10 +76,10 @@
3734 selected = self.combobox_backups.get_active()
3735
3736 if selected == 0:
3737- buf.set_text( Shell.command.read_file( self.file_path ) )
3738+ buf.set_text( self.core.current_server.command.read_file( self.file_path ) )
3739 else:
3740 value = self.combobox_backups.get_active_text()[7:]
3741- buf.set_text( Shell.command.read_file_version( self.file_path, value ) )
3742+ buf.set_text( self.core.current_server.command.read_file_version( self.file_path, value ) )
3743
3744 buf.set_modified(False)
3745
3746@@ -92,8 +92,8 @@
3747 buff = self.text_view_source.get_buffer()
3748 text = buff.get_text(buff.get_start_iter(), buff.get_end_iter())
3749
3750- Shell.command.write_file(self.file_path, text)
3751-
3752+ self.core.current_server.command.write_file(self.file_path, text)
3753+ self.return_value = True
3754 self.window.destroy()
3755 return
3756
3757@@ -108,13 +108,13 @@
3758 self.window.set_title("Edit " + path)
3759 self.label_path.set_text( path )
3760
3761- for file in Shell.command.get_backup_files( path ):
3762+ for file in self.core.current_server.command.get_backup_files( path ):
3763 self.combobox_backups.append_text("Backup " + file[0][-21:-4])
3764 self.combobox_backups.set_active(0)
3765
3766
3767 buf = self.text_view_source.get_buffer()
3768- buf.set_text( Shell.command.read_file( path ) )
3769+ buf.set_text( self.core.current_server.command.read_file( path ) )
3770 buf.set_modified(False)
3771
3772 return
3773
3774=== modified file 'RapacheGtk/ModuleGui.py'
3775--- RapacheGtk/ModuleGui.py 2008-09-05 02:43:18 +0000
3776+++ RapacheGtk/ModuleGui.py 2010-05-16 23:57:26 +0000
3777@@ -50,7 +50,6 @@
3778 from RapacheCore.Module import *
3779 from RapacheGtk import GuiUtils
3780 import RapacheGtk.DesktopEnvironment as Desktop
3781-import RapacheCore.Shell
3782
3783 def open_module_doc( name ):
3784 if ( name == None ): return False
3785@@ -128,23 +127,23 @@
3786 buf.set_modified(False)
3787
3788
3789- def load (self, name ):
3790+ def load (self, module ):
3791 # self.window.set_title(name)
3792- self.module = ModuleModel ( name )
3793+ self.module = module
3794 #self.module.load()
3795 self.__set_module_conf( self.module.get_configuration() )
3796
3797- self.label_module.set_markup("<b><big>Apache2 Module : " + name + "</big></b>")
3798+ self.label_module.set_markup("<b><big>Apache2 Module : " + module.data['name'] + "</big></b>")
3799 self.label_module_description.set_markup("<i>" + self.module.get_description() + "</i>")
3800 self.label_path.set_text( "File : " + self.module.get_configuration_file_name() )
3801 for file in self.module.get_backup_files():
3802 self.combobox_module_backups.append_text("Backup " + file[0][-21:-4])
3803
3804 # Load UI Plugins
3805- for plugin in self.parent.plugin_manager.plugins:
3806- if plugin.module == name:
3807+ for plugin in self.parent.core.plugin_manager.plugins:
3808+ if plugin.module == module.data['name']:
3809 try:
3810- print "Loading plugin " + name
3811+ print "Loading plugin " + module.data['name']
3812 plugin.load_module_properties(self.notebook, self.module)
3813 except Exception:
3814 traceback.print_exc(file=sys.stdout)
3815@@ -159,7 +158,7 @@
3816 buff = self.text_view_module_conf.get_buffer()
3817 text = buff.get_text(buff.get_start_iter(), buff.get_end_iter())
3818
3819- mod = ModuleModel( name )
3820+ mod = self.module
3821 mod.save_configuration( text )
3822
3823 #self.parent.refresh_vhosts()
3824
3825=== added file 'RapacheGtk/Progress.py'
3826--- RapacheGtk/Progress.py 1970-01-01 00:00:00 +0000
3827+++ RapacheGtk/Progress.py 2010-05-16 23:57:26 +0000
3828@@ -0,0 +1,74 @@
3829+#!/usr/bin/env python
3830+
3831+# Rapache - Apache Configuration Tool
3832+# Copyright (C) 2008 Stefano Forenza, Jason Taylor, Emanuele Gentili
3833+#
3834+# This program is free software: you can redistribute it and/or modify
3835+# it under the terms of the GNU General Public License as published by
3836+# the Free Software Foundation, either version 3 of the License, or
3837+# (at your option) any later version.
3838+#
3839+# This program is distributed in the hope that it will be useful,
3840+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3841+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3842+# GNU General Public License for more details.
3843+#
3844+# You should have received a copy of the GNU General Public License
3845+# along with this program. If not, see <http://www.gnu.org/licenses/>.
3846+
3847+import sys
3848+try:
3849+ import pygtk
3850+ pygtk.require("2.0")
3851+except:
3852+ pass
3853+try:
3854+ import gtk
3855+ import gtk.glade
3856+except:
3857+ sys.exit(1)
3858+
3859+import os
3860+
3861+class Progress:
3862+
3863+ def __init__(self, path):
3864+
3865+ # The path to the plugin
3866+ self.glade_path = path
3867+
3868+ gladefile = os.path.join(path, "progress.glade")
3869+ wtree = gtk.glade.XML(gladefile)
3870+
3871+ self.window = wtree.get_widget("dialog_progress")
3872+
3873+ self.entry_username = wtree.get_widget("entry_username")
3874+ self.entry_password = wtree.get_widget("entry_password")
3875+ self.entry_password2 = wtree.get_widget("entry_password2")
3876+
3877+ signals = {
3878+ "on_button_apply_clicked" : self.on_button_apply_clicked,
3879+ "on_button_close_clicked" : self.on_button_close_clicked
3880+ }
3881+ wtree.signal_autoconnect(signals)
3882+ # add on destroy to quit loop
3883+ self.window.connect("destroy", self.on_destroy)
3884+
3885+ self.return_value = None
3886+
3887+ def on_button_close_clicked(self, widget):
3888+ self.window.destroy()
3889+ return
3890+
3891+ def run(self):
3892+ self.window.show()
3893+
3894+ gtk.main()
3895+ return self.return_value
3896+
3897+ def load (self):
3898+ return
3899+
3900+ def on_destroy(self, widget, data=None):
3901+ gtk.main_quit()
3902+
3903
3904=== modified file 'RapacheGtk/RapacheGui.py'
3905--- RapacheGtk/RapacheGui.py 2008-09-15 06:53:55 +0000
3906+++ RapacheGtk/RapacheGui.py 2010-05-16 23:57:26 +0000
3907@@ -32,11 +32,11 @@
3908 import gtk
3909 import os
3910 import re
3911+import time
3912 import threading
3913-import time
3914 import copy
3915
3916-
3917+from RapacheGtk.Threads import threaded
3918 from RapacheGtk.VirtualHostGui import VirtualHostWindow
3919 from RapacheGtk.ModuleGui import ModuleWindow
3920 from RapacheCore.PluginManager import PluginManager
3921@@ -52,36 +52,30 @@
3922 from RapacheGtk.EventDispatcher import Master
3923 import subprocess
3924 import RapacheGtk.DesktopEnvironment as Desktop
3925+from RapacheGtk.Connect import ConnectionDetails
3926 import traceback
3927+from TrayIcon import *
3928 data = \
3929 [(False, "Loading", "please wait" )]
3930
3931 APPNAME="Rapache"
3932-APPVERSION="0.7"
3933+APPVERSION="0.6"
3934
3935 # Turn on gtk threading
3936 gtk.gdk.threads_init()
3937
3938-# Define threaded attribute
3939-def threaded(f):
3940- def wrapper(*args):
3941- t = threading.Thread(target=f, args=args)
3942- t.setDaemon(True) # wont keep app alive
3943- t.start()
3944- return wrapper
3945-
3946 class MainWindow( RapacheCore.Observer.Observable ) :
3947 """This is an Hello World Rapacheefication application"""
3948
3949- def __init__(self, *args, **kwargs):
3950- super (MainWindow, self).__init__ (*args, **kwargs)
3951+ def __init__(self, core):
3952+ super (MainWindow, self).__init__ ()
3953 Master.register(self)
3954
3955- self.denormalized_virtual_hosts = {}
3956- self.plugin_manager = PluginManager()
3957- self.apache = Apache2()
3958+ self.core = core
3959+ self.status = 0 #0 - connected, 1 attempting
3960+ self.__pulse_text = " "
3961+ self.__pulse_flag = False
3962
3963- #gnome.init(APPNAME, APPVERSION)
3964 self.gladefile = Configuration.GLADEPATH + "/" + "main.glade"
3965 self.xml = gtk.glade.XML(self.gladefile)
3966 #Create our dictionary and connect it
3967@@ -100,89 +94,244 @@
3968 "on_button_hide_warning_clicked" : self.on_button_hide_warning_clicked,
3969 "quit" : self.quit,
3970 "on_menuitem_stop_apache_activate" : self.on_menuitem_stop_apache_activate,
3971- "on_button_open_log_clicked" : self.on_button_open_log_clicked
3972+ "on_button_open_log_clicked" : self.on_button_open_log_clicked,
3973+ "on_button_connection_clicked" : self.on_button_connection_clicked
3974 }
3975
3976 gtk.window_set_default_icon_from_file(os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle_golden.svg'))
3977
3978 self.xml.signal_autoconnect(dic)
3979 GuiUtils.change_button_label ( self.xml.get_widget( 'restart_apache' ), "Restart Apache" )
3980- #GuiUtils.change_button_label ( self.xml.get_widget( 'fix_vhosts' ), "Fix Virtual Hosts" )
3981- self.statusbar_server_status = self.xml.get_widget( 'statusbar_server_status' )
3982+
3983+ self.label_server_status = self.xml.get_widget( 'label_server_status' )
3984 self.image_apache_status = self.xml.get_widget( 'image_apache_status' )
3985 self.main_window = self.xml.get_widget("MainWindow")
3986 self.menuitem_stop_apache = self.xml.get_widget("menuitem_stop_apache")
3987 self.menuitem_start_apache = self.xml.get_widget("menuitem_start_apache")
3988 self.menuitem_restart_apache = self.xml.get_widget("menuitem_restart_apache")
3989- #hereby we create lists
3990- self.create_vhost_list()
3991- self.create_modules_list()
3992- self.create_errors_list()
3993- #hereby we fill them
3994- self.refresh_lists(False)
3995-
3996+ self.menu_tools = self.xml.get_widget( 'menu_tools' )
3997+ self.treeview_bookmarks = self.xml.get_widget( 'treeview_bookmarks' )
3998+ self.combobox_log = self.xml.get_widget( 'combobox_log' )
3999+ self.notebook = self.xml.get_widget( 'notebook' )
4000+ self.progressbar = self.xml.get_widget( 'progressbar')
4001+ self.button_connection = self.xml.get_widget( 'button_connection')
4002+ self.comboboxentry_server = self.xml.get_widget( 'comboboxentry_server' )
4003+ self.comboboxentry_entry1 = self.xml.get_widget( 'comboboxentry-entry1' )
4004+ self.button_resolve_errors = self.xml.get_widget( 'button_resolve_errors' )
4005+ self.spinbutton_log_limit = self.xml.get_widget( 'spinbutton_log_limit' )
4006+ # set up display tabs
4007+ self.init_vhost_list()
4008+ self.init_modules_list()
4009+ self.init_errors_list()
4010+ self.init_log_list()
4011+ self.status_icon = StatusIcon( self )
4012+
4013 GuiUtils.style_as_tooltip( self.xml.get_widget( 'restart_apache_notice' ) )
4014- #GuiUtils.style_as_tooltip( self.xml.get_widget( 'unnormalized_notice' ) )
4015- #GuiUtils.style_as_tooltip( self.xml.get_widget( 'hbox_apache_config_error' ) )
4016-
4017- # start status update
4018- self.statusbar_server_status_context_id = self.statusbar_server_status.get_context_id("Apache Server Status")
4019- self.statusbar_server_status.push(self.statusbar_server_status_context_id, "Attempting to connect to server")
4020+
4021+ self.window_status_icons = [
4022+ # 0 - apache stopped
4023+ os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle.svg' )
4024+ # 1 - apache unreachable
4025+ , os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle_orange.svg' )
4026+ # 2 - apache started
4027+ , os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle_green.svg' )
4028+ ]
4029+
4030+ #Setup Bookmark Tree
4031+ #column = gtk.TreeViewColumn(('Icon'))
4032+ #column.set_spacing(4)
4033+ #cell = gtk.CellRendererPixbuf()
4034+ #column.pack_start(cell, expand=False)
4035+ #column.set_attributes(cell, pixbuf=0)
4036+ #self.treeview_bookmarks.append_column(column)
4037+
4038+ #column = gtk.TreeViewColumn(('Title'))
4039+ #column.set_spacing(4)
4040+ #cell = gtk.CellRendererText()
4041+ #column.pack_start(cell, True)
4042+ #column.set_attributes(cell, markup=1)
4043+ #self.treeview_bookmarks.append_column(column)
4044+
4045+ #store = gtk.ListStore(gtk.gdk.Pixbuf, str, int)
4046+ #self.treeview_bookmarks.set_model(store)
4047+
4048+ self.clear_server_information()
4049+
4050+ # if there is a localhost it will be set to current server
4051+ # so load it now
4052+ if self.core.current_server:
4053+ self.connect()
4054+
4055+ def start_pulse(self, text= ' '):
4056+ self.__pulse_text = text
4057+ self.__pulse_count = self.core.current_server.apache.count()
4058+ if not self.__pulse_flag:
4059+ self.__pulse_flag = True
4060+ self.__pulse()
4061+
4062+ def end_pulse(self):
4063+ self.__pulse_flag = False
4064+
4065+ @threaded
4066+ def __pulse(self):
4067+ while self.__pulse_flag == True:
4068+ gobject.idle_add(self.progressbar.pulse)
4069+ count = self.core.current_server.apache.count() - self.__pulse_count
4070+ text = self.__pulse_text
4071+ if count > 0: text += " (" + str(count) + " objects)"
4072+ gobject.idle_add(self.progressbar.set_text, text)
4073+ time.sleep(0.1)
4074+ gobject.idle_add(self.progressbar.set_fraction,0)
4075+ gobject.idle_add(self.progressbar.set_text,' ')
4076+
4077+ def clear_server_information(self):
4078+ self.vhosts_treeview.clear()
4079+ self.modules_treeview.clear()
4080+ self.treeview_errors.clear()
4081+ self.combobox_log.get_model().clear()
4082+ self.notebook.get_nth_page(0).hide()
4083+ self.menuitem_stop_apache.set_sensitive(False)
4084+ self.menuitem_start_apache.set_sensitive(False)
4085+ self.menuitem_restart_apache.set_sensitive(False)
4086+ self.text_view_log.get_buffer().set_text( "" )
4087+ self.text_view_log.set_editable(False)
4088+
4089+ self.comboboxentry_server.get_model().clear()
4090+ for server in self.core.servers:
4091+ self.comboboxentry_server.append_text(server)
4092+
4093+ def load_server_information(self, Force=False):
4094+ self.__load_server_information_pre(Force)
4095+
4096+ def __load_server_information_pre(self, Force=False):
4097+
4098+ self.clear_server_information()
4099+ self.notebook.set_sensitive(False)
4100+ self.status = 1
4101+ self.__load_server_information_thread(Force)
4102+ self.is_connecting( True, 'checking credentials...' )
4103+
4104+ @threaded
4105+ def __load_server_information_thread(self, Force=False):
4106+ print "START load_server_information"
4107+ # Do IO here, we need to do all IO in one big go so that we dont
4108+ # freeze the UI
4109+
4110+ result = self.core.current_server.command.test()
4111+
4112+ if not result:
4113+ gobject.idle_add(self.__load_server_information_fail)
4114+ return
4115+
4116+ gobject.idle_add(self.start_pulse,'loading web sites...')
4117+ self.core.current_server.apache.get_virtual_hosts( True, Force )
4118+
4119+ gobject.idle_add(self.start_pulse,'loading modules...')
4120+ self.core.current_server.apache.get_modules( True, Force )
4121+
4122+ gobject.idle_add(self.start_pulse,'loading log files...')
4123+ self.core.current_server.apache.get_logs( Force )
4124+
4125+ gobject.idle_add(self.start_pulse,'checking for errors...')
4126+ self.core.current_server.apache.get_errors( True )
4127+
4128+ gobject.idle_add(self.__load_server_information_post)
4129+
4130+ def __load_server_information_post(self):
4131+ # post load gtk actions
4132+
4133+ for file in self.core.current_server.apache.get_logs():
4134+ if file.endswith(".log"):
4135+ self.combobox_log.append_text(file)
4136+ self.combobox_log.set_active(0)
4137+
4138+ self.vhosts_treeview.load(self.core.current_server.apache.get_virtual_hosts())
4139+ self.modules_treeview.load(self.core.current_server.apache.get_modules())
4140+ errors = self.core.current_server.apache.get_errors()
4141+ self.treeview_errors.load(errors)
4142+ if len(errors) > 0:
4143+ self.notebook.get_nth_page(0).show()
4144+ self.notebook.set_current_page(0)
4145+ else:
4146+ self.notebook.get_nth_page(0).hide()
4147+
4148+ self.button_resolve_errors.set_sensitive(self.core.current_server.apache.get_fixable_error_count() > 0)
4149+ self.status = 0
4150 self.update_server_status(True)
4151-
4152-
4153+ self.is_connecting( False )
4154+ self.core.save()
4155+
4156+ print "END load_server_information"
4157+
4158+ def __load_server_information_fail(self):
4159+
4160+ self.is_connecting( False )
4161+ self.notebook.set_sensitive(True)
4162+ self.clear_server_information()
4163+ self.end_pulse()
4164+ self.status = -1
4165+
4166+ #self.core.save()
4167+
4168+ print "FAIL load_server_information"
4169+
4170+
4171+ def on_button_connection_clicked(self, widget):
4172+
4173+ server = self.xml.get_widget( 'comboboxentry-entry1').get_text()
4174+ port = 22
4175+ username = ""
4176+ creditials_verified = False
4177+
4178+ if server in self.core.servers:
4179+ s = self.core.servers[server]
4180+ port = s.ssh_port
4181+ username = s.username
4182+ creditials_verified = s.creditials_verified
4183+
4184+ if not creditials_verified:
4185+ cd = ConnectionDetails()
4186+ cd.load(server, port, username)
4187+ server, port, username, password = cd.run()
4188+
4189+ if server in self.core.servers:
4190+ s = self.core.servers[server]
4191+ s.ssh_port = port
4192+ s.username = username
4193+ if password: s.password = password
4194+ self.core.current_server = s
4195+ else:
4196+ self.core.set_new_server(server, port, username, password)
4197+ else:
4198+ self.core.current_server = self.core.servers[server]
4199+
4200+ self.connect()
4201+
4202+ def connect(self):
4203+ self.comboboxentry_entry1.set_text( self.core.current_server.name )
4204+ self.load_server_information(True)
4205
4206-
4207- self.menu_tools = self.xml.get_widget( 'menu_tools' )
4208- for plugin in self.plugin_manager.plugins:
4209- try:
4210- if plugin.is_enabled():
4211- menu_item = plugin.init_main_window(self)
4212- if menu_item != None:
4213- self.menu_tools.add(menu_item)
4214- menu_item.show()
4215- except Exception:
4216- traceback.print_exc(file=sys.stdout)
4217-
4218-
4219-
4220- # Add rich edit to log
4221- self.text_view_log = GuiUtils.new_apache_sourceview()
4222- self.xml.get_widget( 'scroll_window_log' ).add( self.text_view_log )
4223- self.text_view_log.show()
4224- combobox_log = self.xml.get_widget( 'combobox_log' )
4225- files = Shell.command.listdir("/var/log/apache2")
4226- for file in files:
4227- if file.endswith(".log"):
4228- combobox_log.append_text(file)
4229- combobox_log.set_active(0)
4230-
4231 def on_button_open_log_clicked(self, widget):
4232- file = self.xml.get_widget( 'combobox_log' ).get_active_text()
4233- path = os.path.join("/var/log/apache2", file)
4234- text = Shell.command.read_file( path )
4235+ self.__load_log_file_pre()
4236+
4237+ def __load_log_file_pre(self):
4238+ file = self.combobox_log.get_active_text()
4239+ path = os.path.join( Configuration.LOG_PATH, file )
4240+ line_count = self.spinbutton_log_limit.get_value_as_int()
4241+ self.is_connecting( True, 'Loading log file ('+ path +')...' )
4242+ self.__load_log_file_thread(line_count, path)
4243+
4244+ @threaded
4245+ def __load_log_file_thread(self, line_count, path):
4246+ result, text, error = self.core.current_server.command.execute( ["tail", "-n", str(line_count), path] )
4247+ gobject.idle_add(self.__load_log_file_post,text, path)
4248+
4249+ def __load_log_file_post(self, text, path):
4250+ self.is_connecting( False )
4251 self.text_view_log.get_buffer().set_text( text )
4252 self.text_view_log.set_editable(False)
4253 self.xml.get_widget( 'label_log_path').set_text( path )
4254
4255- def refresh_config_test(self, focus=False):
4256- total = self.treeview_errors.load(self.apache, focus)
4257- notebook = self.xml.get_widget( 'notebook' )
4258- button_resolve_errors = self.xml.get_widget( 'button_resolve_errors' )
4259- page = notebook.get_nth_page(0)
4260- print "Errors status:", total
4261- if total > -1:
4262- page.show()
4263- if focus: notebook.set_current_page(0)
4264- else:
4265- page.hide()
4266-
4267- # focus tab if we have fixable errors
4268- if total > 0:
4269- button_resolve_errors.set_sensitive(True)
4270- else:
4271- button_resolve_errors.set_sensitive(False)
4272-
4273 def add_new_vhost_menu_item(self, menu_item):
4274 new_button = self.xml.get_widget( 'new_button')
4275 menu = new_button.get_menu()
4276@@ -194,43 +343,80 @@
4277 menu.add(menu_item)
4278 menu.show_all()
4279
4280+ def __update_server_status(self, image_apache_status, text, window_icon_id, stop, start, restart):
4281+ self.image_apache_status.set_from_stock(image_apache_status, gtk.ICON_SIZE_MENU)
4282+ self.label_server_status.set_text(text)
4283+ self.main_window.set_icon_from_file(self.window_status_icons[window_icon_id])
4284+ self.status_icon.tray.set_from_file(self.window_status_icons[window_icon_id])
4285+ self.menuitem_stop_apache.set_sensitive(stop)
4286+ self.status_icon.stopItem.set_sensitive(stop)
4287+ self.menuitem_start_apache.set_sensitive(start)
4288+ self.status_icon.startItem.set_sensitive(start)
4289+ self.menuitem_restart_apache.set_sensitive(restart)
4290+ self.status_icon.restartItem.set_sensitive(restart)
4291+
4292 @threaded
4293 def update_server_status(self, loop=False):
4294- window_status_icons = [
4295- # 0 - apache stopped
4296- os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle.svg' )
4297- # 1 - apache unreachable
4298- , os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle_orange.svg' ) #1
4299- # 2 - apache started
4300- , os.path.join( Configuration.GLADEPATH, 'icon_cadsoft_eagle_green.svg' ) #1
4301- ]
4302-
4303+
4304 status_change_count = 0
4305- last_status = self.apache.get_status()
4306- while True:
4307- status = self.apache.get_status()
4308- text = "Apache is stopped"
4309- image = gtk.STOCK_NO
4310-
4311-
4312- if status == 1:
4313- text = "Warning can not contact apache"
4314- image = gtk.STOCK_DIALOG_WARNING
4315- if status == 2:
4316- text = "Apache is running"
4317- image = gtk.STOCK_YES
4318-
4319- # All gtk actions must be on main thread
4320- gtk.gdk.threads_enter()
4321- self.image_apache_status.set_from_stock(image, gtk.ICON_SIZE_MENU)
4322- self.statusbar_server_status.pop(self.statusbar_server_status_context_id)
4323- self.statusbar_server_status.push(self.statusbar_server_status_context_id, text)
4324- self.main_window.set_icon_from_file(window_status_icons[status])
4325- self.menuitem_stop_apache.set_sensitive(status == 2)
4326- self.menuitem_start_apache.set_sensitive(status == 0)
4327- self.menuitem_restart_apache.set_sensitive(status == 2)
4328- gtk.gdk.threads_leave()
4329+ last_status = 0
4330+
4331+ try:
4332+ last_status = self.core.current_server.apache.get_status()
4333+ except:
4334+ pass
4335+
4336+ while self.core.current_server:
4337+ if self.status == 0:
4338+ try:
4339+ status = 1
4340+ status = self.core.current_server.apache.get_status()
4341+ except:
4342+ pass
4343+
4344+ text = "Apache is stopped"
4345+ image = gtk.STOCK_NO
4346+ if status == 1:
4347+ text = "Warning can not contact apache"
4348+ image = gtk.STOCK_DIALOG_WARNING
4349+ if status == 2:
4350+ text = "Apache is running"
4351+ image = gtk.STOCK_YES
4352+
4353+ gobject.idle_add(
4354+ self.__update_server_status,
4355+ image,
4356+ text,
4357+ status,
4358+ status == 2,
4359+ status == 0,
4360+ status == 2
4361+ )
4362
4363+ elif self.status == 1:
4364+
4365+ gobject.idle_add(
4366+ self.__update_server_status,
4367+ gtk.STOCK_CONNECT,
4368+ "Standby, establishing a connection...",
4369+ 1,
4370+ False,
4371+ False,
4372+ False
4373+ )
4374+
4375+ elif self.status == -1:
4376+
4377+ gobject.idle_add(
4378+ self.__update_server_status,
4379+ gtk.STOCK_DISCONNECT,
4380+ "Not connected",
4381+ 1,
4382+ False,
4383+ False,
4384+ False
4385+ )
4386+
4387 if not loop:
4388 break
4389
4390@@ -245,7 +431,7 @@
4391
4392
4393 def on_menuitem_stop_apache_activate(self, widget):
4394- self.apache.stop()
4395+ self.core.current_server.apache.stop()
4396 self.update_server_status()
4397
4398 def on_button_hide_warning_clicked(self, widget):
4399@@ -256,48 +442,63 @@
4400 self.please_restart()
4401 return
4402 if event.name == 'please_reload_lists':
4403- self.refresh_modules()
4404 return
4405 def browse_sites_available(self, widget):
4406- Desktop.open_dir( Configuration.SYSCONFDIR )
4407+ Desktop.open_dir( Configuration.SITES_AVAILABLE_DIR )
4408 return
4409
4410 def new_button_clicked(self, widget):
4411 new_vhost_window = VirtualHostWindow ( self )
4412 new_vhost_window.load("")
4413- new_vhost_window.run()
4414- self.refresh_config_test()
4415+ vhost = new_vhost_window.run()
4416+ if vhost:
4417+ hosts = self.core.current_server.apache.get_virtual_hosts()
4418+ hosts[vhost.get_name()] = vhost
4419+ self.vhosts_treeview.load(hosts)
4420
4421 def edit_button_clicked(self, widget, notused = None, notused2 = None):
4422- name = self.vhosts_treeview.get_selected_line()
4423- self.open_edit_vhost_window( VirtualHostModel( name ) )
4424+ vhost = self.vhosts_treeview.get_selected_line()
4425+ clone = vhost.clone()
4426+ self.open_edit_vhost_window( clone )
4427
4428-
4429 def open_edit_vhost_window(self, vhost):
4430 if not vhost.is_editable():
4431 # Use generic editor instead
4432- gew = EditGenericWindow()
4433+ gew = EditGenericWindow(self.core)
4434 gew.load( vhost.get_source_filename() )
4435- gew.run()
4436+ result = gew.run()
4437+ self.vhosts_treeview.load(self.core.current_server.apache.get_virtual_hosts())
4438+ if result:
4439+ self.please_restart()
4440+
4441 else:
4442 new_vhost_window = VirtualHostWindow ( self )
4443 new_vhost_window.load( vhost )
4444- new_vhost_window.run()
4445- self.refresh_config_test()
4446+ vhost = new_vhost_window.run()
4447+ if vhost and vhost.changed:
4448+ hosts = self.core.current_server.apache.get_virtual_hosts()
4449+ hosts[vhost.get_name()] = vhost
4450+ self.vhosts_treeview.load(hosts)
4451+ self.please_restart()
4452
4453 def delete_button_clicked( self, widget ):
4454- name = self.vhosts_treeview.get_selected_line()
4455- if ( self.is_vhost_editable( name ) == False ): return False
4456- if ( name == None ): return False
4457- result = ConfirmationWindow.ask_confirmation(
4458- "You are about to delete the following domain: \n\n"+name+"\n\nData won't be recoverable. Proceed ?"
4459- ,'VirtualHost deletion' )
4460- if ( result != True ): return False
4461- site = VirtualHostModel( name )
4462- site.delete()
4463- self.vhosts_treeview.load()
4464+ vhost = self.vhosts_treeview.get_selected_line()
4465+ if not vhost: return False
4466+ if ( self.is_vhost_editable( vhost ) == False ): return False
4467+
4468+ md = gtk.MessageDialog(self.main_window, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_YES_NO, message_format="You are about to delete the following domain: \n\n"+vhost.get_server_name()+"\n\nData will not be recoverable. Are you sure ?")
4469+ result = md.run()
4470+ md.destroy()
4471+ if result != gtk.RESPONSE_YES:
4472+ return
4473+
4474+ # do the delete
4475+ hosts = self.core.current_server.apache.get_virtual_hosts()
4476+ del hosts[vhost.get_name()]
4477+ vhost.delete()
4478+
4479+ self.vhosts_treeview.load(hosts)
4480 self.please_restart()
4481- self.refresh_config_test()
4482
4483 def edit_module_button_clicked(self, widget, notused = None, notused2 = None):
4484 name = self.modules_treeview.get_selected_line()
4485@@ -306,14 +507,13 @@
4486 module_window = ModuleWindow ( self )
4487 module_window.load( name )
4488 module_window.run()
4489- self.refresh_config_test()
4490
4491 def quit (self, widget):
4492 print 'quitting'
4493 gtk.main_quit()
4494 exit()
4495
4496- def create_vhost_list(self ):
4497+ def init_vhost_list(self ):
4498 #print parent
4499 #sw = gtk.ScrolledWindow()
4500 sw = self.xml.get_widget( 'vhosts_scroll_box' )
4501@@ -329,23 +529,10 @@
4502 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
4503 sw.set_shadow_type(gtk.SHADOW_NONE)
4504 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
4505-
4506- # create denormalized vhosts.
4507- # We check for conf files only present in /etc/apache2/sites-enabled,
4508- # display them as a separate list and offer user to normalize them
4509- # moving them in /etc/apache2/sites-available and linking them back
4510- # from /etc/apache2/sites-enabled
4511-
4512- #denormalized_treeview = VhostsTreeView.DenormalizedVhostsTreeView()
4513- #self.denormalized_treeview = denormalized_treeview
4514-
4515- #denormalized_treeview.set_sensitive( False )
4516- #denormalized_treeview.show()
4517-
4518+
4519 sw.show_all()
4520
4521-
4522- def create_errors_list(self):
4523+ def init_errors_list(self):
4524 self.treeview_errors = VhostsTreeView.ErrorsTreeView()
4525 #treeview.selected_callback = self.row_selected
4526 #treeview.connect_after("row-activated", self.edit_button_clicked )
4527@@ -353,10 +540,14 @@
4528
4529 self.xml.get_widget( 'viewport_errors' ).add(self.treeview_errors)
4530 self.xml.get_widget( 'viewport_errors' ).show_all()
4531-
4532- #self.refresh_config_test()
4533+
4534+ def init_log_list(self):
4535+ # Add rich edit to log
4536+ self.text_view_log = GuiUtils.new_apache_sourceview()
4537+ self.xml.get_widget( 'scroll_window_log' ).add( self.text_view_log )
4538+ self.text_view_log.show()
4539
4540- def create_modules_list(self ):
4541+ def init_modules_list(self ):
4542 sw = self.xml.get_widget( 'modules_scroll_box' )
4543 # create virtualhosts treeview
4544 treeview = VhostsTreeView.ModulesTreeView()
4545@@ -364,49 +555,30 @@
4546 treeview.selected_callback = self.module_row_selected
4547 self.modules_treeview = treeview
4548 self.xml.get_widget( 'modules_container' ).add(treeview)
4549- self.xml.get_widget( 'modules_container' ).reorder_child( treeview, 0)
4550 sw.set_shadow_type(gtk.SHADOW_NONE)
4551 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
4552 sw.set_shadow_type(gtk.SHADOW_NONE)
4553 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
4554 sw.show_all()
4555
4556- def refresh_vhosts ( self ):
4557- print "reloading vhosts.."
4558- self.vhosts_treeview.load()
4559- """def refresh_denormalized_vhosts (self):
4560- self.denormalized_treeview.load()
4561- #if ( len( self.denormalized_treeview.items ) > 0 ):
4562- #self.xml.get_widget( 'unnormalized_notice' ).show_all()
4563- #self.xml.get_widget( 'notebook' ).get_nth_page( 2 ).show()
4564- #else:
4565- #self.xml.get_widget( 'unnormalized_notice' ).hide_all()
4566- #self.xml.get_widget( 'notebook' ).get_nth_page( 2 ).hide()"""
4567- def refresh_modules (self):
4568- print "reloading modules.."
4569- self.modules_treeview.load()
4570- def refresh_lists (self, focus_error=False):
4571- self.refresh_vhosts()
4572- self.refresh_modules()
4573- self.refresh_config_test(focus_error)
4574-
4575 def please_restart ( self ):
4576 self.xml.get_widget( 'restart_apache_notice' ).show()
4577+
4578 def restart_apache ( self, widget ):
4579- if not Shell.command.ask_password(): return
4580+ if not self.core.current_server.command.ask_password(): return
4581 print "Restarting apache on user's request"
4582- self.apache.restart()
4583+ self.core.current_server.apache.restart()
4584 self.update_server_status()
4585 self.xml.get_widget( 'restart_apache_notice' ).hide()
4586- self.refresh_lists(True)
4587+
4588+ self.load_server_information()
4589
4590 def is_vhost_editable (self, name):
4591 return name != 'default'
4592- def is_module_editable (self, name):
4593+ def is_module_editable (self, module):
4594 editable = False
4595- if name:
4596- mod = self.modules_treeview.items[ name+".load" ]
4597- editable = mod.data[ 'configurable' ]
4598+ if module:
4599+ editable = module.data[ 'configurable' ]
4600 return editable
4601 def row_selected( self, widget ):
4602 vhost = self.get_current_vhost()
4603@@ -439,33 +611,28 @@
4604 open_module_doc(name)
4605
4606 def fix_vhosts(self, widget):
4607- if not Shell.command.ask_password(): return
4608- print "Attempting to fix virtualhosts"
4609- items = self.treeview_errors.get_items()
4610- for name in items:
4611- normalize_vhost( name )
4612- #since they were in the enabled, let's enabl'em again
4613- for name in items:
4614- if self.vhosts_treeview.items.has_key( name ):
4615- self.vhosts_treeview.items[name].toggle(True)
4616- #site.toggle(True)
4617- self.refresh_vhosts()
4618- #self.refresh_denormalized_vhosts()
4619- self.refresh_config_test()
4620+ if not self.core.current_server.command.ask_password(): return
4621+ self.core.current_server.apache.apply_fixable_errors()
4622+
4623+ errors = self.core.current_server.apache.get_errors(True)
4624+ self.treeview_errors.load(errors)
4625+ if len(errors) > 0:
4626+ self.notebook.get_nth_page(0).show()
4627+ self.notebook.set_current_page(0)
4628+ else:
4629+ self.notebook.get_nth_page(0).hide()
4630+
4631+ self.button_resolve_errors.set_sensitive(self.core.current_server.apache.get_fixable_error_count() > 0)
4632 self.please_restart()
4633+
4634 def get_current_vhost(self ):
4635- name = self.vhosts_treeview.get_selected_line()
4636- if ( name == None ): return None
4637-
4638- if self.vhosts_treeview.items.has_key( name ):
4639- return self.vhosts_treeview.items[ name ]
4640- else:
4641- return VirtualHostModel( name )
4642+ vhost = self.vhosts_treeview.get_selected_line()
4643+ return vhost
4644
4645 def surf_this(self, widget):
4646- name = self.vhosts_treeview.get_selected_line()
4647+ name = self.vhosts_treeview.get_selected_line().get_server_name()
4648 if name == 'default':
4649- server_name = 'localhost'
4650+ server_name = self.core.current_server.name
4651 else:
4652 server_name = self.get_current_vhost().get_server_name()
4653
4654@@ -477,8 +644,7 @@
4655 if ( server_name ): Desktop.open_url( protocol+"://" + server_name )
4656 def browse_this(self, widget):
4657 document_root = self.get_current_vhost().config.DocumentRoot.value
4658- Desktop.open_dir( document_root )
4659-
4660+ Desktop.open_dir( self.core.current_server.get_nautilus_browse_string(document_root) )
4661
4662 def display_about (self, widget):
4663 dialog = gtk.AboutDialog()
4664@@ -489,3 +655,26 @@
4665 dialog.set_website('http://launchpad.net/rapache')
4666 dialog.run()
4667 dialog.destroy()
4668+
4669+ # status = True: shows progress bar, status = False: shows server entry
4670+ def is_connecting(self, status, text=""):
4671+ self.button_connection.set_sensitive( not status )
4672+ self.comboboxentry_server.set_sensitive( not status )
4673+ if status:
4674+ self.start_pulse(text)
4675+ self.progressbar.show()
4676+ self.comboboxentry_server.hide()
4677+ self.notebook.set_sensitive(False)
4678+ else:
4679+ self.end_pulse()
4680+ self.progressbar.hide()
4681+ self.comboboxentry_server.show()
4682+ self.notebook.set_sensitive(True)
4683+
4684+ def show(self):
4685+ self.main_window.show()
4686+
4687+ def hide(self):
4688+ self.main_window.hide()
4689+
4690+
4691
4692=== added file 'RapacheGtk/Threads.py'
4693--- RapacheGtk/Threads.py 1970-01-01 00:00:00 +0000
4694+++ RapacheGtk/Threads.py 2010-05-16 23:57:26 +0000
4695@@ -0,0 +1,11 @@
4696+import threading
4697+import time
4698+
4699+# Define threaded attribute
4700+def threaded(f):
4701+ def wrapper(*args):
4702+
4703+ t = threading.Thread(target=f, args=args)
4704+ t.setDaemon(True) # wont keep app alive
4705+ t.start()
4706+ return wrapper
4707
4708=== added file 'RapacheGtk/TrayIcon.py'
4709--- RapacheGtk/TrayIcon.py 1970-01-01 00:00:00 +0000
4710+++ RapacheGtk/TrayIcon.py 2010-05-16 23:57:26 +0000
4711@@ -0,0 +1,84 @@
4712+#!/usr/bin/env python
4713+
4714+
4715+
4716+import os
4717+import gtk
4718+import RapacheGui
4719+
4720+
4721+class StatusIcon:
4722+ def __init__(self, main_window):
4723+ self.core = main_window.core
4724+ self.mainWindow = main_window
4725+ self.window_showing = True
4726+
4727+ self.tray = gtk.StatusIcon()
4728+ self.tray.set_tooltip( 'rapache' )
4729+ self.buildMenu()
4730+ self.tray.hide = lambda: self.tray.set_visible( False )
4731+ self.tray.show = lambda: self.tray.set_visible( True )
4732+
4733+ self.tray.connect( 'activate', self.on_activate )
4734+ self.tray.connect( 'popup-menu', self.on_popup_menu )
4735+
4736+ def buildMenu(self):
4737+ self.menu = gtk.Menu()
4738+
4739+ self.restartItem = gtk.MenuItem('Restart apache')
4740+ self.restartItem.connect('activate', self.on_restart)
4741+ self.menu.append(self.restartItem)
4742+
4743+ self.startItem = gtk.MenuItem('Start apache')
4744+ self.startItem.connect('activate', self.on_start)
4745+ self.menu.append(self.startItem)
4746+
4747+ self.stopItem = gtk.MenuItem('_Stop apache')
4748+ self.stopItem.connect('activate', self.on_stop)
4749+ self.menu.append(self.stopItem)
4750+
4751+ separator = gtk.SeparatorMenuItem()
4752+ self.menu.append(separator)
4753+
4754+ self.aboutItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
4755+ self.aboutItem.connect('activate', self.on_about)
4756+ self.menu.append(self.aboutItem)
4757+
4758+ self.quitItem = gtk.ImageMenuItem( gtk.STOCK_QUIT )
4759+ self.quitItem.connect('activate', self.on_quit)
4760+ self.menu.append(self.quitItem)
4761+
4762+
4763+ self.menu.show_all()
4764+
4765+ def on_quit(self, menuItem):
4766+ self.mainWindow.quit(menuItem)
4767+
4768+ def on_restart(self, menuItem):
4769+ self.core.current_server.apache.restart()
4770+
4771+ def on_stop(self, menuItem):
4772+ self.core.current_server.apache.stop()
4773+
4774+ def on_start(self, menuItem):
4775+ self.core.current_server.apache.start()
4776+
4777+ def on_about(self, menuItem):
4778+ self.mainWindow.display_about(menuItem)
4779+
4780+ def set_icon(self, icon):
4781+ self.tray.set_from_file(icon)
4782+
4783+ def on_activate( self, status_icon ):
4784+ self.showHide()
4785+
4786+ def on_popup_menu( self, status_icon, button, activate_time ):
4787+ self.menu.popup( None, None, None, button, activate_time )
4788+
4789+ def showHide(self, widget = None):
4790+ if self.window_showing == True:
4791+ self.mainWindow.hide()
4792+ self.window_showing = False
4793+ else:
4794+ self.mainWindow.show()
4795+ self.window_showing = True
4796
4797=== modified file 'RapacheGtk/VhostsTreeView.py'
4798--- RapacheGtk/VhostsTreeView.py 2008-09-16 19:11:20 +0000
4799+++ RapacheGtk/VhostsTreeView.py 2010-05-16 23:57:26 +0000
4800@@ -23,6 +23,7 @@
4801 from RapacheCore import Module
4802 from RapacheCore import Configuration
4803 from xml.sax import saxutils
4804+from RapacheGtk.Threads import threaded
4805
4806 class ConfFilesTreeView( CheckListView ):
4807 def __init__ (self, *args, **kwargs):
4808@@ -42,24 +43,19 @@
4809 class VhostsTreeView ( ConfFilesTreeView ):
4810 def __init__ (self, *args, **kwargs):
4811 super (VhostsTreeView, self).__init__ (*args, **kwargs)
4812- self.toggled_callback = self.__fixed_toggled
4813-
4814-
4815- def load(self):
4816- self.items = {}
4817+ self.toggled_callback = self.__toggle
4818+
4819+
4820+ def load(self, vhosts):
4821+ self.items = vhosts
4822 site_template = "<b><big>%s</big></b>\n<small>DocumentRoot: %s</small>"
4823 site_unparsable_template = "<b><big>%s</big></b>\n<small><i>Further information not available</i></small>"
4824
4825 lstore = self._reset_model()
4826
4827 data = []
4828- dirList=os.listdir( Configuration.SITES_AVAILABLE_DIR )
4829- dirList = [x for x in dirList if self._blacklisted( x ) == False ]
4830- for fname in dirList :
4831- site = VirtualHostModel( fname )
4832- if not site.is_new:
4833- self.items[ fname ] = site
4834-
4835+ icon_theme = gtk.icon_theme_get_default()
4836+
4837 for idx in sorted( self.items ):
4838 site = self.items[ idx ]
4839 if ( site.parsable ):
4840@@ -70,74 +66,46 @@
4841 iter = lstore.append()
4842
4843 favicon = site.get_icon()
4844- pixbuf = gtk.gdk.pixbuf_new_from_file( favicon )
4845+ if favicon:
4846+ pixbuf = gtk.gdk.pixbuf_new_from_file( favicon )
4847+ else:
4848+ pixbuf = icon_theme.lookup_icon("gtk-directory", 24, 0).load_icon()
4849
4850 lstore.set(iter,
4851 COLUMN_FIXED, site.enabled,
4852 COLUMN_ICON, pixbuf,
4853 COLUMN_SEVERITY, site.get_name(),
4854- COLUMN_MARKUP, markup )
4855-
4856- def __fixed_toggled(self, cell, path, treeview):
4857- if not Shell.command.ask_password(): return
4858+ COLUMN_MARKUP, markup,
4859+ COLUMN_OBJECT, site )
4860+
4861+ def __toggle(self, cell, path, treeview):
4862+
4863 # get toggled iter
4864 model = treeview.get_model()
4865 iter = model.get_iter((int(path),))
4866- fixed = model.get_value(iter, COLUMN_FIXED)
4867- name = model.get_value(iter, COLUMN_SEVERITY)
4868+ enabled = model.get_value(iter, COLUMN_FIXED)
4869+ vhost = model.get_value(iter, COLUMN_OBJECT)
4870
4871- fixed = not fixed
4872- if fixed:
4873- Shell.command.sudo_execute ( [Configuration.APPPATH+'/hosts-manager', '-a',name])
4874- else :
4875- Shell.command.sudo_execute ( [Configuration.APPPATH+'/hosts-manager', '-r',name])
4876- # set new value
4877- site = VirtualHostModel( name )
4878- site.toggle( fixed )
4879- model.set(iter, COLUMN_FIXED, site.enabled )
4880- if ( site.changed ):
4881- self.raise_event( 'please_restart_apache' )
4882+ enabled = not enabled
4883+ if not vhost.apache.server.command.ask_password(): return
4884+ model.set(iter, COLUMN_FIXED, enabled )
4885+ self.__update_vhost_thread(vhost, enabled)
4886+
4887+ @threaded
4888+ def __update_vhost_thread(self, vhost, enabled):
4889+ try:
4890+ vhost.toggle( enabled )
4891+ except:
4892+ pass
4893+ gobject.idle_add(self.__update_vhost_post, vhost)
4894+
4895+ def __update_vhost_post(self, vhost):
4896+ if ( vhost.changed ):
4897+ self.raise_event( 'please_restart_apache', vhost )
4898+ self.raise_event( 'please_reload_lists', {}, True )
4899+
4900 gobject.type_register (VhostsTreeView)
4901-"""
4902-class DenormalizedVhostsTreeView ( ConfFilesTreeView ):
4903- def __init__ (self, *args, **kwargs):
4904- super (DenormalizedVhostsTreeView, self).__init__ (*args, **kwargs)
4905- #print self.column_checkbox, self.column_description, self.column_icon
4906- self.column_checkbox.set_visible( False )
4907- self.column_icon.get_cell_renderers()[0].set_property( 'stock-id', gtk.STOCK_DIALOG_WARNING )
4908- def load(self):
4909- self.items = {}
4910- site_template = "<b><big>%s</big></b>"
4911- lstore = self._reset_model()
4912-
4913- data = []
4914- dirList=os.listdir( Configuration.SITES_ENABLED_DIR )
4915- dirList = [x for x in dirList if self._blacklisted( x ) == False ]
4916- dirList = [x for x in dirList if is_denormalized_vhost( x ) == False ]
4917-
4918- self.items = {}
4919- for fname in dirList :
4920- site = VirtualHostModel( fname )
4921- self.items[ fname ] = site
4922- site = None
4923- for idx in sorted( self.items ):
4924- site = self.items[ idx ]
4925- normalizable = not is_not_normalizable(site.get_name())
4926- markup = site_template % site.get_name()
4927- if ( normalizable == False ):
4928- markup = markup + " CANNOT FIX"
4929- iter = lstore.append()
4930-
4931- lstore.set(iter,
4932- COLUMN_FIXED, normalizable,
4933- COLUMN_SEVERITY, site.get_name(),
4934- COLUMN_MARKUP, markup
4935- )
4936-
4937- def toggled_callback(self, *args, **kwargs):
4938- pass
4939-gobject.type_register (DenormalizedVhostsTreeView )
4940-"""
4941+
4942 class ModulesTreeView ( ConfFilesTreeView ):
4943 def __init__ (self, *args, **kwargs):
4944 super (ModulesTreeView, self).__init__ (*args, **kwargs)
4945@@ -146,35 +114,25 @@
4946 pixbuf = gtk.gdk.pixbuf_new_from_file( icon_file_name )
4947
4948 self.column_icon.get_cell_renderers()[0].set_property('pixbuf', pixbuf)
4949- self.toggled_callback = self.__fixed_toggled
4950+ self.toggled_callback = self.__toggle
4951 self.selected_callback = self.__selected
4952 self.column_description.get_cell_renderers()[0].set_property('wrap-mode', gtk.WRAP_WORD)
4953 self.column_description.get_cell_renderers()[0].set_property('wrap-width', 400)
4954 def __selected(self, *args, **kwargs ):
4955 print "MODULE NAME:", self.get_selected_line()
4956 print "DEPENDANTS: ", Module.get_module_dependants(self.get_selected_line(), self.items)
4957- def load(self):
4958- self.items = {}
4959+
4960+
4961+ def load(self, modules):
4962+ self.items = modules
4963 mod_template = "<b><big>%s</big></b>"
4964 mod_unparsable_template = "<b><big>%s</big></b>\n<small><i>Further information not available</i></small>"
4965 lstore = self._reset_model()
4966 data = []
4967-
4968- """dirList=os.listdir( Configuration.MODS_AVAILABLE_DIR )
4969- dirList = [x for x in dirList if self._blacklisted( x ) == False ]
4970- for fname in dirList :
4971- mod = Module.ModuleModel( fname )
4972- try:
4973- mod.load()
4974- except "VhostUnparsable":
4975- pass
4976- self.items[ fname ] = mod
4977- mod = None
4978- """
4979- self.items = Module.module_list()
4980-
4981- for idx in sorted( self.items ):
4982- mod = self.items[ idx ]
4983+ keys = self.items.keys()
4984+ keys.sort()
4985+ for key in keys:
4986+ mod = modules[key]
4987 if ( mod.parsable ):
4988 markup = mod_template \
4989 % ( mod.data['name'] ) #, mod.data[ 'DocumentRoot' ] )
4990@@ -190,28 +148,44 @@
4991 lstore.set(iter,
4992 COLUMN_FIXED, mod.data['enabled'],
4993 COLUMN_SEVERITY, mod.data['name'],
4994- COLUMN_MARKUP, markup )
4995+ COLUMN_MARKUP, markup,
4996+ COLUMN_OBJECT, mod )
4997
4998+<<<<<<< TREE
4999 def __fixed_toggled(self, cell, path, treeview):
5000 if not Shell.command.ask_password(): return
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: