first commit, ARGGGGGH!

master
Chris Punches 2018-10-07 23:08:35 -04:00
commit 277feac742
13 changed files with 1020 additions and 0 deletions

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# Scallywag
Any swashbuckler's favorite tool.
# Purpose
A piratebay browser that deliberately circumvents processor-sharing exploitation being sent to browsers.
# Not Purpose
Not a tool to steal things with. Magnet links and torrents are a perfectly valid technology and must be used responsibly by the user.

156
Scallywag Executable file
View File

@ -0,0 +1,156 @@
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
from rsrc.Scraper import proxylister, searcher
from configparser import ConfigParser
import subprocess
class Config:
def __init__(self, config_file):
settings = ConfigParser(allow_no_value=True)
settings.read(config_file)
# the url used to list out proxies
self.proxylist_url = settings.get("list_source", "piratebay_proxy_list")
class Scallywag:
def on_btnRefresh_clicked( self, object, data=None ):
self.status("refresh pressed")
def on_btnSearch_clicked( self, object, data=None ):
self.status("search pressed")
# clear the results_store
# seeders, leechers, size, name
self.results_store.clear()
for row in self.results_store:
self.results_store.remove(row)
# prove to me that the results_store is populated
for row in self.results_store:
print(row[:])
for column in self.results_tree_view.get_columns():
self.results_tree_view.remove_column(column)
# associate new results_store with the treeview
self.results_tree_view.set_model(self.results_store)
# add search result entries to the results store
# TODO add retrieval from search textentry
search_field = self.builder.get_object("txtSearch")
search_terms = search_field.get_text()
for result in self.get_results( search_terms ):
print( result.__str__() )
self.results_store.append( [ result.seeders, result.leechers, result.size, result.title, result.author, result.url ])
# prove to me that the results_store is populated
for row in self.results_store:
print(row[:])
for i, col_title in enumerate( [ "Seeders", "Leechers", "Size", "Title", "Author", "Url" ] ):
# renderer creation
renderer = Gtk.CellRendererText()
# text is column number
column = Gtk.TreeViewColumn(col_title, renderer, text=i)
# add column to tvw
self.results_tree_view.append_column(column)
def get_current_proxy(self):
return self.mnuPulldown.get_active_text()
def on_mnuPulldown_changed(self, object, data=None ):
new_proxy = self.get_current_proxy()
self.config.proxy = new_proxy
self.status( str.format( "Changed PirateBay proxy site to {0}", self.config.proxy ) )
def get_results(self, search_terms):
self.searcher = searcher.Scraper( self.config )
results = self.searcher.get_results( search_terms )
for result in results:
yield result
def on_btnDownload_clicked( self, object, data=None, **args ):
selection = self.results_tree_view.get_selection()
(tm, ti) = selection.get_selected()
url = tm.get_value(ti, 5)
# TODO scrape url for magnet link then pass to xdg-open
magnet = self.searcher.get_magnet( url )
subprocess.call(["xdg-open", magnet])
self.status("Opening Magnet with xdg-open...")
def status( self, msg ):
# GTK team, your API is bullshit.
self.statusbar.push( self.statusbar.get_context_id("stsBar"), msg )
def on_winMain_destroy(self, object, data=None):
print("quit by exiting")
Gtk.main_quit()
def __init__(self, configFile):
self.config = Config( configFile )
self.gladefile = "./rsrc/gui/winMain.glade"
self.builder = Gtk.Builder()
self.builder.add_from_file(self.gladefile)
self.builder.connect_signals(self)
self.window = self.builder.get_object("winMain")
self.statusbar = self.builder.get_object("stsBar")
self.status("Choose your PirateBay Proxy")
self.mnuPulldown = self.builder.get_object("mnuPulldown")
self.proxy_store = Gtk.ListStore(str)
self.mnuPulldown.set_model(self.proxy_store)
self.proxylister = proxylister.Scraper( self.config )
for proxy in self.proxylister.get_proxies():
self.proxy_store.append([proxy])
self.mnuPulldown.set_active(0)
self.results_store = Gtk.ListStore(int, int, str, str, str, str)
self.window.set_focus(self.builder.get_object("txtSearch"))
# treeview
self.results_tree_view = self.builder.get_object("tvwResults")
# wtf. why doesn't this work?
self.results_tree_view.connect("row-activated", self.on_btnDownload_clicked )
self.window.show_all()
if __name__ == "__main__":
main = Scallywag("config.ini")
Gtk.main()

2
config.ini Normal file
View File

@ -0,0 +1,2 @@
[list_source]
piratebay_proxy_list = thepiratebay-proxylist.se

0
rsrc/Scraper/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,33 @@
import requests
from lxml import html
class Scraper:
def __init__( self, config ):
# the request client, belongs to session even if no "user session" is needed
self.client = requests.Session()
self.config = config
def get_proxies(self):
fetch_results = self.client.get( "https://" + self.config.proxylist_url )
proxy_list = self.Parser.scrape( "proxy_list", fetch_results.content )
return proxy_list
class Parser:
@staticmethod
def scrape( datapoint, text ):
cases = {
"proxy_list": Scraper.Parser.proxy_list
}
return cases[ datapoint ]( text )
@staticmethod
def proxy_list( text ):
proxyTable = html.fromstring( text )
proxyTable_xpath = proxyTable.xpath( '//table[@class="proxies"]/tbody/tr/@data-domain' )
return proxyTable_xpath
class SessionError( Exception ):
def __init__( self, value ):
self.value = value

108
rsrc/Scraper/searcher.py Normal file
View File

@ -0,0 +1,108 @@
import requests
from lxml import html
import urllib
import re
import json
class Result:
def __init__(self, title, seeders, leechers, size, author, url):
self.title = str(title)
self.seeders = int(seeders)
self.leechers = int(leechers)
self.size = str(size)
self.author = str(author)
self.url = str(url)
def __str__(self):
myjson = {}
myjson['title'] = self.title
myjson['seeders'] = self.seeders
myjson['leechers'] = self.leechers
myjson['size'] = self.size
myjson['author'] = self.author
myjson['url'] = self.url
return json.dumps(myjson)
class Scraper:
def __init__( self, config ):
# the request client, belongs to session even if no "user session" is needed
self.client = requests.Session()
self.config = config
def craft_url(self, protocol, proxy, search_terms):
# https://pirate.blue/s/?q=Raising+Arizona&category=0&page=0&orderby=99
f = { 'q': search_terms, 'category': 0, 'page': 0, 'orderby': 99 }
return str.format( "{0}://{1}/s/?{2}", protocol, proxy, urllib.parse.urlencode(f) )
def get_results(self, search_terms):
print("Fetching from")
print(self.config.proxy)
url = self.craft_url( "https", self.config.proxy, search_terms )
fetch_results = self.client.get( url )
results_list = self.Parser.scrape( "results_list", fetch_results.content )
return results_list
def get_magnet(self, url):
url = "https://" + self.config.proxy + url
fetch_results = self.client.get(url)
magnet = self.Parser.scrape( "magnet_link", fetch_results.content )
return magnet
class Parser:
@staticmethod
def scrape( datapoint, text ):
cases = {
"results_list": Scraper.Parser.results_list,
"magnet_link": Scraper.Parser.magnet_link
}
return cases[ datapoint ]( text )
@staticmethod
def results_list( text ):
resultsTable = html.fromstring( text )
resultsTable_xpath = resultsTable.xpath( '//table[@id="searchResult"]/tr' )
results_buffer = list()
for tr in resultsTable_xpath:
title = tr.xpath('td[2]/div[1]/a[1]/text()')[0]
seeders = tr.xpath('td[3]/text()')[0]
leechers = tr.xpath('td[4]/text()')[0]
author = tr.xpath('td[2]/font/a/text()')[0]
size_unprocessed = tr.xpath('td[2]/font/text()')[0]
url = tr.xpath('td/div[@class="detName"]/a[@class="detLink"]/@href')[0]
m = re.search('Size (.+?),', size_unprocessed)
if m:
size = m.group(1)
results_buffer.append(
Result(title, seeders, leechers, size, author, url)
)
return results_buffer
@staticmethod
def magnet_link( text ):
link_page = html.fromstring( text )
magnet_link = link_page.xpath('//div[@class="download"]/a/@href')[0]
return magnet_link
class SessionError( Exception ):
def __init__( self, value ):
self.value = value

211
rsrc/gui/#winMain.glade# Normal file
View File

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.4 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="winMain">
<property name="name">winMain</property>
<property name="can_focus">False</property>
<property name="default_width">500</property>
<property name="default_height">600</property>
<signal name="destroy" handler="on_winMain_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="boxMain">
<property name="name">boxMain</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBoxText" id="mnuPulldown">
<property name="name">mnuPulldown</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<signal name="changed" handler="on_mnuPulldown_changed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnRefresh">
<property name="label">gtk-refresh</property>
<property name="name">btnRefresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_btnRefresh_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="stsBar">
<property name="name">stsBar</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_start">10</property>
<property name="margin_end">10</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="hexpand">True</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnDownload">
<property name="label" translatable="yes">Open in Client</property>
<property name="name">btnDownload</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_btnDownload_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scwResults">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTreeView" id="tvwResults">
<property name="name">tvwResults</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkBox" id="boxSearch">
<property name="name">boxSearch</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="txtSearch">
<property name="name">txtSearch</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="is_focus">True</property>
<property name="has_default">True</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="activates_default">True</property>
<signal name="activate" handler="on_btnSearch_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnSearch">
<property name="label">gtk-find</property>
<property name="name">btnSearch</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="margin_right">6</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_btnSearch_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.4 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow">
<property name="can_focus">False</property>
<property name="default_width">440</property>
<property name="default_height">250</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="lblLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Select a PirateBay Proxy</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBox" id="mnuPulldown">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnSelect">
<property name="label" translatable="yes">Select</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnRefresh">
<property name="label" translatable="yes">Refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child>
<placeholder/>
</child>
</object>
</interface>

212
rsrc/gui/winMain.glade Normal file
View File

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.4 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="winMain">
<property name="name">winMain</property>
<property name="can_focus">False</property>
<property name="default_width">500</property>
<property name="default_height">600</property>
<signal name="destroy" handler="on_winMain_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="boxMain">
<property name="name">boxMain</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBoxText" id="mnuPulldown">
<property name="name">mnuPulldown</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<signal name="changed" handler="on_mnuPulldown_changed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnRefresh">
<property name="label">gtk-refresh</property>
<property name="name">btnRefresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_btnRefresh_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="stsBar">
<property name="name">stsBar</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_start">10</property>
<property name="margin_end">10</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="hexpand">True</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnDownload">
<property name="label" translatable="yes">Open in Client</property>
<property name="name">btnDownload</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_btnDownload_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scwResults">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTreeView" id="tvwResults">
<property name="name">tvwResults</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="row-activated" handler="on_btnDownload_clicked" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkBox" id="boxSearch">
<property name="name">boxSearch</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="txtSearch">
<property name="name">txtSearch</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="is_focus">True</property>
<property name="has_default">True</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="activates_default">True</property>
<signal name="activate" handler="on_btnSearch_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnSearch">
<property name="label">gtk-find</property>
<property name="name">btnSearch</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="margin_right">6</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_btnSearch_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</interface>

210
rsrc/gui/winMain.glade~ Normal file
View File

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.4 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="winMain">
<property name="name">winMain</property>
<property name="can_focus">False</property>
<property name="default_width">500</property>
<property name="default_height">600</property>
<signal name="destroy" handler="on_winMain_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="boxMain">
<property name="name">boxMain</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBoxText" id="mnuPulldown">
<property name="name">mnuPulldown</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<signal name="changed" handler="on_mnuPulldown_changed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnRefresh">
<property name="label">gtk-refresh</property>
<property name="name">btnRefresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_btnRefresh_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="stsBar">
<property name="name">stsBar</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_start">10</property>
<property name="margin_end">10</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="hexpand">True</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnDownload">
<property name="label" translatable="yes">Open in Client</property>
<property name="name">btnDownload</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_btnDownload_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scwResults">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTreeView" id="tvwResults">
<property name="name">tvwResults</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkBox" id="boxSearch">
<property name="name">boxSearch</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkEntry" id="txtSearch">
<property name="name">txtSearch</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="is_focus">True</property>
<property name="has_default">True</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="activates_default">True</property>
<signal name="activate" handler="on_btnSearch_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnSearch">
<property name="label">gtk-find</property>
<property name="name">btnSearch</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="margin_right">6</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_btnSearch_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</interface>