How to convert self join query into PySpark? - sql

I need to convert this SQL code into PySpark:
SELECT
e.emp_id 'Emp_Id', e.emp_name 'Employee', m.emp_id 'Mgr_Id', m.emp_name 'Manager'
FROM
emp e
JOIN
emp m ON (e.manager_id = m.emp_id);
I tried this:
empDF=spark.read.format("jdbc").option("url", host).option("user", user).option("password",pwd).option("dbtable","EMP").load()
df1=empDF.alias("emp1").join(empDF.alias("emp2"), \
col("emp1.manager_id") == col("emp2.emp_id"),"inner") \
.select(col("emp1.emp_id"),col("emp1.name"), \
col("emp2.emp_id").alias("manager_id"), \
col("emp2.name").alias("manager_name")) \
.show(truncate=False)

Try the following:
df1 = (
empDF.alias("emp1")
.join(empDF.alias("emp2"),
col("emp1.manager_id") == col("emp2.emp_id"),
"inner")
.select(
col("emp1.emp_id").alias("Emp_Id"),
col("emp1.emp_name").alias("Employee"),
col("emp2.emp_id").alias("Mgr_Id"),
col("emp2.emp_name").alias("Manager"))
)
df1.show(truncate=False)

Related

Translate SQL UPDATE with multiple INNER JOIN and WHERE into PySpark

I am trying to execute the below code using PySpark:
join_on = (df_1.C1_PROFIT == df_2.C2_PROFIT) & \ # JOIN CONDITION
(df_1.C1_REVENUE == df_3.C3_REVENUE_BREAK) & \ # JOIN CONDITION
(df_1.C1_LOSS == df_4.C4_TOTAL_LOSS) & \ # JOIN CONDITION
((df_4.TOTAL_YEAR_PROFIT) > (df_3.TOTAL_GROWTH)) # WHERE CONDITION
df = (df_1.alias('a')
.join(df_2.alias('b'), join_on, 'left')
.join(df_3.alias('c'), join_on, 'left')
.join(df_4.alias('d'), join_on, 'left')
.select(
*[c for c in df_2.columns if c != 'C2_TARGET'],
F.expr("nvl2(b.C2_PROFIT, '500', a.C2_TARGET) C2_TARGET")
)
)
Error after running the query:
'TOTAL_YEAR_PROFIT','TOTAL_GROWTH', 'TOTAL_LOSS', 'REVENUE_BREAK'
does not exist in df_1 columns:
The original SQL query:
UPDATE (( companyc1
INNER JOIN companyc2
ON company1.c1_profit = company2.c2_profit)
INNER JOIN companyc3
ON company1.c1_revenue = company3.revenue_break)
INNER JOIN companyc4
ON company1.c1_loss = company4.c4_total_loss
SET companyc1.sales = "500"
WHERE (( ( company4.total_year_profit ) > [company3].[total_growth] ))
Can anyone help me find where I am doing the mistake?
Your join_on conditions will have to be split for each of the join operation, like so:
df = (df_1.alias('a')
.join(df_2.alias('b'), df_1.C1_PROFIT == df_2.C2_PROFIT, 'left')
.join(df_3.alias('c'), df_1.C1_REVENUE == df_3.C3_REVENUE_BREAK, 'left')
.join(df_4.alias('d'), df_1.C1_LOSS == df_4.C4_TOTAL_LOSS. 'left')
.select(
*[c for c in df_2.columns if c != 'C2_TARGET'],
F.expr("nvl2(b.C2_PROFIT, '500', a.C2_TARGET) C2_TARGET")
).where("d.TOTAL_YEAR_PROFIT > c.TOTAL_GROWTH")
)
When translating SQL UPDATE containing multiple joins, it seems to me, that the universally safe approach could involve groupBy, agg and monotonically_increasing_id (to make sure that the row number of the original df will not shrink after the aggregation).
I've made the following tables in MS Access, to make sure that the approach I suggest, would work the same way in Spark.
Inputs:
Result after the update:
Spark
It seems, MS Access aggregates column values, so the following will do the same.
Inputs:
from pyspark.sql import functions as F
df_1 = spark.createDataFrame(
[(2, 10, 5, 'replace'),
(2, 10, 5, 'replace'),
(1, 10, None, 'keep'),
(2, None, 5, 'keep')],
['C1_PROFIT', 'C1_REVENUE', 'C1_LOSS', 'SALES']
)
df_2 = spark.createDataFrame([(1,), (2,), (8,)], ['C2_PROFIT'])
df_3 = spark.createDataFrame([(10, 51), (10, 50)], ['REVENUE_BREAK', 'TOTAL_GROWTH'])
df_4 = spark.createDataFrame([(5, 50), (5, 51),], ['C4_TOTAL_LOSS', 'TOTAL_YEAR_PROFIT'])
Script:
df_1 = df_1.withColumn('_id', F.monotonically_increasing_id())
df = (df_1.alias('a')
.join(df_2.alias('b'), df_1.C1_PROFIT == df_2.C2_PROFIT, 'left')
.join(df_3.alias('c'), df_1.C1_REVENUE == df_3.REVENUE_BREAK, 'left')
.join(df_4.alias('d'), df_1.C1_LOSS == df_4.C4_TOTAL_LOSS, 'left')
.groupBy(*[c for c in df_1.columns if c != 'SALES'])
.agg(F.when(F.max('d.total_year_profit') > F.min('c.total_growth'), '500')
.otherwise(F.first('a.SALES')).alias('SALES')
).drop('_id')
)
df.show()
# +---------+----------+-------+-----+
# |C1_PROFIT|C1_REVENUE|C1_LOSS|SALES|
# +---------+----------+-------+-----+
# | 1| 10| null| keep|
# | 2| null| 5| keep|
# | 2| 10| 5| 500|
# | 2| 10| 5| 500|
# +---------+----------+-------+-----+

Create subquery using peewee, using `.select` on the subquery results

I have a rather complex peewee query that looks like that:
SolutionAlias = Solution.alias()
fields = [
SolutionAlias.id.alias('solution_id'),
SolutionAlias.solver.id.alias('solver_id'),
SolutionAlias.exercise.id.alias('exercise_id'),
]
query = (
User
.select(*fields)
.join(Exercise, JOIN.CROSS)
.join(Course, JOIN.LEFT_OUTER, on=(Exercise.course == Course.id))
.join(SolutionAlias, JOIN.LEFT_OUTER, on=(
(SolutionAlias.exercise == Exercise.id)
& (SolutionAlias.solver == User.id)
))
.where(
(Exercise.id << self.get_exercise_ids()),
(User.id << self.get_user_ids()),
)
.group_by(Exercise.id, User.id, SolutionAlias.id)
.having(
(SolutionAlias.id == fn.MAX(SolutionAlias.id))
| (SolutionAlias.id.is_null(True))
)
.alias('solutions_subquery')
)
full_query_fields = [
query.c.solver_id,
query.c.exercise_id,
Solution.id.alias('solution_id'),
SolutionAssessment.icon.alias('assessment_icon'),
]
solutions = (
Solution
.select(*full_query_fields)
.join(query, JOIN.RIGHT_OUTER, on=(
Solution.id == query.c.solution_id
))
.join(SolutionAssessment, JOIN.LEFT_OUTER, on=(
(Solution.assessment == SolutionAssessment.id)
))
)
This one actually works, generating the following SQL query:
SELECT
"solutions_subquery"."solver_id",
"solutions_subquery"."exercise_id",
"t1"."id" AS "solution_id",
"t2"."icon" AS "assessment_icon"
FROM
"solution" AS "t1"
RIGHT OUTER JOIN (
SELECT
"t3"."id" AS "solution_id",
"t4"."id" AS "solver_id",
"t5"."id" AS "exercise_id"
FROM
"user" AS "t4" CROSS
JOIN "exercise" AS "t5"
LEFT OUTER JOIN "course" AS "t6" ON ("t5"."course_id" = "t6"."id")
LEFT OUTER JOIN "solution" AS "t3" ON (
("t3"."exercise_id" = "t5"."id")
AND ("t3"."solver_id" = "t4"."id")
)
WHERE
(
(
"t5"."id" IN (155, 156, 157)
)
AND (
"t4"."id" IN (1, 24, 25, 26, 27, 28)
)
)
GROUP BY
"t5"."id",
"t4"."id",
"t3"."id"
HAVING
(
(
"t3"."id" = MAX("t3"."id")
)
OR ("t3"."id" IS NULL)
)
) AS "solutions_subquery" ON (
"t1"."id" = "solutions_subquery"."solution_id"
)
LEFT OUTER JOIN "solutionassessment" AS "t2" ON ("t1"."assessment_id" = "t2"."id")
But I don't really want to use RIGHT_JOIN as it isn't supported by SQLite.
When trying to query using the subquery query and JOINing the Solution table into the subquery's result, I get an error from peewee.
The new query:
solutions = (
query
.select(*full_query_fields)
.join(Solution, JOIN.LEFT_OUTER, on=(
Solution.id == query.c.solution_id
))
.join(SolutionAssessment, JOIN.LEFT_OUTER, on=(
(Solution.assessment == SolutionAssessment.id)
))
)
The generated query:
SELECT
"solutions_subquery"."solver_id",
"solutions_subquery"."exercise_id",
"t1"."id" AS "solution_id",
"t1"."checker_id",
"t1"."state",
"t1"."submission_timestamp",
"t2"."name" AS "assessment",
"t2"."icon" AS "assessment_icon"
FROM
"user" AS "t3" CROSS
JOIN "exercise" AS "t4"
LEFT OUTER JOIN "course" AS "t5" ON ("t4"."course_id" = "t5"."id")
LEFT OUTER JOIN "solution" AS "t6" ON (
("t6"."exercise_id" = "t4"."id")
AND ("t6"."solver_id" = "t3"."id")
)
LEFT OUTER JOIN "solution" AS "t1" ON (
"t1"."id" = "solutions_subquery"."solution_id"
)
LEFT OUTER JOIN "solutionassessment" AS "t2" ON ("t1"."assessment_id" = "t2"."id")
WHERE
(
(
"t4"."id" IN (155, 156, 157)
)
AND (
"t3"."id" IN (1, 24, 25, 26, 27, 28)
)
)
GROUP BY
"t4"."id",
"t3"."id",
"t6"."id"
HAVING
(
(
"t6"."id" = MAX("t6"."id")
)
OR ("t6"."id" IS NULL)
)
Which results in:
psycopg2.errors.UndefinedTable: missing FROM-clause entry for table "solutions_subquery"
LINE 1: ...EFT OUTER JOIN "solution" AS "t1" ON ("t1"."id" = "solutions...
During handling of the above exception, another exception occurred:
[Truncated for readability...]
loguru.logger.critical(str(list(solutions.dicts().execute())))
[Truncated for readability...]
peewee.ProgrammingError: missing FROM-clause entry for table "solutions_subquery"
LINE 1: ...EFT OUTER JOIN "solution" AS "t1" ON ("t1"."id" = "solutions...
Why does peewee flatten the query? Is there another way to use LEFT_JOIN?
Eventually found the Select function in the documentation, which allows me to kind of wrap the previous query:
solutions = (
Select(columns=full_query_fields)
.from_(query)
.join(Solution, JOIN.LEFT_OUTER, on=(
Solution.id == query.c.solution_id
))
.join(SolutionAssessment, JOIN.LEFT_OUTER, on=(
(Solution.assessment == SolutionAssessment.id)
))
)
This solution works.

left outer join Lambda

All,
I have multiple left outer join from multiple tables.
My SQL query works fine as below:
select distinct
C.CUST_CD, C.DSC, C.BH_PHONE, A.ADDRESS, CITY.DESCR CITY, ZIP.DESCR ZIP,
CSH.UDT_DT , CSR.DSC
from
dbo.CUST C
inner join dbo.CUST_ADDR A on C.CUST_CD = A.CUST_CD and A.ADDR_CD = 5
left outer join dbo.LOCATION CITY on A.CITY_CD = CITY.LOCATION_CD
left outer join dbo.LOCATION ZIP on A.ZIP_CD = ZIP.LOCATION_CD
left outer join dbo.CUST_STS S on C.CUST_STS_CD = S.CUST_STS_CD
left outer join dbo.CUST_STS_HIS CSH on C.CUST_CD = CSH.CUST_CD
left outer join dbo.CUST_STS_REASON CSR on CSH.REASON_CD = CSR.REASON_CD
where
C.CUST_STS_CD in (5)
and CSH.CUST_STS_CD in (5)
and CSR.STS_CD in (5)
order by C.CUST_CD
My Lambda expression looks like this:
var items = (
from a in db.CUSTs
from b in db.CUST_ADDR
.Where(bb => bb.CUST_CD == a.CUST_CD && bb.ADDR_CD ==5)
from c in db.LOCATION
.Where(cc => cc.LOCATION_CD == b.CITY_CD)
.DefaultIfEmpty() // <== makes outer left join
from d in db.LOCATION
.Where(dd => dd.LOCATION_CD == c.LOCATION_CD)
.DefaultIfEmpty()
from e in db.LOCATION
.Where(ee => ee.LOCATION_CD == b.ZIP_CD)
.DefaultIfEmpty()
from f in db.CUST_STS_HIS
.Where(ff => ff.CUST_STS_CD == a.CUST_STS_CD)
.DefaultIfEmpty()
from g in db.CUST_STS_REASON
.Where(gg => gg.STS_CD == f.CUST_STS_CD)
.DefaultIfEmpty()
where (a.CUST_STS_CD == 5 && f.CUST_STS_CD == 5 && g.STS_CD == 5)
select new
{
CUSTCode = a.CUST_CD,
CUSTDesc = a.DSC,
CUSTPhone = a.BH_PHONE,
CUSTAddr = a.ADDRESS,
CUSTCity = c.DESCR,
CUSTZip = d.DESCR,
CUSTCounty = e.DESCR,
Date = f.UDT_DT,
reason = g.DSC
})
.ToList();
Here's the SQL from the Lamda expression:
SELECT
1 AS [C1],
[Filter1].[CUST_CD1] AS [CUST_CD],
[Filter1].[DSC] AS [DSC],
[Filter1].[BH_PHONE] AS [BH_PHONE],
[Filter1].[ADDRESS] AS [ADDRESS],
[Filter1].[DESCR1] AS [DESCR],
[Filter1].[DESCR2] AS [DESCR1],
[Filter1].[DESCR3] AS [DESCR2],
[Filter1].[UDT_DT] AS [UDT_DT],
[Extent7].[DSC] AS [DSC1]
FROM (SELECT [Extent1].[CUST_CD] AS [CUST_CD1], [Extent1].[DSC] AS [DSC], [Extent1].[BH_PHONE] AS [BH_PHONE], [Extent1].[ADDRESS] AS [ADDRESS], [Extent3].[DESCR] AS [DESCR1], [Extent4].[DESCR] AS [DESCR2], [Extent5].[DESCR] AS [DESCR3], [Extent6].[UDT_DT] AS [UDT_DT], [Extent6].[CUST_STS_CD] AS [CUST_STS_CD1]
FROM [DBO].[CUST] AS [Extent1]
INNER JOIN (SELECT
[CUST_ADDR].[CUST_CD] AS [CUST_CD],
[CUST_ADDR].[ADDR_CD] AS [ADDR_CD],
[CUST_ADDR].[ADDRESS] AS [ADDRESS],
[CUST_ADDR].[CITY_CD] AS [CITY_CD],
[CUST_ADDR].[ZIP_CD] AS [ZIP_CD],
[CUST_ADDR].[STATE_CD] AS [STATE_CD],
[CUST_ADDR].[ADDRESS2] AS [ADDRESS2]
FROM [DBO].[CUST_ADDR] AS [CUST_ADDR]) AS [Extent2] ON ([Extent2].[CUST_CD] = [Extent1].[CUST_CD]) AND (cast(5 as decimal(18)) = [Extent2].[ADDR_CD])
LEFT OUTER JOIN [DBO].[LOCATION] AS [Extent3] ON [Extent3].[LOCATION_CD] = [Extent2].[CITY_CD]
LEFT OUTER JOIN [DBO].[LOCATION] AS [Extent4] ON [Extent4].[LOCATION_CD] = [Extent3].[LOCATION_CD]
LEFT OUTER JOIN [DBO].[LOCATION] AS [Extent5] ON [Extent5].[LOCATION_CD] = [Extent2].[ZIP_CD]
INNER JOIN (SELECT
[CUST_STS_HIS].[CUST_CD] AS [CUST_CD],
[CUST_STS_HIS].[UDT_DT] AS [UDT_DT],
[CUST_STS_HIS].[REASON_CD] AS [REASON_CD],
[CUST_STS_HIS].[CUST_STS_CD] AS [CUST_STS_CD],
[CUST_STS_HIS].[USR_ID] AS [USR_ID],
[CUST_STS_HIS].[NOTES] AS [NOTES]
FROM [DBO].[CUST_STS_HIS] AS [CUST_STS_HIS]) AS [Extent6] ON [Extent6].[CUST_STS_CD] = [Extent1].[CUST_STS_CD]
WHERE (cast(5 as decimal(18)) = [Extent1].[CUST_STS_CD]) AND (cast(5 as decimal(18)) = [Extent6].[CUST_STS_CD]) ) AS [Filter1]
INNER JOIN (SELECT
[CUST_STS_REASON].[STS_CD] AS [STS_CD],
[CUST_STS_REASON].[REASON_CD] AS [REASON_CD],
[CUST_STS_REASON].[DSC] AS [DSC],
[CUST_STS_REASON].[RES_KEY] AS [RES_KEY]
FROM [DBO].[CUST_STS_REASON] AS [CUST_STS_REASON]) AS [Extent7] ON [Extent7].[STS_CD] = [Filter1].[CUST_STS_CD1]
I am getting my SQL query results as expected (about 300 or so records). However, my lambda is bringing all records (over 100k). It is complete ignoring my "where" clause in the statement.
Could you please point me in the right direction on this query?
I appreciate your time and consideration.
Well, since there is more than one way of skinning a cat, I ended up creating, executing a Stored Procedure that solved the problem and returned only the data that I needed. Thank you for all your responses though. I really learned something new here. I appreciate!

python- how to join two seperate queries based on common value

I have two queries which links to different databases
query = "select name ,ctry from xxxx where xxxx"
cursor.execute(query)
results1 = list(cursor.fetchall())
for row in results1:
query1 = "SELECT sessionname, country FROM xxx where and sessions.sessionname = '"+row[0] +"'"
cur.execute(query1)
results2.append(cur.fetchall())
How to connect them if they have common value(sessionname and name) and save it's output to file. Both queries are located in different dbo (oracle, postgresql)
My code is here :
try:
query = """select smat.s_name "SQLITE name" ,smed.m_ctry as "Country", smed.m_name "HDD Label" from smart.smed2smat ss, smart.smed smed, smart.smat smat where ss.M2S_SMAT=smat.s_id and ss.m2s_smed=smed.m_id and smed.m_name like '{0}%' order by smat.s_name""" .format(line_name)
cursor.execute(query)
columns = [i[0] for i in cursor.description]
results1 = cursor.fetchall()
for row in results1:
query1 = "SELECT sessions.sessionname, projects.country , projects.projectname FROM momatracks.sessions, momatracks.projects, momatracks.sessionsgeo where sessions.projectid = projects.id and sessionsgeo.sessionname = sessions.sessionname and sessions.sessionname = '"+row[0] +"' order by sessions.sessionname"
cur.execute(query1)
results2 =cur.fetchall()
print "results1 -----> \n:", row
tmp=[]
output_items = []
for tmp in results2:
print "---> \n", tmp
try:
stations_dict = dict([(item[0], item[1:]) for item in tmp])
for item in row:
output_item = list(item) + stations_dict.get(item[0], [])
output_items.append(output_item)
except Exception, f:
print str (f)
cursor.close()
cur.close()
except Exception, g:
print str ( g )
except Exception, e:
print str ( e )
My results from row and tmp are :
row - WE246JP_2015_10_11__14_53_33', 'NLD', '031_025_SQLITE_NLD1510_03INDIA
and
tmp - WE246JP_2015_10_11__14_53_33', 'NLD', 'NLD15_N2C1-4_NL'
How to properly connect them? I want output look like this :
output_items - WE246JP_2015_10_11__14_53_33', 'NLD', '031_025_SQLITE_NLD1510_03INDIA', 'NLD15_N2C1-4_NL'
At the moment i get this error :
can only concatenate list (not "str") to list
Also value station_dict looks like this :( And this is not what i intended to do
'W': 'E246JP_2015_10_11__15_23_33', 'N': 'LD15_N2C1-4_NL3'
I know there is something wrong with my code which is simmilar to join. Can anyone explain this to me ? I used method below :
http://forums.devshed.com/python-programming-11/join-arrays-based-common-value-sql-left-join-943177.html
If the sessions are exactly the same in both databases then just zip the results:
query = """
select
smat.s_name "SQLITE name",
smed.m_ctry as "Country",
smed.m_name "HDD Label"
from
smart.smed2smat ss
inner join
smart.smed smed on ss.M2S_SMAT = smat.s_id
inner join
smart.smat smat on ss.m2s_smed = smed.m_id
where smed.m_name like '{0}%'
order by smat.s_name
""".format(line_name)
cursor.execute(query)
results1 = cursor.fetchall()
query1 = """
select
sessions.sessionname,
projects.country,
projects.projectname
from
momatracks.sessions,
inner join
momatracks.projects on sessions.projectid = projects.id
inner join
momatracks.sessionsgeo on sessionsgeo.sessionname = sessions.sessionname
where sessions.sessionname in {}
order by sessions.sessionname
""".format(tuple([row[0] for row in results1]))
cur.execute(query1)
results2 = cur.fetchall()
zipped = zip(results1, results2)
output_list = [(m[0][0], m[0][1], m[0][2], m[1][2]) for m in zipped]
If the sessions are different then make each result a dictionary to join.
I think you can use a subquery here. There's no way for me to test it, but I think it should look like this:
SELECT *
FROM (SELECT smat.s_name "SQLITE name" ,
smed.m_ctry as "Country",
smed.m_name "HDD Label"
FROM smart.smed2smat ss,
smart.smed smed,
smart.smat smat
WHERE ss.M2S_SMAT=smat.s_id
AND ss.m2s_smed=smed.m_id
AND smed.m_name like '{0}%'
ORDER BY smat.s_name) t1,
(SELECT sessions.sessionname,
projects.country ,
projects.projectname
FROM momatracks.sessions,
momatracks.projects,
momatracks.sessionsgeo
WHERE sessions.projectid = projects.id
AND sessionsgeo.sessionname = sessions.sessionname
AND sessions.sessionname = '"+row[0] +"'
ORDER BY sessions.sessionname) t2
WHERE t1."SQLITE name" = t2.sessionname ;

Cannot get scroll bar to work PyGTK treeview

First let me start off by saying I read on here a lot and I have googled around for the answer but have not been able to turn one up.
Basically I am trying to add a scroll bar to add to my vbox window. I know its simply something I am not understanding. Here is the code (please ignore the mysql statements, I haven't gotten around to cleaning them up yet
#!/usr/bin/python
import pygtk
pygtk.require('2.0')
import gtk
import os
import sys
import MySQLdb
from Tkinter import *
database_connection = MySQLdb.connect('localhost', 'root', '', 'nmap');
cursor = database_connection.cursor()
class Table_GUI:
cells = {}
columns = {}
sort_order = gtk.SORT_ASCENDING
def delete_event(self, widget, event, data=None):
return False
def destroy(self, widget, data=None):
gtk.main_quit()
def __init__(self):
# create a new window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_geometry_hints(min_width=400, min_height=200)
self.window.connect("delete_event", self.delete_event)
self.window.connect("destroy", self.destroy)
self.vbox = gtk.VBox(False, 0)
self.window.add(self.vbox)
self.vbox.show()
self.vbox.pack_start(self.scrolledwindow)
self.frm_table = gtk.Frame()
self.frm_table.set_shadow_type(gtk.SHADOW_NONE)
self.frm_table.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#fff'))
self.show_Table(oper_sys, ip_get)
self.frm_table.show()
self.vbox.pack_start(self.frm_table, True, True, 0)
self.window.show()
def show_Table(self, search_os, search_ip):
### Create the table
# List of items to display which represent IP, OS, DNS, Port number and Port description
self.liststore = gtk.ListStore(str, str, str, str, str)
if search_os != "" and search_ip !="":
#Set up the queries. If the user has activted the checkbox, we need to include the ports in the query
if ports_check == 1:
pass
#Otherwise just return the relevent data
else:
pass
elif search_os != "" and search_ip == "":
if ports_check == 1:
pass
else:
pass
elif search_os =="" and search_ip != "":
if ports_check == 1:
pass
else:
pass
#get the results and prepare to put them inside of lists
fetch_results = cursor.fetchall()
host_name_list = []
operating_list = []
ip_list = []
ports = []
#The element chosen to append to each list based on the order of retrieval in the mysql query
for individual_result in fetch_results:
ip_list.append(individual_result[0])
operating_list.append(individual_result[1])
host_name_list.append(individual_result[2])
if ports_check == 1:
ports.append(individual_result[3])
#we are going to add blanks to the files in order to help readability
#when putting this into the chart
cleaned_host =[]
cleaned_ip = []
cleaned_os_list = []
index_counter = 0
#this loop will check to see if the entry already exists in the cleaned variables. If it does, it 'omitts' them by inserting a blank line
while index_counter < len(host_name_list):
if host_name_list[index_counter] in cleaned_host:
#print "found a duplicate in HOST....OMITTING"
cleaned_host.append("")
else:
#print "adding ", host_name_list[index_counter]
cleaned_host.append(host_name_list[index_counter])
if operating_list[index_counter] in cleaned_os_list and ip_list[index_counter] in cleaned_ip:
#print "found a duplicate in OPERATING....OMITTING"
cleaned_os_list.append("")
else:
#print "adding ", operating_list[index_counter]
cleaned_os_list.append(operating_list[index_counter])
if ip_list[index_counter] in cleaned_ip:
#print "Found a duplicate in IP.... OMITTING "
cleaned_ip.append("")
else:
#print "adding ", ip_list[index_counter]
cleaned_ip.append(ip_list[index_counter])
index_counter +=1
#this section appends to the list store depending on whether the user wants to see the ports or not
counter = 0
for single_result in fetch_results:
if ports_check == 1:
self.liststore.append(
[ cleaned_ip[counter], cleaned_os_list[counter], cleaned_host[counter], single_result[4], single_result[3] ]
)
else:
self.liststore.append(
[ single_result[0], single_result[1], single_result[2], "" , "" ]
)
counter +=1
# Treeview
self.treeview = gtk.TreeView()
self.treeview.set_property("fixed-height-mode", False)
#For some reason I can't get the scrolled window to work...
self.scrolledwindow = gtk.ScrolledWindow()
self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
# Columns
self.newColumn("IP Address", 0)
self.newColumn("Operating System", 1)
self.newColumn("Hostname",2)
if ports_check == 1:
self.newColumn("Ports", 3)
self.newColumn("Protocol name", 4)
self.treeview.set_model(self.liststore)
self.treeview.set_headers_clickable(True)
self.frm_table.add(self.treeview)
self.treeview.show()
#this function allows for the sorting of the columns
#Given the way this works with the ports_check == 1, this will confuse the output
def on_column_clicked(self, tc, user_data):
self.liststore.set_sort_column_id(user_data, self.sort_order)
if self.sort_order == gtk.SORT_ASCENDING:
self.sort_order = gtk.SORT_DESCENDING
else:
self.sort_order = gtk.SORT_ASCENDING
tc.set_sort_order(self.sort_order)
def newColumn(self, title, index):
self.cells[index] = gtk.CellRendererText()
self.cells[index].set_property('cell-background-gdk', gtk.gdk.color_parse("#FFF"))
self.columns[index] = gtk.TreeViewColumn(title, self.cells[index], text=index)
self.columns[index].set_resizable(True)
self.columns[index].set_reorderable(True)
self.columns[index].set_sort_indicator(True)
if(index == 0) :
self.columns[index].set_min_width(130)
if (index == 1) :
self.columns[index].set_min_width(300)
if (index == 2) :
self.columns[index].set_min_width(200)
self.columns[index].connect("clicked", self.on_column_clicked, index)
self.treeview.insert_column(self.columns[index], -1)
# The main function
def main(self):
gtk.main()
class createUI:
def pushButton(self, parent):
global ports_check, oper_sys, ip_get
ports_check = display_ports.get()
oper_sys = OS.get()
ip_get = IP.get()
gui = Table_GUI()
gui.main()
def __init__(self, parent):
#export variables from this class so they are available in other classes
global OS, IP, counter, display_ports
self.panel1 = Frame(parent.title("main window"))
self.panel1.pack()
self.frame1 = Frame(self.panel1)
#in the first frame, create the directions and the input boxes
self.OS_label = Message(self.frame1, text="Search by operating system", justify=LEFT, width=180).pack(pady=2)
OS = Entry(self.frame1)
OS.pack()
OS.focus_set()
self.IP_label = Message(self.frame1, text="Search by IP", justify=LEFT, width=180).pack(pady=3)
IP = Entry(self.frame1)
IP.pack(pady=14, padx=60)
self.frame1.pack()
self.frame5 = Frame(self.panel1)
#set the variables used by the checkboxes to an IntVar so that they can be evaluated as off or on
display_ports = IntVar()
ports_checkbutton = Checkbutton(self.frame5, text='Display Ports', onvalue = 1, offvalue = 0, variable=display_ports, width=10)
ports_checkbutton.pack(side=LEFT)
self.frame5.pack()
self.frame6 = Frame(self.panel1)
#lambda was used so that the button does not execute the addToDB class before click. addToDB requires an argument and self.database_button didn't work
self.database_button = Button(self.frame6, text="Get results!")
self.database_button.pack()
self.database_button.configure(command=lambda btn = self.database_button: self.pushButton(btn))
self.quit_button = Button(self.frame6, text="Get me outta here", command=self.panel1.quit).pack()
self.frame6.pack()
if __name__ == "__main__":
root = Tk()
ui = createUI(root)
ui.panel1.mainloop()
You will see the following in there:
# For some reason I can't get the scrolled window to work...
self.scrolledwindow = gtk.ScrolledWindow()
self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
When I have attempted to attach it via
self.scrolledwindow.add_with_viewport(self.treeview)
I get the message
GtkWarning: Attempting to add a widget with type GtkTreeView to a container of type GtkFrame, but the widget is already inside a container of type GtkViewport
I went to the FAQ page but I really didn't understand what it was telling me.
If I try to set in on self.window I get:
GtkWarning: Can't set a parent on a toplevel widget
self.scrolledwindow.add_with_viewport(self.window)
That one is pretty self explanatory
If I try to add it to vbox I get:
GtkWarning: IA__gtk_scrolled_window_add_with_viewport: assertion `child->parent == NULL' failed[/quote]
I am not looking for a freebie but I am hoping that someone could help to point me in the right direction. (as you can see I am not coming with a "can you make me a program that does X" scenario)
--->New GTK only interface below<----
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk
import gtk
import os
import sys
import MySQLdb
database_connection = MySQLdb.connect('localhost', 'root', '', 'nmap');
cursor = database_connection.cursor()
#---------------------------------------------------------------
class Application(gtk.Window):
cells = {}
columns = {}
sort_order = gtk.SORT_ASCENDING
####################
def __init__(self):
gtk.Window.__init__( self )
self.set_title("Netowrk Scanner")
self.create_widgets()
self.connect_signals()
#self.window.show_all()
self.show_all()
gtk.main()
#####################
def create_widgets(self):
#Ask the user to search by operating system
self.vbox = gtk.VBox(spacing=10)
self.operating_system_label_hbox_1 = gtk.HBox(spacing=10)
self.label = gtk.Label("Search by Operating System :")
self.operating_system_label_hbox_1.pack_start(self.label)
#Set a check box so the user can choose to display ports
self.ports_hbox_8 = gtk.HBox(spacing=10)
self.ports_check = gtk.CheckButton("Display Ports")
self.ports_hbox_8.pack_start(self.ports_check)
self.halign_ports = gtk.Alignment(0,1,1,0)
self.halign_ports.add(self.ports_hbox_8)
self.os_entry_hbox_2 = gtk.HBox(spacing=10)
self.OS = gtk.Entry()
self.os_entry_hbox_2.pack_start(self.OS)
self.hostname_label_hbox_3 = gtk.HBox(spacing=10)
self.label = gtk.Label("Search by Hostname:")
self.hostname_label_hbox_3.pack_start(self.label)
self.hostname_entry_hbox_4 = gtk.HBox(spacing=10)
self.HOSTNAME = gtk.Entry()
self.hostname_entry_hbox_4.pack_start(self.HOSTNAME)
self.ip_label_hbox_5 = gtk.HBox(spacing=10)
self.label = gtk.Label("Search by IP:")
self.ip_label_hbox_5.pack_start(self.label)
self.ip_entry_hbox_6 = gtk.HBox(spacing=10)
self.IP = gtk.Entry()
self.ip_entry_hbox_6.pack_start(self.IP)
self.buttons_hbox_7 = gtk.HBox(spacing=10)
self.button_ok = gtk.Button("Get Results!")
self.buttons_hbox_7.pack_start(self.button_ok)
self.button_exit = gtk.Button("Get me Outta Here!")
self.buttons_hbox_7.pack_start(self.button_exit)
#The order in which you pack_start a widget is the order in which it is displayed on the screen
self.vbox.pack_start(self.operating_system_label_hbox_1)
self.vbox.pack_start(self.os_entry_hbox_2)
self.vbox.pack_start(self.hostname_label_hbox_3)
self.vbox.pack_start(self.hostname_entry_hbox_4)
self.vbox.pack_start(self.ip_label_hbox_5)
self.vbox.pack_start(self.ip_entry_hbox_6)
self.vbox.pack_start(self.halign_ports, False, False, 3)
self.vbox.pack_start(self.buttons_hbox_7)
self.add(self.vbox)
##########################
def connect_signals(self):
#Have the buttons start 'listening' for user interaction
self.button_ok.connect("clicked", self.button_click)
self.button_exit.connect("clicked", self.exit_program)
def button_click(self, clicked):
#This function gets the values of the input boxes as well as the check box
#And then passes them to the show_table function so it can get the correct results from the database
global ports_check, os, ip, hostname
os = self.OS.get_text()
ip = self.IP.get_text()
hostname = self.HOSTNAME.get_text()
ports_check = self.ports_check.get_active()
self.frm_table = gtk.Window()
self.frm_table.set_title("Network scan results")
#Change the background to white instead of grey
self.frm_table.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#fff'))
self.frm_table.show()
self.show_Table(os, ip, hostname)
############################
def show_Table(self, search_os, search_ip, search_hostname):
### Create the table
# List of items to display which represent IP, OS, DNS, Port number and Port description
self.liststore = gtk.ListStore(str, str, str, str, str)
#If the user is running a search on the hostname run these queries
if search_hostname != "":
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE DNS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % (search_hostname))
#Otherwise just return the relevent data
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE DNS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % (search_hostname))
#If the user has specified the IP and the OS to search, run this query
if search_os != "" and search_ip !="":
#Set up the queries. If the user has activated the checkbox, we need to include the ports in the query
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' and Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % (search_os, search_ip))
#Otherwise just return the relevent data
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' and Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % (search_os, search_ip))
#If the user has specified an OS but not an IP run this
elif search_os != "" and search_ip == "":
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % search_os)
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % search_os)
#If the user has specified an IP but not an OS run this
elif search_os =="" and search_ip != "":
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % search_ip)
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % search_ip)
#get the results and prepare to put them inside of lists
fetch_results = cursor.fetchall()
host_name_list = []
operating_list = []
ip_list = []
ports = []
#The element chosen to append to each list based on the order of retrieval in the mysql query
for individual_result in fetch_results:
ip_list.append(individual_result[0])
operating_list.append(individual_result[1])
host_name_list.append(individual_result[2])
if ports_check == True:
ports.append(individual_result[3])
#we are going to add blanks to the files in order to help readability
#when putting this into the chart
cleaned_host =[]
cleaned_ip = []
cleaned_os_list = []
index_counter = 0
#this loop will check to see if the entry already exists in the cleaned variables. If it does, it 'omitts' them by inserting a blank line
while index_counter < len(host_name_list):
if host_name_list[index_counter] in cleaned_host:
#print "found a duplicate in HOST....OMITTING"
cleaned_host.append("")
else:
#print "adding ", host_name_list[index_counter]
cleaned_host.append(host_name_list[index_counter])
if operating_list[index_counter] in cleaned_os_list and ip_list[index_counter] in cleaned_ip:
#print "found a duplicate in OPERATING....OMITTING"
cleaned_os_list.append("")
else:
#print "adding ", operating_list[index_counter]
cleaned_os_list.append(operating_list[index_counter])
if ip_list[index_counter] in cleaned_ip:
#print "Found a duplicate in IP.... OMITTING "
cleaned_ip.append("")
else:
#print "adding ", ip_list[index_counter]
cleaned_ip.append(ip_list[index_counter])
index_counter +=1
#this section appends to the list store depending on whether the user wants to see the ports or not
counter = 0
for single_result in fetch_results:
if ports_check == True:
self.liststore.append(
[ cleaned_ip[counter], cleaned_os_list[counter], cleaned_host[counter], single_result[4], single_result[3] ]
)
else:
self.liststore.append(
[ single_result[0], single_result[1], single_result[2], "" , "" ]
)
counter +=1
# Treeview
self.treeview = gtk.TreeView()
#In lieu of getting the scroll bar to work, force a max height requirement on creation
self.treeview.set_property('height-request', 600)
# Columns
self.newColumn("IP Address", 0)
self.newColumn("Operating System", 1)
self.newColumn("Hostname",2)
#I only want the ports columns to show if the user requests it because this calls different mysql queries
if ports_check == True:
self.newColumn("Ports", 3)
self.newColumn("Protocol name", 4)
#put the liststore inside of the tree view
self.treeview.set_model(self.liststore)
self.treeview.set_headers_clickable(True)
#Still can't get the scroll bar to work properly so leaving them commented out
#self.scrolledwindow = gtk.ScrolledWindow()
#self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
#add the tree view to the frm_table
self.frm_table.add(self.treeview)
self.treeview.show()
##########################
def on_column_clicked(self, tc, user_data):
#This function allows the columns to be resorted upon click
self.liststore.set_sort_column_id(user_data, self.sort_order)
if self.sort_order == gtk.SORT_ASCENDING:
self.sort_order = gtk.SORT_DESCENDING
else:
self.sort_order = gtk.SORT_ASCENDING
tc.set_sort_order(self.sort_order)
###########################
def newColumn(self, title, index):
#This function cleans up code because I want these options on all of the columns
#This code block would have to be duplicated for each column otherwise...
self.cells[index] = gtk.CellRendererText()
self.cells[index].set_property('cell-background-gdk', gtk.gdk.color_parse("#FFF"))
self.columns[index] = gtk.TreeViewColumn(title, self.cells[index], text=index)
self.columns[index].set_resizable(True)
self.columns[index].set_reorderable(True)
self.columns[index].set_sort_indicator(True)
if(index == 0) :
self.columns[index].set_min_width(130)
if (index == 1) :
self.columns[index].set_min_width(300)
if (index == 2) :
self.columns[index].set_min_width(200)
self.columns[index].connect("clicked", self.on_column_clicked, index)
self.treeview.insert_column(self.columns[index], -1)
# The main function
########################
def exit_program(self, widget, callback_data=None):
gtk.main_quit()
#---------------------------------------------
if __name__ == "__main__":
app = Application()
database_connection.commit()
cursor.close()
database_connection.close()
--->end new interface<---
I am still having the same problems with the scroll bars. I suspect it is the way I am adding widgets to containers.
NOTE: I removed mysql statements from first GUI to save post space
The only difference with my working code is that I do NOT use "add_with_viewport" :
swH = gtk.ScrolledWindow()
swH.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swH.add(treeviewH)
It works fine. Please try, and tell me if it's OK. If not, I will digg further.
EDIT
Try this sample, adapt it with your DB data (I cannot run your program because I do not have the db), and enjoy !
#!/usr/bin/env python
# -*- Encoding: Latin-1 -*-
import pygtk
pygtk.require('2.0')
import gtk
def window():
win = gtk.Window ()
win.set_default_size(300, 150)
win.set_position(gtk.WIN_POS_CENTER)
win.connect ('delete_event', gtk.main_quit)
cols = ['Date', 'Index', 'Program', 'Comments']
sequence = [str] * len(cols)
starStore = gtk.TreeStore( * sequence)
starView = gtk.TreeView(starStore)
starView.cell = [None] * len(cols)
tvcolumn = [None] * len(cols)
for colnum, col in enumerate(cols):
starView.cell[colnum] = gtk.CellRendererText()
tvcolumn[colnum] = gtk.TreeViewColumn(col, starView.cell[colnum])
tvcolumn[colnum].add_attribute(starView.cell[colnum], 'text', colnum)
starView.append_column(tvcolumn[colnum])
scrollTree = gtk.ScrolledWindow()
scrollTree.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
scrollTree.add(starView)
win.add(scrollTree)
data = [['2010', '123', 'P02', 'Initial'],
['2008', '456', 'P08', 'not finished'],
['2007', '456', 'P08', 'not finished'],
['2006', '456', 'P08', 'not finished'], # copy and paste a line to add, delete a line to shorten the treeview. The scollbar appears when needed.
['2005', '456', 'P08', 'not finished'],
['2004', '456', 'P08', 'not finished'],
['2001', '999', 'P999', 'A space Odissey']]
for line in data:
mother = starStore.append( None, [line[0], line[1], line[2], line[3]])
win.show_all()
gtk.main()
if __name__ == '__main__':
window()
Thank you so much for that!
After some playing around I was able to adapt my program with your guidance!
If anyone is interested in this I am posting the code below for completeness
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk
import gtk
import os
import sys
import MySQLdb
database_connection = MySQLdb.connect('localhost', 'root', '', 'nmap');
cursor = database_connection.cursor()
class Application(gtk.Window):
cells = {}
columns = {}
sort_order = gtk.SORT_ASCENDING
####################
def __init__(self):
gtk.Window.__init__( self )
self.set_title("Netowrk Scanner")
self.set_position(gtk.WIN_POS_CENTER)
self.create_widgets()
self.connect_signals()
#self.window.show_all()
self.show_all()
gtk.main()
##################
def create_widgets(self):
#Ask the user to search by operating system
self.vbox = gtk.VBox(spacing=10)
self.operating_system_label_hbox_1 = gtk.HBox(spacing=10)
self.label = gtk.Label("Search by Operating System :")
self.operating_system_label_hbox_1.pack_start(self.label)
#Set a check box so the user can choose to display ports
self.ports_hbox_8 = gtk.HBox(spacing=10)
self.ports_check = gtk.CheckButton("Display Ports")
self.ports_hbox_8.pack_start(self.ports_check)
self.halign_ports = gtk.Alignment(0,1,1,0)
self.halign_ports.add(self.ports_hbox_8)
self.os_entry_hbox_2 = gtk.HBox(spacing=10)
self.OS = gtk.Entry()
self.os_entry_hbox_2.pack_start(self.OS)
self.hostname_label_hbox_3 = gtk.HBox(spacing=10)
self.label = gtk.Label("Search by Hostname:")
self.hostname_label_hbox_3.pack_start(self.label)
self.hostname_entry_hbox_4 = gtk.HBox(spacing=10)
self.HOSTNAME = gtk.Entry()
self.hostname_entry_hbox_4.pack_start(self.HOSTNAME)
self.ip_label_hbox_5 = gtk.HBox(spacing=10)
self.label = gtk.Label("Search by IP:")
self.ip_label_hbox_5.pack_start(self.label)
self.ip_entry_hbox_6 = gtk.HBox(spacing=10)
self.IP = gtk.Entry()
self.ip_entry_hbox_6.pack_start(self.IP)
self.buttons_hbox_7 = gtk.HBox(spacing=10)
self.button_ok = gtk.Button("Get Results!")
self.buttons_hbox_7.pack_start(self.button_ok)
self.button_exit = gtk.Button("Get me Outta Here!")
self.buttons_hbox_7.pack_start(self.button_exit)
#The order in which you pack_start a widget is the order in which it is displayed on the screen
self.vbox.pack_start(self.operating_system_label_hbox_1)
self.vbox.pack_start(self.os_entry_hbox_2)
self.vbox.pack_start(self.hostname_label_hbox_3)
self.vbox.pack_start(self.hostname_entry_hbox_4)
self.vbox.pack_start(self.ip_label_hbox_5)
self.vbox.pack_start(self.ip_entry_hbox_6)
self.vbox.pack_start(self.halign_ports, False, False, 3)
self.vbox.pack_start(self.buttons_hbox_7)
self.add(self.vbox)
##########################
def connect_signals(self):
#Have the buttons start 'listening' for user interaction
self.button_ok.connect("clicked", self.button_click)
self.button_exit.connect("clicked", self.exit_program)
########################
def button_click(self, clicked):
#This function gets the values of the input boxes as well as the check box
#And then passes them to the show_table function so it can get the correct results from the database
global ports_check, os, ip, hostname
os = self.OS.get_text()
ip = self.IP.get_text()
hostname = self.HOSTNAME.get_text()
ports_check = self.ports_check.get_active()
self.show_Table(os, ip, hostname)
##############
def show_Table(self, search_os, search_ip, search_hostname):
### Create the table
# List of items to display which represent IP, OS, DNS, Port number and Port description
# Columns
if ports_check == True:
cols = ['IP Address', 'Operating System', 'Hostname', 'Ports', 'Protocol Name']
else:
cols = ['IP Address', 'Operating System', 'Hostname']
"""
self.newColumn("IP Address", 0)
self.newColumn("Operating System", 1)
self.newColumn("Hostname",2)
#I only want the ports columns to show if the user requests it because this calls different mysql queries
if ports_check == True:
self.newColumn("Ports", 3)
self.newColumn("Protocol name", 4)
"""
sequence = [str] * len(cols)
self.treestore = gtk.TreeStore( * sequence)
self.treestore.connect("rows-reordered", self.on_column_clicked)
self.treeview = gtk.TreeView(self.treestore)
self.treeview.cell = [None] * len(cols)
self.treeview_column = [None] * len(cols)
for column_number, col in enumerate(cols):
self.treeview.cell[column_number] = gtk.CellRendererText()
self.treeview_column[column_number] = gtk.TreeViewColumn(col, self.treeview.cell[column_number])
self.treeview_column[column_number].add_attribute(self.treeview.cell[column_number], 'text', column_number)
self.treeview_column[column_number].set_resizable(True)
self.treeview_column[column_number].set_reorderable(True)
self.treeview_column[column_number].set_sort_indicator(True)
self.treeview_column[column_number].set_sort_column_id(column_number)
self.treeview.append_column(self.treeview_column[column_number])
self.scrollTree = gtk.ScrolledWindow()
self.scrollTree.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
self.scrollTree.add(self.treeview)
#If the user is running a search on the hostname run these queries
if search_hostname != "":
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE DNS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % (search_hostname))
#Otherwise just return the relevent data
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE DNS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % (search_hostname))
#If the user has specified the IP and the OS to search, run this query
if search_os != "" and search_ip !="":
#Set up the queries. If the user has activated the checkbox, we need to include the ports in the query
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' and Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % (search_os, search_ip))
#Otherwise just return the relevent data
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' and Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % (search_os, search_ip))
#If the user has specified an OS but not an IP run this
elif search_os != "" and search_ip == "":
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % search_os)
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE OS_Name LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % search_os)
#If the user has specified an IP but not an OS run this
elif search_os =="" and search_ip != "":
if ports_check == True:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name, Port_Description, Open_Port FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address ), Open_Port" % search_ip)
else:
cursor.execute("SELECT DISTINCT Computer_IP_Address, OS_Name, DNS_Name FROM Computer_Ports AS CP \
JOIN Computer_Info AS CI ON ( CP.Computer_ID = CI.Computer_ID ) \
JOIN Ports_Table AS PT ON ( CP.Port_ID = PT.Port_ID ) \
JOIN OS_Table AS OS ON ( CI.Computer_ID = OS.OS_ID ) \
JOIN Port_Description AS PS ON ( PT.Open_Port = PS.Port_Number ) \
WHERE Computer_IP_Address LIKE '%%%s%%' ORDER BY inet_aton( Computer_IP_Address )" % search_ip)
#get the results and prepare to put them inside of lists
fetch_results = cursor.fetchall()
host_name_list = []
operating_list = []
ip_list = []
ports = []
#The element chosen to append to each list based on the order of retrieval in the mysql query
for individual_result in fetch_results:
ip_list.append(individual_result[0])
operating_list.append(individual_result[1])
host_name_list.append(individual_result[2])
if ports_check == True:
ports.append(individual_result[3])
#we are going to add blanks to the files in order to help readability
#when putting this into the chart
cleaned_host =[]
cleaned_ip = []
cleaned_os_list = []
index_counter = 0
#this loop will check to see if the entry already exists in the cleaned variables. If it does, it 'omitts' them by inserting a blank line
while index_counter < len(host_name_list):
if host_name_list[index_counter] in cleaned_host:
#print "found a duplicate in HOST....OMITTING"
cleaned_host.append("")
else:
#print "adding ", host_name_list[index_counter]
cleaned_host.append(host_name_list[index_counter])
if operating_list[index_counter] in cleaned_os_list and ip_list[index_counter] in cleaned_ip:
#print "found a duplicate in OPERATING....OMITTING"
cleaned_os_list.append("")
else:
#print "adding ", operating_list[index_counter]
cleaned_os_list.append(operating_list[index_counter])
if ip_list[index_counter] in cleaned_ip:
#print "Found a duplicate in IP.... OMITTING "
cleaned_ip.append("")
else:
#print "adding ", ip_list[index_counter]
cleaned_ip.append(ip_list[index_counter])
index_counter +=1
#this section appends to the list store depending on whether the user wants to see the ports or not
counter = 0
for single_result in fetch_results:
if ports_check == True:
self.treestore.append( None,
[ cleaned_ip[counter], cleaned_os_list[counter], cleaned_host[counter], single_result[4], single_result[3] ]
)
else:
self.treestore.append(None,
[ single_result[0], single_result[1], single_result[2] ]
)
counter +=1
self.frm_table = gtk.Window()
self.frm_table.set_default_size(600, 800)
self.frm_table.set_title("Network scan results")
#Change the background to white instead of grey
self.frm_table.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#fff'))
self.frm_table.add(self.scrollTree)
self.frm_table.show_all()
######################
def on_column_clicked(self, col1, col2, col3, col4 ):
#This function allows the columns to be resorted upon click
if self.sort_order == gtk.SORT_ASCENDING:
self.sort_order = gtk.SORT_DESCENDING
else:
self.sort_order = gtk.SORT_ASCENDING
#tc.set_sort_order(self.sort_order)
###############
def exit_program(self, widget, callback_data=None):
gtk.main_quit()
#---------------------------------------------
if __name__ == "__main__":
app = Application()
database_connection.commit()
cursor.close()
database_connection.close()