Commit d3689666 authored by Danial Behzadi's avatar Danial Behzadi
Browse files

Setup Debian packaging

parent 9a3d0a83
# Carburetor
This is a graphical settings app for tractor which is a package uses Python stem library to provide a connection through the onion proxy and sets up proxy in user session, so you don't have to mess up with TOR on your system anymore.
## Install
In Debian based distros, make sure that you have `software-properties-common` package installed an then do as following:
sudo add-apt-repository ppa:tractor-team/tractor
sudo apt update
sudo apt install carburetor
If you are using a distro other than Ubuntu, please check if the release name in the relevant file located in `/etc/apt/sources.list.d/` is a supported one (e.g. bionic).
If your distro is not Debian based or you don't want to use PPA, just copy `carburetor` file to `/usr/bin/` directory, but note that you will miss the updates to it. However you are welcome in contirbuting package build recepie of your distro to carburetor.
## Run
you can run `carburetor` by command line for now, but a `.desktop` file is on the way for launching it through desktop environment.
misc:Depends=
misc:Pre-Depends=
Package: carburetor
Version: 1.0-1
Architecture: all
Maintainer: Danial Behzadi <dani.behzi@ubuntu.com>
Installed-Size: 25
Depends: traktor (>= 1.4), python3, python3-gi, python3-gi-cairo, gir1.2-gtk-3.0, python3-notify2
Section: net
Priority: optional
Description: Settings app for Tractor
This package is a graphical settings for tractor
which is an app using Python stem to provide
a connection through the onion proxy and sets up
proxy in user session, so you don't have to mess
up with TOR on your system anymore.
d968eb3f02c8eaf5f0ae4e6693992936 usr/bin/carburetor
3c7869980af3268998ee04b172699586 usr/share/doc/carburetor/changelog.Debian.gz
b59e393d1d760753c622b8665b3c0e09 usr/share/doc/carburetor/copyright
af8a3bd4714cc2239bfa9f04074a7c85 usr/share/man/man1/carburetor.1.gz
#! /usr/bin/env python3
# 2018 - Danial Behzadi
# Released under GPLv3+
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gio, Gtk, GLib
import notify2
import os
import re
from subprocess import PIPE, Popen
command = "traktor "
dconf = Gio.Settings.new("org.tractor")
notify2.init('Carburetor')
class Label(Gtk.Label):
def __init__(self):
Gtk.Label.__init__(self)
#self.props.margin = 5
class ToolButton(Gtk.ToolButton):
def is_running(self):
check = Popen(command + "isrunning", stdout=PIPE, shell=True)
output = check.stdout.read()
if "True" in str(output):
return True
else:
return False
class VBox(Gtk.VBox):
def __init__(self):
Gtk.VBox.__init__(self)
separator = Gtk.Box()
self.pack_start(separator, True, True, 0)
separator = Gtk.Box()
self.pack_end(separator, True, True, 0)
class StartButton(ToolButton):
def __init__(self):
Gtk.ToolButton.__init__(self)
self.update_label(firstrun=True)
self.connect("clicked", self.on_start_clicked)
def update_label(self, firstrun=False):
if self.is_running():
self.set_tooltip_text("Stop")
self.set_label("Stop")
self.props.icon_name = "media-playback-stop"
notif = notify2.Notification("Carburetor", "Tractor is running")
else:
self.set_label("Start")
self.set_tooltip_text("Start")
self.props.icon_name = "media-playback-start"
notif = notify2.Notification("Carburetor", "Tractor is stopped")
notif.set_timeout(notify2.EXPIRES_DEFAULT)
if not firstrun:
notif.show()
else:
notif.close()
def on_start_clicked(self, button):
if self.is_running():
stop = Popen(command + "stop", stdout=PIPE, shell=True)
stop.wait()
else:
start = Popen(command + "start", stdout=PIPE, shell=True)
start.wait()
self.update_label()
class SetButton(ToolButton):
def __init__(self):
Gtk.ToolButton.__init__(self)
self.update_label()
self.connect("clicked", self.on_set_clicked)
def update_label(self):
proxy = Gio.Settings.new("org.gnome.system.proxy")
socks = Gio.Settings.new("org.gnome.system.proxy.socks")
if dconf.get_boolean("accept-connection"):
ip = "0.0.0.0"
else:
ip = "127.0.0.1"
if proxy.get_string("mode") == "manual" and socks.get_int("port") == dconf.get_int("socks-port") and socks.get_string("host") == ip:
self.set_tooltip_text("Unset Proxy")
self.set_label("Unset Proxy")
self.props.icon_name="network-error"
else:
self.set_tooltip_text("Set Proxy")
self.set_label("Set Proxy")
self.props.icon_name="network-transmit-receive"
def on_set_clicked(self, button):
proxy = Gio.Settings.new("org.gnome.system.proxy")
socks = Gio.Settings.new("org.gnome.system.proxy.socks")
if dconf.get_boolean("accept-connection"):
ip = "0.0.0.0"
else:
ip = "127.0.0.1"
if proxy.get_string("mode") == "manual" and socks.get_int("port") == dconf.get_int("socks-port") and socks.get_string("host") == ip:
unset = Popen(command + "unset", stdout=PIPE, shell=True)
unset.wait()
else:
pset = Popen(command + "set", stdout=PIPE, shell=True)
pset.wait()
self.update_label()
class NewidButton(ToolButton):
def __init__(self):
Gtk.ToolButton.__init__(self)
self.set_tooltip_text("New ID")
self.set_label("New ID")
self.props.icon_name = "view-refresh"
self.connect("clicked", self.on_newid_clicked)
def on_newid_clicked(self, button):
if self.is_running():
newid = Popen(command + "newid", stdout=PIPE, shell=True)
newid.wait()
notif = notify2.Notification("Carburetor", "You have a new identity!")
else:
notif = notify2.Notification("Carburetor", "Tractor is not running!")
notif.set_timeout(notify2.EXPIRES_DEFAULT)
notif.show()
class HeaderBar(Gtk.HeaderBar):
def __init__(self):
Gtk.HeaderBar.__init__(self)
self.set_show_close_button(True)
title = "Carburetor"
subtitle = "Settings for Tractor"
self.props.title = title
self.props.subtitle = subtitle
button = StartButton()
self.pack_start(button)
button = SetButton()
self.pack_start(button)
button = NewidButton()
self.pack_start(button)
class SocksPort(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.set_homogeneous(False)
vbox = VBox()
vbox.set_homogeneous(False)
label = Label()
label.set_markup("<b>Socks Port</b>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
label = Label()
label.set_markup("<small>Local port on which Tractor would be listen</small>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
self.pack_start(vbox, True, True, 0)
vbox = VBox()
vbox.set_homogeneous(False)
spin = Gtk.SpinButton()
port = dconf.get_int("socks-port")
adjustment = Gtk.Adjustment(port, 1, 65535, 1, 1, 0)
spin.set_adjustment(adjustment)
spin.set_text(str(port))
dconf.bind("socks-port", spin, "value", Gio.SettingsBindFlags.DEFAULT)
vbox.pack_start(spin, False, False, 0)
self.pack_start(vbox, False, True, 0)
class DNSPort(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.set_homogeneous(False)
vbox = VBox()
vbox.set_homogeneous(False)
label = Label()
label.set_markup("<b>DNS Port</b>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
label = Label()
label.set_markup("<small>Local port on which you would have an anonymous name server</small>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
self.pack_start(vbox, True, True, 0)
vbox = VBox()
vbox.set_homogeneous(False)
spin = Gtk.SpinButton()
port = dconf.get_int("dns-port")
adjustment = Gtk.Adjustment(port, 1, 65535, 1, 1, 0)
spin.set_adjustment(adjustment)
spin.set_text(str(port))
dconf.bind("dns-port", spin, "value", Gio.SettingsBindFlags.DEFAULT)
vbox.pack_start(spin, False, False, 0)
self.pack_start(vbox, False, True, 0)
class AcceptConnection(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.set_homogeneous(False)
vbox = VBox()
vbox.set_homogeneous(False)
label = Label()
label.set_markup("<b>Accept connection</b>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
label = Label()
label.set_markup("<small>Whether or not allowing external devices to use this network</small>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
self.pack_start(vbox, True, True, 0)
vbox = VBox()
vbox.set_homogeneous(False)
switch = Gtk.Switch.new()
dconf.bind("accept-connection", switch, "active", Gio.SettingsBindFlags.DEFAULT)
vbox.pack_start(switch, False, False, 0)
self.pack_start(vbox, False, True, 0)
class BridgeConfig(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.set_homogeneous(False)
vbox = VBox()
vbox.set_homogeneous(False)
label = Label()
label.set_markup("<b>Use bridges</b>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
label = Label()
label.set_markup("<small>Bridges help you to bypass tor sensorship</small>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
self.pack_start(vbox, True, True, 0)
vbox = VBox()
vbox.set_homogeneous(False)
switch = Gtk.Switch.new()
dconf.bind("use-bridges", switch, "active", Gio.SettingsBindFlags.DEFAULT)
vbox.pack_start(switch, False, False, 0)
self.pack_start(vbox, False, True, 0)
class BridgeList(Gtk.Box):
config_dir = GLib.get_user_config_dir() + "/traktor"
def __init__(self):
Gtk.Box.__init__(self)
self.set_homogeneous(False)
vbox = VBox()
vbox.set_homogeneous(False)
label = Label()
label.set_text("Bridges:")
vbox.pack_start(label, False, False, 0)
self.pack_start(vbox, False, False, 0)
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_min_content_height(150)
text_view = Gtk.TextView()
text_view.set_wrap_mode(1)
text_buffer = text_view.get_buffer()
bridges_file = self.config_dir + "/Bridges"
if not os.path.isfile(bridges_file):
bridges_file = [skel_path for skel_path in GLib.get_system_data_dirs() if os.path.exists(skel_path) and "traktor" in os.listdir(skel_path)][-1]+"/traktor/SampleBridges"
with open(bridges_file) as file:
text = file.read()
text_buffer.set_text(str(text))
scrolled_window.add(text_view)
self.pack_start(scrolled_window, True, True, 0)
vbox = VBox()
vbox.set_homogeneous(False)
button = Gtk.Button()
button.set_label("Save")
button.connect("clicked", self.on_save_clicked, text_buffer)
vbox.pack_start(button, False, False, 0)
self.pack_start(vbox, False, False, 0)
def on_save_clicked(self, button, text_buffer):
bridges_file = self.config_dir + "/Bridges"
text = text_buffer.get_text(text_buffer.get_start_iter(), text_buffer.get_end_iter(), 0)
bridge_regex = re.compile(r'^( )*([Bb][Rr][Ii][Dd][Gg][Ee])?( )*', re.MULTILINE)
if text == bridge_regex.sub('Bridge ', text):
if not os.path.exists(self.config_dir):
os.makedirs(self.config_dir)
with open(bridges_file, 'w') as file:
file.write(text)
else:
window = self.get_toplevel()
dialog = Gtk.MessageDialog(window, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Can not save the bridges", )
dialog.format_secondary_markup("Please check the syntax of bridges")
response = dialog.run()
if -6 < response < -3:
dialog.close()
class ObfsPath (Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.set_homogeneous(False)
vbox = VBox()
vbox.set_homogeneous(False)
label = Label()
label.set_markup("<b>obfs4proxy executable</b>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
label = Label()
label.set_markup("<small>You should specify where is obfs4proxy file</small>")
label.set_xalign(0)
vbox.pack_start(label, False, False, 0)
self.pack_start(vbox, True, True, 0)
vbox = VBox()
chooser = Gtk.FileChooserButton()
current_file = Gio.File.new_for_path(dconf.get_string("obfs4-path"))
chooser.set_file(current_file)
chooser.connect("file-set", self.on_file_set)
vbox.pack_start(chooser, False, False, 0)
self.pack_start(vbox, True, True, 0)
def on_file_set(self, chooser):
filename = chooser.get_filename()
dconf.set_string("obfs4-path", filename)
class MainContainer(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.set_spacing(5)
separator = Gtk.VBox()
self.pack_start(separator, True, True, 0)
separator = Gtk.VBox()
self.pack_end(separator, True, True, 0)
def main():
window = Gtk.Window()
header_bar = HeaderBar()
window.set_titlebar(header_bar)
main_container = MainContainer()
main_box = Gtk.VBox()
main_box.set_spacing(10)
socks_port_box = SocksPort()
main_box.pack_start(socks_port_box, False, False, 0)
dns_port_box = DNSPort()
main_box.pack_start(dns_port_box, False, False, 0)
accept_connection_box = AcceptConnection()
main_box.pack_start(accept_connection_box, False, False, 0)
bridge_config_box = BridgeConfig()
main_box.pack_start(bridge_config_box, False, False, 0)
bridge_list_box = BridgeList()
main_box.pack_start(bridge_list_box, False, False, 0)
obfs_path_box = ObfsPath()
main_box.pack_start(obfs_path_box, False, False, 0)
main_container.pack_start(main_box, False, False, 0)
window.add(main_container)
window.connect('destroy', Gtk.main_quit)
window.show_all()
Gtk.main()
if __name__ == "__main__":
main()
Carburetor - Settings app for Tractor
Copyright 2018 Danial Behzadi <dani.behzi@ubuntu.com>
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://gitlab.com/tractor-team/carburetor
License: GPL-3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-3".
carburetor (1.0-1) bionic; urgency=medium
* Initial release.
-- Danial Behzadi <dani.behzi@ubuntu.com> Thu, 19 Jul 2018 01:30:00 +0430
Source: carburetor
Maintainer: Danial Behzadi <dani.behzi@ubuntu.com>
Section: net
Priority: optional
Standards-Version: 3.9.8
Build-Depends: debhelper (>=9)
Package: carburetor
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, traktor (>=1.4), python3, python3-gi, python3-gi-cairo, gir1.2-gtk-3.0, python3-notify2
Description: Settings app for Tractor
This package is a graphical settings for tractor
which is an app using Python stem to provide
a connection through the onion proxy and sets up
proxy in user session, so you don't have to mess
up with TOR on your system anymore.
Carburetor - Settings app for Tractor
Copyright 2018 Danial Behzadi <dani.behzi@ubuntu.com>
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://gitlab.com/tractor-team/carburetor
License: GPL-3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-3".
carburetor_1.0-1_all.deb net optional
carburetor_1.0-1_amd64.buildinfo net optional
carburetor usr/bin
#!/usr/bin/make -f
export DH_VERBOSE=1
%:
dh $@ --with-python3
.\" Manpage for carburetor
.\" Contact dani.behzi@ubuntu.com to correct errors or typos.
.TH man 1 "19 Jul 2018" "1.4" "carburetor man page"
.SH NAME
carburetor \- Settings for traktr
.SH SYNOPSIS
carburetor
.SH DESCRIPTION
This is a graphical settings app for tractor which is a package uses Python stem library to provide a connection through the onion proxy and sets up proxy in user session, so you don't have to mess up with TOR on your system anymore.
.SH AUTHOR
Danial Behzadi (dani.behzi@ubuntu.com)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment