mirror of
https://github.com/gryf/wicd.git
synced 2025-12-20 21:08:06 +01:00
merged latest 1.6
This commit is contained in:
127
CHANGES
127
CHANGES
@@ -1,4 +1,131 @@
|
|||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
revno: 434
|
||||||
|
committer: Adam Blackburn <compwiz18@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Sun 2009-07-05 08:51:39 -1000
|
||||||
|
message:
|
||||||
|
updated translations.py
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 433
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Sun 2009-07-05 14:42:39 -0400
|
||||||
|
message:
|
||||||
|
Actually tell the user that he may need to be in wpath.wicd_group if wicd-clientgets an access-denied error.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 432
|
||||||
|
committer: Adam Blackburn <compwiz18@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Sun 2009-07-05 08:16:59 -1000
|
||||||
|
message:
|
||||||
|
check to see if the interface exists in the decorator
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 431
|
||||||
|
committer: Dan O'Reilly <oreilldf@gmail.com>
|
||||||
|
branch nick: trunk
|
||||||
|
timestamp: Thu 2009-07-02 18:26:37 -0400
|
||||||
|
message:
|
||||||
|
Make sure we run to_unicode on all properties we read from disk or get from the user (bug 390680).
|
||||||
|
Don't try to run global scripts of the global script directory doesn't exist (bug 386244).
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 430
|
||||||
|
committer: Dan O'Reilly <oreilldf@gmail.com>
|
||||||
|
branch nick: trunk
|
||||||
|
timestamp: Thu 2009-07-02 16:50:48 -0400
|
||||||
|
message:
|
||||||
|
Fix crash when trying to create an ad-hoc network.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 429
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Tue 2009-06-30 22:58:44 -0400
|
||||||
|
message:
|
||||||
|
Merged r353 of 1.6-nacl.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.62
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Tue 2009-06-30 22:43:17 -0400
|
||||||
|
message:
|
||||||
|
Background wicd's startup in Slackware's initscript.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.61
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Tue 2009-06-30 21:51:33 -0400
|
||||||
|
message:
|
||||||
|
Fix a small unicode problem in wicd-curses that caused a crash in Debian Lenny.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 428
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Wed 2009-06-24 19:14:43 -0400
|
||||||
|
message:
|
||||||
|
Merge bugfixes from r351 of 1.6-nacl, thanks to comfrey in #wicd for noticing them.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.60
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Wed 2009-06-24 19:10:30 -0400
|
||||||
|
message:
|
||||||
|
Do nothing if the user makes a connection attempt while scanning.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.59
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Wed 2009-06-24 18:44:29 -0400
|
||||||
|
message:
|
||||||
|
Do nothing in wicd-curses if there are no networks present.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.58
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Wed 2009-06-24 18:43:58 -0400
|
||||||
|
message:
|
||||||
|
Merged r417 of mainline 1.6.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.57
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Sun 2009-06-21 14:07:22 -0400
|
||||||
|
message:
|
||||||
|
Merged r426 of mainline 1.6.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.56
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Fri 2009-06-19 23:20:29 -0400
|
||||||
|
message:
|
||||||
|
Merge r417 of mainline 1.6.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.55
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Wed 2009-06-17 20:52:59 -0400
|
||||||
|
message:
|
||||||
|
Merge r416 of mainline 1.6.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 202.2.54
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6-nacl
|
||||||
|
timestamp: Sun 2009-06-07 14:53:04 -0400
|
||||||
|
message:
|
||||||
|
Merge 411 of mainline 1.6.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 427
|
||||||
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Sun 2009-06-21 14:45:44 -0400
|
||||||
|
message:
|
||||||
|
Fix typo that crashes wicd-curses on attempting to bring up the help dialog.
|
||||||
|
------------------------------------------------------------
|
||||||
|
revno: 426
|
||||||
|
committer: Adam Blackburn <compwiz18@gmail.com>
|
||||||
|
branch nick: 1.6
|
||||||
|
timestamp: Sat 2009-06-20 23:02:23 -0500
|
||||||
|
message:
|
||||||
|
updated setup.py version and CHANGES
|
||||||
|
------------------------------------------------------------
|
||||||
revno: 425
|
revno: 425
|
||||||
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
committer: Andrew Psaltis <ampsaltis@gmail.com>
|
||||||
branch nick: 1.6
|
branch nick: 1.6
|
||||||
|
|||||||
16
NEWS
16
NEWS
@@ -1,5 +1,19 @@
|
|||||||
Wicd 1.6.x Branch
|
Wicd 1.6.0 Branch
|
||||||
|
1.6.2:
|
||||||
|
Minor Changes:
|
||||||
|
- Now deals better if the interface disappears while running
|
||||||
|
- Will now start if the global script directories don't exist
|
||||||
|
- Adhoc window will now work correctly
|
||||||
|
- PSK can be generated from non-ASCII characters
|
||||||
|
- Fix a minor wicd-curses crash while connecting during a scan
|
||||||
|
|
||||||
|
1.6.1:
|
||||||
|
Minor Changes:
|
||||||
|
- User is told if the lack permission to access the daemon
|
||||||
|
- Support for wireless cards that don't report signal strength added
|
||||||
|
- Enhanced network configuration dialog title
|
||||||
|
|
||||||
|
1.6.0:
|
||||||
Major Changes:
|
Major Changes:
|
||||||
- Improved tray icon and GUI images (thanks to Martin Sagastume)
|
- Improved tray icon and GUI images (thanks to Martin Sagastume)
|
||||||
- Reorganized network list in the GUI for easier navigation
|
- Reorganized network list in the GUI for easier navigation
|
||||||
|
|||||||
@@ -33,10 +33,6 @@ def error(ui,parent,message):
|
|||||||
dialog = TextDialog(message,6,40,('important',"ERROR"))
|
dialog = TextDialog(message,6,40,('important',"ERROR"))
|
||||||
return dialog.run(ui,parent)
|
return dialog.run(ui,parent)
|
||||||
|
|
||||||
# My savior. :-)
|
|
||||||
# Although I could have made this myself pretty easily, just want to give credit
|
|
||||||
# where it's due.
|
|
||||||
# http://excess.org/urwid/browser/contrib/trunk/rbreu_filechooser.py
|
|
||||||
class SelText(urwid.Text):
|
class SelText(urwid.Text):
|
||||||
"""A selectable text widget. See urwid.Text."""
|
"""A selectable text widget. See urwid.Text."""
|
||||||
|
|
||||||
@@ -253,7 +249,7 @@ class ComboBoxException(Exception):
|
|||||||
# I based this off of the code found here:
|
# I based this off of the code found here:
|
||||||
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py
|
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py
|
||||||
# This is a hack/kludge. It isn't without quirks, but it more or less works.
|
# This is a hack/kludge. It isn't without quirks, but it more or less works.
|
||||||
# We need to wait for changes in urwid's Canvas controls before we can actually
|
# We need to wait for changes in urwid's Canvas API before we can actually
|
||||||
# make a real ComboBox.
|
# make a real ComboBox.
|
||||||
class ComboBox(urwid.WidgetWrap):
|
class ComboBox(urwid.WidgetWrap):
|
||||||
"""A ComboBox of text objects"""
|
"""A ComboBox of text objects"""
|
||||||
@@ -333,9 +329,8 @@ class ComboBox(urwid.WidgetWrap):
|
|||||||
str,trash = self.label.get_text()
|
str,trash = self.label.get_text()
|
||||||
|
|
||||||
self.overlay = None
|
self.overlay = None
|
||||||
#w,sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc')
|
|
||||||
self.cbox = DynWrap(SelText(self.DOWN_ARROW),attrs=attrs,focus_attr=focus_attr)
|
self.cbox = DynWrap(SelText(self.DOWN_ARROW),attrs=attrs,focus_attr=focus_attr)
|
||||||
# Unicode will kill me sooner or later. ^_^
|
# Unicode will kill me sooner or later.
|
||||||
if label != '':
|
if label != '':
|
||||||
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
|
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
|
||||||
else:
|
else:
|
||||||
@@ -344,10 +339,9 @@ class ComboBox(urwid.WidgetWrap):
|
|||||||
|
|
||||||
# We need this to pick our keypresses
|
# We need this to pick our keypresses
|
||||||
self.use_enter = use_enter
|
self.use_enter = use_enter
|
||||||
# The Focus
|
|
||||||
self.focus = focus
|
self.focus = focus
|
||||||
|
|
||||||
# The callback and friends
|
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.user_args = user_args
|
self.user_args = user_args
|
||||||
|
|
||||||
@@ -443,11 +437,6 @@ class Dialog2(urwid.WidgetWrap):
|
|||||||
w = self.frame
|
w = self.frame
|
||||||
self.view = w
|
self.view = w
|
||||||
|
|
||||||
# pad area around listbox
|
|
||||||
#w = urwid.Padding(w, ('fixed left',2), ('fixed right',2))
|
|
||||||
#w = urwid.Filler(w, ('fixed top',1), ('fixed bottom',1))
|
|
||||||
#w = urwid.AttrWrap(w, 'body')
|
|
||||||
|
|
||||||
# buttons: tuple of name,exitcode
|
# buttons: tuple of name,exitcode
|
||||||
def add_buttons(self, buttons):
|
def add_buttons(self, buttons):
|
||||||
l = []
|
l = []
|
||||||
@@ -503,8 +492,6 @@ class Dialog2(urwid.WidgetWrap):
|
|||||||
class TextDialog(Dialog2):
|
class TextDialog(Dialog2):
|
||||||
def __init__(self, text, height, width, header=None,align='left'):
|
def __init__(self, text, height, width, header=None,align='left'):
|
||||||
l = [urwid.Text(text)]
|
l = [urwid.Text(text)]
|
||||||
#for line in text:
|
|
||||||
# l.append( urwid.Text( line,align=align))
|
|
||||||
body = urwid.ListBox(l)
|
body = urwid.ListBox(l)
|
||||||
body = urwid.AttrWrap(body, 'body')
|
body = urwid.AttrWrap(body, 'body')
|
||||||
|
|
||||||
@@ -596,7 +583,6 @@ class OptCols(urwid.WidgetWrap):
|
|||||||
else:
|
else:
|
||||||
key += part
|
key += part
|
||||||
|
|
||||||
#theText = urwid.Text([(attrs[0],cmd[0]),(attrs[1],cmd[1])])
|
|
||||||
if debug:
|
if debug:
|
||||||
callback = self.debugClick
|
callback = self.debugClick
|
||||||
args = cmd[1]
|
args = cmd[1]
|
||||||
@@ -608,9 +594,6 @@ class OptCols(urwid.WidgetWrap):
|
|||||||
('fixed',len(key)+1,urwid.Text((attrs[0],key+':')) ),
|
('fixed',len(key)+1,urwid.Text((attrs[0],key+':')) ),
|
||||||
urwid.AttrWrap(urwid.Text(cmd[1]),attrs[1])],
|
urwid.AttrWrap(urwid.Text(cmd[1]),attrs[1])],
|
||||||
callback,args)
|
callback,args)
|
||||||
#if i != len(tuples)-1:
|
|
||||||
# textList.append(('fixed',maxlen,col))
|
|
||||||
#else: # The last one
|
|
||||||
textList.append(col)
|
textList.append(col)
|
||||||
i+=1
|
i+=1
|
||||||
if debug:
|
if debug:
|
||||||
@@ -625,19 +608,3 @@ class OptCols(urwid.WidgetWrap):
|
|||||||
def mouse_event(self,size,event,button,x,y,focus):
|
def mouse_event(self,size,event,button,x,y,focus):
|
||||||
# Widgets are evenly long (as of current), so...
|
# Widgets are evenly long (as of current), so...
|
||||||
return self._w.mouse_event(size,event,button,x,y,focus)
|
return self._w.mouse_event(size,event,button,x,y,focus)
|
||||||
"""
|
|
||||||
if self.debug:
|
|
||||||
if x > size[0]-10:
|
|
||||||
return
|
|
||||||
widsize = (size[0]-10)/len(self.callbacks)
|
|
||||||
else:
|
|
||||||
widsize = size[0]/len(self.callbacks)
|
|
||||||
widnum = x/widsize
|
|
||||||
if self.debug:
|
|
||||||
text = str(widnum)
|
|
||||||
if self.callbacks[widnum] == None:
|
|
||||||
text += " None"
|
|
||||||
self.debug.set_text(text)
|
|
||||||
elif self.callbacks[widnum] != None:
|
|
||||||
self.callbacks[widnum]()
|
|
||||||
"""
|
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ def check_for_wireless(iwconfig, wireless_ip, set_status):
|
|||||||
if not network:
|
if not network:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
network = str(network)
|
network = unicode(network)
|
||||||
if daemon.GetSignalDisplayType() == 0:
|
if daemon.GetSignalDisplayType() == 0:
|
||||||
strength = wireless.GetCurrentSignalStrength(iwconfig)
|
strength = wireless.GetCurrentSignalStrength(iwconfig)
|
||||||
else:
|
else:
|
||||||
@@ -202,7 +202,7 @@ def about_dialog(body):
|
|||||||
# Modeled after htop's help
|
# Modeled after htop's help
|
||||||
def help_dialog(body):
|
def help_dialog(body):
|
||||||
textT = urwid.Text(('header','wicd-curses help'),'right')
|
textT = urwid.Text(('header','wicd-curses help'),'right')
|
||||||
textSH = urwid.Text(['This is ',('blue','wicd-curses-'+CURSES_REVNO),' using wicd ',unicode(daemon.Hello()),'\n'])
|
textSH = urwid.Text(['This is ',('blue','wicd-curses-'+CURSES_REV),' using wicd ',unicode(daemon.Hello()),'\n'])
|
||||||
|
|
||||||
textH = urwid.Text([
|
textH = urwid.Text([
|
||||||
"For more detailed help, consult the wicd-curses(8) man page.\n",
|
"For more detailed help, consult the wicd-curses(8) man page.\n",
|
||||||
@@ -383,17 +383,24 @@ class WiredComboBox(ComboBox):
|
|||||||
|
|
||||||
def keypress(self,size,key):
|
def keypress(self,size,key):
|
||||||
prev_focus = self.get_focus()[1]
|
prev_focus = self.get_focus()[1]
|
||||||
key = self.__super.keypress(size,key)
|
key = ComboBox.keypress(self,size,key)
|
||||||
|
if key == ' ':
|
||||||
if self.get_focus()[1] == len(self.list)-1:
|
if self.get_focus()[1] == len(self.list)-1:
|
||||||
dialog = InputDialog(('header',language["add_new_wired_profile"]),7,30)
|
dialog = InputDialog(('header',language["add_new_wired_profile"]),7,30)
|
||||||
|
|
||||||
exitcode,name = dialog.run(ui,self.parent)
|
exitcode,name = dialog.run(ui,self.parent)
|
||||||
if exitcode == 0:
|
if exitcode == 0:
|
||||||
|
name = name.strip()
|
||||||
|
if not name:
|
||||||
|
error(ui,self.parent,'Invalid profile name')
|
||||||
|
self.set_focus(prev_focus)
|
||||||
|
return key
|
||||||
|
|
||||||
wired.CreateWiredNetworkProfile(name,False)
|
wired.CreateWiredNetworkProfile(name,False)
|
||||||
self.set_list(wired.GetWiredProfileList())
|
self.set_list(wired.GetWiredProfileList())
|
||||||
self.rebuild_combobox()
|
self.rebuild_combobox()
|
||||||
self.set_focus(prev_focus)
|
self.set_focus(prev_focus)
|
||||||
else:
|
else:
|
||||||
|
print "updating..."
|
||||||
wired.ReadWiredNetworkProfile(self.get_selected_profile())
|
wired.ReadWiredNetworkProfile(self.get_selected_profile())
|
||||||
if key == 'delete':
|
if key == 'delete':
|
||||||
if len(self.theList) == 1:
|
if len(self.theList) == 1:
|
||||||
@@ -821,18 +828,17 @@ class appGUI():
|
|||||||
self.diag.ready_widgets(ui,self.frame)
|
self.diag.ready_widgets(ui,self.frame)
|
||||||
self.frame.set_body(self.diag)
|
self.frame.set_body(self.diag)
|
||||||
self.diag_type = 'conf'
|
self.diag_type = 'conf'
|
||||||
# Guess what! I actually need to put this here, else I'll have
|
if "enter" in keys or 'C' in keys:
|
||||||
# tons of references to self.frame lying around. ^_^
|
if not self.scanning:
|
||||||
if "enter" in keys:
|
|
||||||
focus = self.frame.body.get_focus()
|
focus = self.frame.body.get_focus()
|
||||||
if focus == self.wiredCB:
|
if focus == self.wiredCB:
|
||||||
self.special = focus
|
self.special = focus
|
||||||
self.connect("wired",0)
|
self.connect("wired",0)
|
||||||
else:
|
else:
|
||||||
# wless list only other option
|
# wless list only other option, if it is around
|
||||||
|
if self.wlessLB != self.no_wlan:
|
||||||
wid,pos = self.thePile.get_focus().get_focus()
|
wid,pos = self.thePile.get_focus().get_focus()
|
||||||
self.connect("wireless",pos)
|
self.connect("wireless",pos)
|
||||||
|
|
||||||
if "esc" in keys:
|
if "esc" in keys:
|
||||||
# Force disconnect here if connection in progress
|
# Force disconnect here if connection in progress
|
||||||
if self.connecting:
|
if self.connecting:
|
||||||
@@ -853,15 +859,6 @@ class appGUI():
|
|||||||
return True
|
return True
|
||||||
if "A" in keys:
|
if "A" in keys:
|
||||||
about_dialog(self.frame)
|
about_dialog(self.frame)
|
||||||
if "C" in keys:
|
|
||||||
focus = self.frame.body.get_focus()
|
|
||||||
if focus == self.wiredCB:
|
|
||||||
self.special = focus
|
|
||||||
self.connect("wired",0)
|
|
||||||
else:
|
|
||||||
# wless list only other option
|
|
||||||
wid,pos = self.thePile.get_focus().get_focus()
|
|
||||||
self.connect("wireless",pos)
|
|
||||||
if "I" in keys:
|
if "I" in keys:
|
||||||
self.raise_hidden_network_dialog()
|
self.raise_hidden_network_dialog()
|
||||||
if "H" in keys or 'h' in keys or '?' in keys:
|
if "H" in keys or 'h' in keys or '?' in keys:
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ wicd_start() {
|
|||||||
echo "$PIDFILE and try again..."
|
echo "$PIDFILE and try again..."
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
echo "Starting wicd daemon: $DAEMON"
|
echo "Starting wicd daemon: $DAEMON &"
|
||||||
wicd 2>/dev/null 1>&2
|
wicd 2>/dev/null 1>&2 &
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,20 +11,6 @@
|
|||||||
<allow send_interface="org.wicd.daemon.wireless"/>
|
<allow send_interface="org.wicd.daemon.wireless"/>
|
||||||
<allow send_destination="org.wicd.daemon.wired"/>
|
<allow send_destination="org.wicd.daemon.wired"/>
|
||||||
<allow send_interface="org.wicd.daemon.wired"/>
|
<allow send_interface="org.wicd.daemon.wired"/>
|
||||||
<allow send_destination="org.wicd.daemon.config"/>
|
|
||||||
<allow send_interface="org.wicd.daemon.config"/>
|
|
||||||
</policy>
|
|
||||||
|
|
||||||
<policy at_console="true">
|
|
||||||
<allow send_destination="org.wicd.daemon"/>
|
|
||||||
<allow send_interface="org.wicd.daemon"/>
|
|
||||||
<allow send_destination="org.wicd.daemon.wireless"/>
|
|
||||||
<allow send_interface="org.wicd.daemon.wireless"/>
|
|
||||||
<allow send_destination="org.wicd.daemon.wired"/>
|
|
||||||
<allow send_interface="org.wicd.daemon.wired"/>
|
|
||||||
<allow send_destination="org.wicd.daemon.config"/>
|
|
||||||
<allow send_interface="org.wicd.daemon.config"/>
|
|
||||||
<allow send_interface="org.freedesktop.DBus.Introspectable"/>
|
|
||||||
</policy>
|
</policy>
|
||||||
|
|
||||||
<policy context="default">
|
<policy context="default">
|
||||||
@@ -33,9 +19,29 @@
|
|||||||
|
|
||||||
<!-- This Unix group will have permission to use Wicd's gui -->
|
<!-- This Unix group will have permission to use Wicd's gui -->
|
||||||
<policy group="%WICDGROUP%">
|
<policy group="%WICDGROUP%">
|
||||||
<allow send_interface="org.freedesktop.DBus.Introspectable"/>
|
|
||||||
<allow send_destination="org.wicd.daemon"/>
|
<allow send_destination="org.wicd.daemon"/>
|
||||||
<allow send_interface="org.wicd.daemon"/>
|
<allow send_interface="org.wicd.daemon"/>
|
||||||
|
<allow send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||||
|
<!-- The Introspectable allow shouldn't be needed here, but
|
||||||
|
it seems that a few distributions aren't yet allowing
|
||||||
|
it in their hal configs, and we need it here, so... -->
|
||||||
|
</policy>
|
||||||
|
|
||||||
|
<!-- Comment the block below if you do not want all users logged in
|
||||||
|
locally to have permission to use wicd-client. This ignores the
|
||||||
|
group based permission model defined above for the "%WICDGROUP%"
|
||||||
|
group. Note that this only applies if you are using ConsoleKit -
|
||||||
|
if you do not have ConsoleKit installed and in use, then this
|
||||||
|
block makes no difference either way. -->
|
||||||
|
|
||||||
|
<policy at_console="true">
|
||||||
|
<allow send_destination="org.wicd.daemon"/>
|
||||||
|
<allow send_interface="org.wicd.daemon"/>
|
||||||
|
<allow send_destination="org.wicd.daemon.wireless"/>
|
||||||
|
<allow send_interface="org.wicd.daemon.wireless"/>
|
||||||
|
<allow send_destination="org.wicd.daemon.wired"/>
|
||||||
|
<allow send_interface="org.wicd.daemon.wired"/>
|
||||||
|
<allow send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||||
</policy>
|
</policy>
|
||||||
|
|
||||||
</busconfig>
|
</busconfig>
|
||||||
|
|||||||
5
setup.py
5
setup.py
@@ -26,7 +26,7 @@ import subprocess
|
|||||||
|
|
||||||
# Be sure to keep this updated!
|
# Be sure to keep this updated!
|
||||||
# VERSIONNUMBER
|
# VERSIONNUMBER
|
||||||
VERSION_NUM = '1.6.1'
|
VERSION_NUM = '1.6.2'
|
||||||
# REVISION_NUM is automatically updated
|
# REVISION_NUM is automatically updated
|
||||||
REVISION_NUM = 'unknown'
|
REVISION_NUM = 'unknown'
|
||||||
CURSES_REVNO = 'uimod'
|
CURSES_REVNO = 'uimod'
|
||||||
@@ -412,6 +412,7 @@ class get_translations(Command):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
import urllib, shutil
|
import urllib, shutil
|
||||||
|
if os.path.exists('translations'):
|
||||||
shutil.rmtree('translations/')
|
shutil.rmtree('translations/')
|
||||||
os.makedirs('translations')
|
os.makedirs('translations')
|
||||||
filename, headers = urllib.urlretrieve('http://wicd.sourceforge.net/translator/idlist/')
|
filename, headers = urllib.urlretrieve('http://wicd.sourceforge.net/translator/idlist/')
|
||||||
@@ -525,7 +526,7 @@ try:
|
|||||||
data.append((wpath.resume, ['other/80-wicd-connect.sh' ]))
|
data.append((wpath.resume, ['other/80-wicd-connect.sh' ]))
|
||||||
data.append((wpath.suspend, ['other/50-wicd-suspend.sh' ]))
|
data.append((wpath.suspend, ['other/50-wicd-suspend.sh' ]))
|
||||||
if not wpath.no_install_pmutils:
|
if not wpath.no_install_pmutils:
|
||||||
data.append((wpath.pmutils, ['other/55wicd' ]))
|
data.append((wpath.pmutils, ['other/91wicd' ]))
|
||||||
print 'Using pid path', os.path.basename(wpath.pidfile)
|
print 'Using pid path', os.path.basename(wpath.pidfile)
|
||||||
print 'Language support for',
|
print 'Language support for',
|
||||||
for language in os.listdir('translations/'):
|
for language in os.listdir('translations/'):
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ class WirelessInterface(Interface, BaseWirelessInterface):
|
|||||||
try:
|
try:
|
||||||
results = self.scan_iface.Scan()
|
results = self.scan_iface.Scan()
|
||||||
except iwscan.error, e:
|
except iwscan.error, e:
|
||||||
print "ERROR: %s"
|
print "ERROR: %s" % e
|
||||||
return []
|
return []
|
||||||
return filter(None, [self._parse_ap(cell) for cell in results])
|
return filter(None, [self._parse_ap(cell) for cell in results])
|
||||||
|
|
||||||
|
|||||||
@@ -111,12 +111,12 @@ class ConfigManager(RawConfigParser):
|
|||||||
except (ValueError, TypeError, AttributeError):
|
except (ValueError, TypeError, AttributeError):
|
||||||
ret = Noneify(ret)
|
ret = Noneify(ret)
|
||||||
# This is a workaround for a python-dbus issue on 64-bit systems.
|
# This is a workaround for a python-dbus issue on 64-bit systems.
|
||||||
if isinstance(ret, (int)):
|
if isinstance(ret, (int, long)):
|
||||||
try:
|
try:
|
||||||
Int32(ret)
|
Int32(ret)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
ret = long(ret)
|
ret = str(ret)
|
||||||
return ret
|
return to_unicode(ret)
|
||||||
|
|
||||||
def get(self, *args, **kargs):
|
def get(self, *args, **kargs):
|
||||||
""" Calls the get_option method """
|
""" Calls the get_option method """
|
||||||
|
|||||||
@@ -182,6 +182,8 @@ def WriteLine(my_file, text):
|
|||||||
|
|
||||||
def ExecuteScripts(scripts_dir, verbose=False, extra_parameters=()):
|
def ExecuteScripts(scripts_dir, verbose=False, extra_parameters=()):
|
||||||
""" Execute every executable file in a given directory. """
|
""" Execute every executable file in a given directory. """
|
||||||
|
if not os.path.exists(scripts_dir):
|
||||||
|
return
|
||||||
for obj in os.listdir(scripts_dir):
|
for obj in os.listdir(scripts_dir):
|
||||||
obj = os.path.abspath(os.path.join(scripts_dir, obj))
|
obj = os.path.abspath(os.path.join(scripts_dir, obj))
|
||||||
if os.path.isfile(obj) and os.access(obj, os.X_OK):
|
if os.path.isfile(obj) and os.access(obj, os.X_OK):
|
||||||
|
|||||||
@@ -655,17 +655,16 @@ class WiredNetworkEntry(NetworkEntry):
|
|||||||
|
|
||||||
def add_profile(self, widget):
|
def add_profile(self, widget):
|
||||||
""" Add a profile to the profile list. """
|
""" Add a profile to the profile list. """
|
||||||
print "adding profile"
|
|
||||||
|
|
||||||
response = string_input("Enter a profile name", "The profile name " +
|
response = string_input("Enter a profile name", "The profile name " +
|
||||||
"will not be used by the computer. It " +
|
"will not be used by the computer. It " +
|
||||||
"allows you to " +
|
"allows you to " +
|
||||||
"easily distinguish between different network " +
|
"easily distinguish between different network " +
|
||||||
"profiles.", "Profile name:")
|
"profiles.", "Profile name:").strip()
|
||||||
|
|
||||||
# if response is "" or None
|
# if response is "" or None
|
||||||
if not response:
|
if not response:
|
||||||
return
|
error(None, "Invalid profile name", block=True)
|
||||||
|
return False
|
||||||
|
|
||||||
profile_name = response
|
profile_name = response
|
||||||
profile_list = wired.GetWiredProfileList()
|
profile_list = wired.GetWiredProfileList()
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ class Wireless(Controller):
|
|||||||
wiface = self.wiface
|
wiface = self.wiface
|
||||||
print 'Creating ad-hoc network'
|
print 'Creating ad-hoc network'
|
||||||
print 'Stopping dhcp client and wpa_supplicant'
|
print 'Stopping dhcp client and wpa_supplicant'
|
||||||
BACKEND.ReleaseDHCP()
|
wiface.ReleaseDHCP()
|
||||||
wiface.StopWPA()
|
wiface.StopWPA()
|
||||||
print 'Putting wireless interface down'
|
print 'Putting wireless interface down'
|
||||||
wiface.Down()
|
wiface.Down()
|
||||||
@@ -880,7 +880,8 @@ class WirelessConnectThread(ConnectThread):
|
|||||||
if self.network.get('enctype'):
|
if self.network.get('enctype'):
|
||||||
self.SetStatus('validating_authentication')
|
self.SetStatus('validating_authentication')
|
||||||
if not wiface.ValidateAuthentication(time.time()):
|
if not wiface.ValidateAuthentication(time.time()):
|
||||||
if not self.connect_result:
|
print "connect result is %s" % self.connect_result
|
||||||
|
if not self.connect_result or self.connect_result == 'Failed':
|
||||||
self.abort_connection('bad_pass')
|
self.abort_connection('bad_pass')
|
||||||
|
|
||||||
# Set up gateway, IP address, and DNS servers.
|
# Set up gateway, IP address, and DNS servers.
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class PreferencesDialog(object):
|
|||||||
sudo_list = [self.sudoautoradio, self.gksudoradio, self.kdesuradio,
|
sudo_list = [self.sudoautoradio, self.gksudoradio, self.kdesuradio,
|
||||||
self.ktsussradio]
|
self.ktsussradio]
|
||||||
self._setup_external_app_radios(sudo_list, daemon.GetSudoApp,
|
self._setup_external_app_radios(sudo_list, daemon.GetSudoApp,
|
||||||
daemon.SetAudoApp)
|
daemon.SetSudoApp)
|
||||||
|
|
||||||
auto_conn_meth = daemon.GetWiredAutoConnectMethod()
|
auto_conn_meth = daemon.GetWiredAutoConnectMethod()
|
||||||
if auto_conn_meth == 1:
|
if auto_conn_meth == 1:
|
||||||
|
|||||||
@@ -44,18 +44,17 @@ def get_gettext():
|
|||||||
lc, encoding = locale.getdefaultlocale(envvars=('LC_MESSAGES',
|
lc, encoding = locale.getdefaultlocale(envvars=('LC_MESSAGES',
|
||||||
'LC_ALL', 'LANG',
|
'LC_ALL', 'LANG',
|
||||||
'LANGUAGE'))
|
'LANGUAGE'))
|
||||||
|
langs += [lc]
|
||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
print str(e)
|
print str(e)
|
||||||
print "Default locale unavailable, falling back to en_US"
|
print "Default locale unavailable, falling back to en_US"
|
||||||
if (lc):
|
|
||||||
langs += [lc]
|
|
||||||
langs += ["en_US"]
|
langs += ["en_US"]
|
||||||
lang = gettext.translation('wicd', local_path, languages=langs,
|
lang = gettext.translation('wicd', local_path, languages=langs,
|
||||||
fallback=True)
|
fallback=True)
|
||||||
_ = lang.gettext
|
_ = lang.gettext
|
||||||
return _
|
return _
|
||||||
|
|
||||||
# Generated automatically on Sat, 20 Jun 2009 21:58:21 CDT
|
# Generated automatically on Sun, 05 Jul 2009 13:51:18 CDT
|
||||||
_ = get_gettext()
|
_ = get_gettext()
|
||||||
language = {}
|
language = {}
|
||||||
language['resetting_ip_address'] = _('''Resetting IP address...''')
|
language['resetting_ip_address'] = _('''Resetting IP address...''')
|
||||||
@@ -214,7 +213,7 @@ language['connection_established'] = _('''Connection established''')
|
|||||||
language['disconnected'] = _('''Disconnected''')
|
language['disconnected'] = _('''Disconnected''')
|
||||||
language['establishing_connection'] = _('''Establishing connection...''')
|
language['establishing_connection'] = _('''Establishing connection...''')
|
||||||
language['association_failed'] = _('''Connection failed: Could not contact the wireless access point.''')
|
language['association_failed'] = _('''Connection failed: Could not contact the wireless access point.''')
|
||||||
language['access_denied'] = _('''Unable to contact the Wicd daemon due to an access denied error from DBus. Please check your DBus configuration.''')
|
language['access_denied'] = _('''Unable to contact the Wicd daemon due to an access denied error from DBus. Please check that your user is in the $A group.''')
|
||||||
language['disconnecting_active'] = _('''Disconnecting active connections...''')
|
language['disconnecting_active'] = _('''Disconnecting active connections...''')
|
||||||
language['access_denied_wc'] = _('''ERROR: wicd-curses was denied access to the wicd daemon: please check that your user is in the "$A" group.''')
|
language['access_denied_wc'] = _('''ERROR: wicd-curses was denied access to the wicd daemon: please check that your user is in the "$A" group.''')
|
||||||
language['post_disconnect_script'] = _('''Run post-disconnect script''')
|
language['post_disconnect_script'] = _('''Run post-disconnect script''')
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ def catchdbus(func):
|
|||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
except DBusException, e:
|
except DBusException, e:
|
||||||
if e.get_dbus_name() != None and "DBus.Error.AccessDenied" in e.get_dbus_name():
|
if e.get_dbus_name() != None and "DBus.Error.AccessDenied" in e.get_dbus_name():
|
||||||
error(None, language['access_denied'])
|
error(None, language['access_denied'].replace("$A","<b>"+wpath.wicd_group+"</b>"))
|
||||||
#raise
|
#raise
|
||||||
raise DBusException(e)
|
raise DBusException(e)
|
||||||
else:
|
else:
|
||||||
@@ -121,13 +121,15 @@ class TrayIcon(object):
|
|||||||
Base Class for implementing a tray icon to display network status.
|
Base Class for implementing a tray icon to display network status.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, animate):
|
def __init__(self, animate, displaytray=True):
|
||||||
if USE_EGG:
|
if USE_EGG:
|
||||||
self.tr = self.EggTrayIconGUI()
|
self.tr = self.EggTrayIconGUI()
|
||||||
else:
|
else:
|
||||||
self.tr = self.StatusTrayIconGUI()
|
self.tr = self.StatusTrayIconGUI()
|
||||||
self.icon_info = self.TrayConnectionInfo(self.tr, animate)
|
self.icon_info = self.TrayConnectionInfo(self.tr, animate)
|
||||||
self.tr.icon_info = self.icon_info
|
self.tr.icon_info = self.icon_info
|
||||||
|
print 'displaytray %s' % displaytray
|
||||||
|
self.tr.visible(displaytray)
|
||||||
|
|
||||||
def is_embedded(self):
|
def is_embedded(self):
|
||||||
if USE_EGG:
|
if USE_EGG:
|
||||||
@@ -666,6 +668,18 @@ class TrayIcon(object):
|
|||||||
"""
|
"""
|
||||||
self.tooltip.set_tip(self.eb, val)
|
self.tooltip.set_tip(self.eb, val)
|
||||||
|
|
||||||
|
def visible(self, val):
|
||||||
|
""" Set if the icon is visible or not.
|
||||||
|
|
||||||
|
If val is True, makes the icon visible, if val is False,
|
||||||
|
hides the tray icon.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if val:
|
||||||
|
self.tray.show_all()
|
||||||
|
else:
|
||||||
|
self.tray.hide_all()
|
||||||
|
|
||||||
|
|
||||||
if hasattr(gtk, "StatusIcon"):
|
if hasattr(gtk, "StatusIcon"):
|
||||||
class StatusTrayIconGUI(gtk.StatusIcon, TrayIconGUI):
|
class StatusTrayIconGUI(gtk.StatusIcon, TrayIconGUI):
|
||||||
@@ -696,6 +710,14 @@ class TrayIcon(object):
|
|||||||
self.current_icon_path = path
|
self.current_icon_path = path
|
||||||
gtk.StatusIcon.set_from_file(self, path)
|
gtk.StatusIcon.set_from_file(self, path)
|
||||||
|
|
||||||
|
def visible(self, val):
|
||||||
|
""" Set if the icon is visible or not.
|
||||||
|
|
||||||
|
If val is True, makes the icon visible, if val is False,
|
||||||
|
hides the tray icon.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.set_visible(val)
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
""" Print usage information. """
|
""" Print usage information. """
|
||||||
@@ -707,6 +729,7 @@ Arguments:
|
|||||||
\t-n\t--no-tray\tRun wicd without the tray icon.
|
\t-n\t--no-tray\tRun wicd without the tray icon.
|
||||||
\t-h\t--help\t\tPrint this help information.
|
\t-h\t--help\t\tPrint this help information.
|
||||||
\t-a\t--no-animate\tRun the tray without network traffic tray animations.
|
\t-a\t--no-animate\tRun the tray without network traffic tray animations.
|
||||||
|
\t-o\t--only-notifications\tDon't display anything except notifications.
|
||||||
""" % wpath.version
|
""" % wpath.version
|
||||||
|
|
||||||
def setup_dbus(force=True):
|
def setup_dbus(force=True):
|
||||||
@@ -764,8 +787,9 @@ def main(argv):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'nha', ['help', 'no-tray',
|
opts, args = getopt.getopt(sys.argv[1:], 'nhao', ['help', 'no-tray',
|
||||||
'no-animate'])
|
'no-animate',
|
||||||
|
'only-notifications'])
|
||||||
except getopt.GetoptError:
|
except getopt.GetoptError:
|
||||||
# Print help information and exit
|
# Print help information and exit
|
||||||
usage()
|
usage()
|
||||||
@@ -773,6 +797,7 @@ def main(argv):
|
|||||||
|
|
||||||
use_tray = True
|
use_tray = True
|
||||||
animate = True
|
animate = True
|
||||||
|
display_app = True
|
||||||
for opt, a in opts:
|
for opt, a in opts:
|
||||||
if opt in ('-h', '--help'):
|
if opt in ('-h', '--help'):
|
||||||
usage()
|
usage()
|
||||||
@@ -781,6 +806,10 @@ def main(argv):
|
|||||||
use_tray = False
|
use_tray = False
|
||||||
elif opt in ('-a', '--no-animate'):
|
elif opt in ('-a', '--no-animate'):
|
||||||
animate = False
|
animate = False
|
||||||
|
elif opt in ('-o', '--only-notifications'):
|
||||||
|
print "only displaying notifications"
|
||||||
|
use_tray = False
|
||||||
|
display_app = False
|
||||||
else:
|
else:
|
||||||
usage()
|
usage()
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
@@ -789,14 +818,14 @@ def main(argv):
|
|||||||
setup_dbus()
|
setup_dbus()
|
||||||
atexit.register(on_exit)
|
atexit.register(on_exit)
|
||||||
|
|
||||||
if not use_tray or not ICON_AVAIL:
|
if display_app and not use_tray or not ICON_AVAIL:
|
||||||
the_gui = gui.appGui(standalone=True)
|
the_gui = gui.appGui(standalone=True)
|
||||||
mainloop = gobject.MainLoop()
|
mainloop = gobject.MainLoop()
|
||||||
mainloop.run()
|
mainloop.run()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Set up the tray icon GUI and backend
|
# Set up the tray icon GUI and backend
|
||||||
tray_icon = TrayIcon(animate)
|
tray_icon = TrayIcon(animate, displaytray=display_app)
|
||||||
|
|
||||||
# Check to see if wired profile chooser was called before icon
|
# Check to see if wired profile chooser was called before icon
|
||||||
# was launched (typically happens on startup or daemon restart).
|
# was launched (typically happens on startup or daemon restart).
|
||||||
|
|||||||
@@ -1055,14 +1055,14 @@ class WirelessDaemon(dbus.service.Object):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
@dbus.service.method('org.wicd.daemon.wireless')
|
@dbus.service.method('org.wicd.daemon.wireless')
|
||||||
def SetWirelessProperty(self, networkid, property, value):
|
def SetWirelessProperty(self, netid, prop, value):
|
||||||
""" Sets property to value in network specified. """
|
""" Sets property to value in network specified. """
|
||||||
# We don't write script settings here.
|
# We don't write script settings here.
|
||||||
if (property.strip()).endswith("script"):
|
if (prop.strip()).endswith("script"):
|
||||||
print "Setting script properties through the daemon is not" \
|
print "Setting script properties through the daemon is not" \
|
||||||
+ " permitted."
|
+ " permitted."
|
||||||
return False
|
return False
|
||||||
self.LastScan[networkid][property] = misc.Noneify(value)
|
self.LastScan[netid][prop] = misc.to_unicode(misc.Noneify(value))
|
||||||
|
|
||||||
@dbus.service.method('org.wicd.daemon.wireless')
|
@dbus.service.method('org.wicd.daemon.wireless')
|
||||||
def DetectWirelessInterface(self):
|
def DetectWirelessInterface(self):
|
||||||
@@ -1201,6 +1201,8 @@ class WirelessDaemon(dbus.service.Object):
|
|||||||
if cur_network["hidden"]:
|
if cur_network["hidden"]:
|
||||||
if cur_network.get("essid") in ["", "Hidden", "<hidden>", None]:
|
if cur_network.get("essid") in ["", "Hidden", "<hidden>", None]:
|
||||||
cur_network["essid"] = "<hidden>"
|
cur_network["essid"] = "<hidden>"
|
||||||
|
else:
|
||||||
|
cur_network['essid'] = self.config.get(section, 'essid')
|
||||||
return "100: Loaded Profile"
|
return "100: Loaded Profile"
|
||||||
|
|
||||||
@dbus.service.method('org.wicd.daemon.wireless')
|
@dbus.service.method('org.wicd.daemon.wireless')
|
||||||
@@ -1373,7 +1375,7 @@ class WiredDaemon(dbus.service.Object):
|
|||||||
print "Setting script properties through the daemon" \
|
print "Setting script properties through the daemon" \
|
||||||
+ " is not permitted."
|
+ " is not permitted."
|
||||||
return False
|
return False
|
||||||
self.WiredNetwork[property] = misc.Noneify(value)
|
self.WiredNetwork[property] = misc.to_unicode(misc.Noneify(value))
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print 'SetWiredProperty: WiredNetwork does not exist'
|
print 'SetWiredProperty: WiredNetwork does not exist'
|
||||||
@@ -1506,8 +1508,10 @@ class WiredDaemon(dbus.service.Object):
|
|||||||
if not self.config.has_option(prof, script):
|
if not self.config.has_option(prof, script):
|
||||||
self.config.set(prof, script, None)
|
self.config.set(prof, script, None)
|
||||||
|
|
||||||
if profilename == "":
|
profilename = profilename.strip()
|
||||||
|
if not profilename:
|
||||||
self.config.write()
|
self.config.write()
|
||||||
|
print "Warning: Bad wired profile name given, ignoring."
|
||||||
return "500: Bad Profile name"
|
return "500: Bad Profile name"
|
||||||
if self.debug_mode:
|
if self.debug_mode:
|
||||||
print "saving wired profile %s" % profilename
|
print "saving wired profile %s" % profilename
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ def neediface(default_response):
|
|||||||
"""
|
"""
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
def newfunc(self, *args, **kwargs):
|
def newfunc(self, *args, **kwargs):
|
||||||
if not self.iface:
|
if not self.iface or \
|
||||||
|
not os.path.exists('/sys/class/net/%s' % self.iface):
|
||||||
return default_response
|
return default_response
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
newfunc.__dict__ = func.__dict__
|
newfunc.__dict__ = func.__dict__
|
||||||
|
|||||||
Reference in New Issue
Block a user