<commit_before>"""
 history.py - Handles the History of the jython console
 Copyright (C) 2001 Carlos Quiroz

 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 2
 of the License, or 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, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
"""
#from org.gjt.sp.jedit.gui import HistoryModel

class History:
    """
    The class history handles the history management basically wrapping the
    built-in jEdit's history capabilities
    """

    def __init__(self, console):
        self.history = []
        self.console = console
        self.index = 0
        self.last = ""

    def append(self, line):
        if line == '\n' or len(line) == 0: return
##  if line == self.last: # avoid duplicates
##      self.index = len(self.history) - 1
##          return

        self.last = line
        self.history.append(line)
        self.index = len(self.history) - 1

    def historyUp(self, event):
        if len(self.history) > 0 and self.console.inLastLine():
            self.console.replaceRow(self.history[self.index])
            self.index = max(self.index - 1, 0)

    def historyDown(self, event):
        if len(self.history) > 0 and self.console.inLastLine():
            if self.index == len(self.history) - 1:
                self.console.replaceRow("")
            else:
                self.index += 1
                self.console.replaceRow(self.history[self.index])

<commit_msg>avoid duplicates default event to None<commit_after>"""
 history.py - Handles the History of the jython console
 Copyright (C) 2001 Carlos Quiroz

 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 2
 of the License, or 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, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
"""
#from org.gjt.sp.jedit.gui import HistoryModel

class History:
    """
    The class history handles the history management basically wrapping the
    built-in jEdit's history capabilities
    """

    def __init__(self, console):
        self.history = []
        self.console = console
        self.index = 0
        self.last = ""

    def append(self, line):
        if line == None or line == '\n' or len(line) == 0:
            return

        if line != self.last: # avoids duplicates
            self.last = line
            self.history.append(line)
        self.index = len(self.history) - 1

    def historyUp(self, event=None):
        if len(self.history) > 0 and self.console.inLastLine():
            self.console.replaceRow(self.history[self.index])
            self.index = max(self.index - 1, 0)

    def historyDown(self, event=None):
        if len(self.history) > 0 and self.console.inLastLine():
            if self.index == len(self.history) - 1:
                self.console.replaceRow("")
            else:
                self.index += 1
                self.console.replaceRow(self.history[self.index])

<|endoftext|>


<commit_before>#!/usr/bin/python3

import asyncio
import hangups
import sys
import json
from hangups.conversation import ConversationList, build_user_conversation_list
import hangups

from html.parser import HTMLParser
from html.entities import name2codepoint
import re

class TcpServer(asyncio.Protocol):
    def connection_made(self, transport):
        """
        Called when a connection is made.
        The argument is the transport representing the pipe connection.
        To receive data, wait for data_received() calls.
        When the connection is closed, connection_lost() is called.
        """
        print("Connection received!", self, dir(self))
        self.transport = transport

        asyncio.async(self._send_messages())  # Or asyncio.ensure_future if using 3.4.3+
        print("## Loop finished in connection_made")

    @asyncio.coroutine
    def _send_messages(self):
        """ Send messages to the server as they become available. """
        print("## TCP receive loop Ready!")
        while True:
            data = yield from queueHoToTcp.get()
            self.transport.write(data.encode('utf-8'))
            print('TCP Message sent: {!r}'.format(data))

    def data_received(self, raw):
        """
        Called when some data is received.
        The argument is a bytes object.
        """
        print("TCP received data :", raw)
        data = json.loads(raw.decode('utf-8'))
        asyncio.async(self.send_message_to_Ho(data))

    @asyncio.coroutine
    def send_message_to_Ho(self, data):
        yield from queueTcpToHo.put(data)

    @asyncio.coroutine
    def connection_lost(self, exc):
        """
        Called when the connection is lost or closed.
        The argument is an exception object or None (the latter
        meaning a regular EOF is received or the connection was
        aborted or closed).
        """
        print("TCP Connection lost! Closing server...")
        #server.close()

class HoClient():
    def __init__(self, loop, inQueue, outQueue, cookiePath):
        self.loop = loop
        self.inQueue = inQueue
        self.outQueue = outQueue

        cookies = hangups.auth.get_auth_stdin(cookiePath)
        self.client = hangups.Client(cookies)
        self.client.on_connect.add_observer(lambda: asyncio.async(self.on_connect()))

        asyncio.async(self.client.connect())

    @asyncio.coroutine
    def on_connect(self):
        """Handle connecting for the first time (callback)"""
        print('Ho Connected')

        user_list, conv_list = (
            yield from hangups.build_user_conversation_list(self.client)
        )

        self.userIds = []
        for u in user_list.get_all():
            print(u.id_, u.first_name, u.full_name, u.photo_url, u.emails)
            self.userIds.append({"id": u.id_.chat_id, "first_name": u.first_name, "full_name": u.full_name})

        self.convIds = []
        for c in conv_list.get_all():
            print(c.users, dir(c.users))
            print(c.id_, c.name, [x.id_.chat_id for x in c.users])
            print(c.users, dir(c.users))
            print(c.id_, c.name, [x.id_.chat_id for x in c.users])
            self.convIds.append({"id":c.id_, "name":c.name, "users": [x.id_.chat_id for x in c.users]})
        print("Conversation list :", self.convIds)

        conv_list.on_event.add_observer(self.on_event)

        asyncio.async(self._send_messages())  # Or asyncio.ensure_future if using 3.4.3+

        yield from self.outQueue.put(json.dumps({"conversations": self.convIds, "users": self.userIds}))
        print("## Ho Connection handling done")

    @asyncio.coroutine
    def _send_messages(self):
        """ Send messages to the server as they become available. """
        print("## HO receive loop Ready!")
        while True:
            data = yield from self.inQueue.get()
            print('HO Message sent: {!r}'.format(data))
            asyncio.async(self.send_message(data["conversation"], data["text"]))
        print("## HO receive loop Finished")

    @asyncio.coroutine
    def send_message(self, convId, data):
        print("send message :", data)
        request = hangups.hangouts_pb2.SendChatMessageRequest(
            request_header=self.client.get_request_header(),
            event_request_header=hangups.hangouts_pb2.EventRequestHeader(
                conversation_id=hangups.hangouts_pb2.ConversationId(
                    id=convId
                ),
                client_generated_id=self.client.get_client_generated_id(),
            ),
            message_content=hangups.hangouts_pb2.MessageContent(
#                segment=[hangups.ChatMessageSegment(data).serialize()],
                 segment=simple_parse_to_segments(data)
            ),
        )
        yield from self.client.send_chat_message(request)

    @asyncio.coroutine
    def on_status_changes(self):
        print("on_status_changes", self)

    @asyncio.coroutine
    def on_event(self, conv_event):
        print("on_event", conv_event, dir(conv_event))
        if isinstance(conv_event, hangups.ChatMessageEvent):
            print("## On Event. Pushing data to queue HoToTcp")
            yield from self.outQueue.put(json.dumps({"conversation": conv_event.conversation_id, "timestamp": conv_event.timestamp.timestamp(), "user": conv_event.user_id.chat_id, "text": conv_event.text}))
            print("## On Event. data pushed to queue HoToTcp")

    @asyncio.coroutine
    def _on_status_changes(self, state_update):
        if state_update.HasField('conversation'):
            print("status changes : conversation")

        if state_update.watermark_notification is not None:
            print("watermark notification")

class simpleHTMLParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self._flags = {"bold" : False,
                       "italic" : False,
                       "underline" : False,
                       "link_target" : None}

        self._link_text = None

    def feed(self, html):
        self._segments = list()
        super().feed(html)
        return self._segments

    def handle_starttag(self, tag, attrs):
        if tag == 'b':
            self._flags["bold"] = True
        elif tag == 'i':
            self._flags["italic"] = True
        elif tag == 'u':
            self._flags["underline"] = True
        elif tag == 'a':
            self._link_text = ""
            for attr in attrs:
                if attr[0] == "href":
                    self._flags["link_target"] = attr[1]
                    break

    def handle_endtag(self, tag):
        if tag == 'b':
            self._flags["bold"] = False
        elif tag == 'i':
            self._flags["italic"] = False
        elif tag == 'u':
            self._flags["underline"] = False
        elif tag == 'a':
            self._segments.append(
              hangups.ChatMessageSegment(
                self._link_text,
                hangups.SegmentType.LINK,
                link_target=self._flags["link_target"],
                is_bold=self._flags["bold"],
                is_italic=self._flags["italic"],
                is_underline=self._flags["underline"]).serialize())
            self._flags["link_target"] = None
        elif tag == 'br':
            self._segments.append(
              hangups.ChatMessageSegment(
                "\n",
                1).serialize())
                #hangups.SegmentType.LINE_BREAK).serialize())

    def handle_data(self, data):
        if self._flags["link_target"] is not None:
            self._link_text += data
        else:
            self._segments.append(
              hangups.ChatMessageSegment(
                data,
                is_bold=self._flags["bold"],
                is_italic=self._flags["italic"],
                is_underline=self._flags["underline"],
                link_target=self._flags["link_target"]).serialize())

def simple_parse_to_segments(html):
    html = fix_urls(html)
    parser = simpleHTMLParser()
    return parser.feed(html)

def fix_urls(text):
    """adapted from http://stackoverflow.com/a/1071240"""
    pat_url = re.compile(  r'''
                     (?x)( # verbose identify URLs within text
   (http|https|ftp|gopher) # make sure we find a resource type
                       :// # ...needs to be followed by colon-slash-slash
            (\w+[:.]?){2,} # at least two domain groups, e.g. (gnosis.)(cx)
                      (/?| # could be just the domain name (maybe w/ slash)
                [^ \n\r"]+ # or stuff then space, newline, tab, quote
                    [\w/]) # resource name ends in alphanumeric or slash
       $|(?=[\s\.,>)'"\]]) # EOL or assert: followed by white or clause ending
                         ) # end of match group
                           ''')

    for url in re.findall(pat_url, text):
       if url[0]:
        text = text.replace(url[0], '%(url)s' % {"url" : url[0]})

    return text

#def main(argv):
argv=sys.argv
if (len(argv) != 3):
    print("Usage : hoToTcp /path/to/.cache/hangups/refresh_token.txt port")
    sys.exit(-1);
#    return -1;

print("Starting hoToTcp gateway...")

loop = asyncio.get_event_loop()

print("Creating Messages Queues")
queueHoToTcp = asyncio.Queue(maxsize=0, loop=loop)
queueTcpToHo = asyncio.Queue(maxsize=0, loop=loop)
print("Queues created")

print("Creating Hangups client")
ho = HoClient(loop, queueTcpToHo, queueHoToTcp, argv[1])
print("Hangups client created")

print("Creating TCP Server")
server = loop.run_until_complete(loop.create_server(TcpServer, 'localhost', argv[2]))
print("Server created")

print("hoToTcp gateway Started !")
print("****-----------------****")
loop.run_forever()
print("Loop finished, exiting...")
exit(0)
#return 0

#if __name__ == '__main__':
#    main(sys.argv)
#    sys.exit(main(sys.argv))

<commit_msg>Added messages separation using the ASCII record character, to split TCP messages when several received in the same buffer<commit_after>#!/usr/bin/python3

import asyncio
import hangups
import sys
import json
from hangups.conversation import ConversationList, build_user_conversation_list
import hangups

from html.parser import HTMLParser
from html.entities import name2codepoint
import re

class TcpServer(asyncio.Protocol):
    def connection_made(self, transport):
        """
        Called when a connection is made.
        The argument is the transport representing the pipe connection.
        To receive data, wait for data_received() calls.
        When the connection is closed, connection_lost() is called.
        """
        print("Connection received!", self, dir(self))
        self.transport = transport

        asyncio.async(self._send_messages())  # Or asyncio.ensure_future if using 3.4.3+
        print("## Loop finished in connection_made")

    @asyncio.coroutine
    def _send_messages(self):
        """ Send messages to the server as they become available. """
        print("## TCP receive loop Ready!")
        while True:
            data = yield from queueHoToTcp.get()
            self.transport.write(data.encode('utf-8'))
            print('TCP Message sent: {!r}'.format(data))

    def data_received(self, raw):
        """
        Called when some data is received.
        The argument is a bytes object.
        """
        print("TCP received data :", raw)
        asyncio.async(self.send_message_to_Ho(raw))

    @asyncio.coroutine
    def send_message_to_Ho(self, data):
        for record in data.split(b'\x1E'):
            print("Send Message after split:", record)
            if len(record) > 0:
                data = json.loads(record.decode('utf-8'))
                yield from queueTcpToHo.put(data)

    @asyncio.coroutine
    def connection_lost(self, exc):
        """
        Called when the connection is lost or closed.
        The argument is an exception object or None (the latter
        meaning a regular EOF is received or the connection was
        aborted or closed).
        """
        print("TCP Connection lost! Closing server...")
        #server.close()

class HoClient():
    def __init__(self, loop, inQueue, outQueue, cookiePath):
        self.loop = loop
        self.inQueue = inQueue
        self.outQueue = outQueue

        cookies = hangups.auth.get_auth_stdin(cookiePath)
        self.client = hangups.Client(cookies)
        self.client.on_connect.add_observer(lambda: asyncio.async(self.on_connect()))

        asyncio.async(self.client.connect())

    @asyncio.coroutine
    def on_connect(self):
        """Handle connecting for the first time (callback)"""
        print('Ho Connected')

        user_list, conv_list = (
            yield from hangups.build_user_conversation_list(self.client)
        )

        self.userIds = []
        for u in user_list.get_all():
            print(u.id_, u.first_name, u.full_name, u.photo_url, u.emails)
            self.userIds.append({"id": u.id_.chat_id, "first_name": u.first_name, "full_name": u.full_name})

        self.convIds = []
        for c in conv_list.get_all():
            print(c.users, dir(c.users))
            print(c.id_, c.name, [x.id_.chat_id for x in c.users])
            print(c.users, dir(c.users))
            print(c.id_, c.name, [x.id_.chat_id for x in c.users])
            self.convIds.append({"id":c.id_, "name":c.name, "users": [x.id_.chat_id for x in c.users]})
        print("Conversation list :", self.convIds)

        conv_list.on_event.add_observer(self.on_event)

        asyncio.async(self._send_messages())  # Or asyncio.ensure_future if using 3.4.3+

        yield from self.outQueue.put(json.dumps({"conversations": self.convIds, "users": self.userIds}))
        print("## Ho Connection handling done")

    @asyncio.coroutine
    def _send_messages(self):
        """ Send messages to the server as they become available. """
        print("## HO receive loop Ready!")
        while True:
            data = yield from self.inQueue.get()
            print('HO Message sent: {!r}'.format(data))
            asyncio.async(self.send_message(data["conversation"], data["text"]))
        print("## HO receive loop Finished")

    @asyncio.coroutine
    def send_message(self, convId, data):
        print("send message :", data)
        request = hangups.hangouts_pb2.SendChatMessageRequest(
            request_header=self.client.get_request_header(),
            event_request_header=hangups.hangouts_pb2.EventRequestHeader(
                conversation_id=hangups.hangouts_pb2.ConversationId(
                    id=convId
                ),
                client_generated_id=self.client.get_client_generated_id(),
            ),
            message_content=hangups.hangouts_pb2.MessageContent(
#                segment=[hangups.ChatMessageSegment(data).serialize()],
                 segment=simple_parse_to_segments(data)
            ),
        )
        yield from self.client.send_chat_message(request)

    @asyncio.coroutine
    def on_status_changes(self):
        print("on_status_changes", self)

    @asyncio.coroutine
    def on_event(self, conv_event):
        print("on_event", conv_event, dir(conv_event))
        if isinstance(conv_event, hangups.ChatMessageEvent):
            print("## On Event. Pushing data to queue HoToTcp")
            yield from self.outQueue.put(json.dumps({"conversation": conv_event.conversation_id, "timestamp": conv_event.timestamp.timestamp(), "user": conv_event.user_id.chat_id, "text": conv_event.text}))
            print("## On Event. data pushed to queue HoToTcp")

    @asyncio.coroutine
    def _on_status_changes(self, state_update):
        if state_update.HasField('conversation'):
            print("status changes : conversation")

        if state_update.watermark_notification is not None:
            print("watermark notification")

class simpleHTMLParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self._flags = {"bold" : False,
                       "italic" : False,
                       "underline" : False,
                       "link_target" : None}

        self._link_text = None

    def feed(self, html):
        self._segments = list()
        super().feed(html)
        return self._segments

    def handle_starttag(self, tag, attrs):
        if tag == 'b':
            self._flags["bold"] = True
        elif tag == 'i':
            self._flags["italic"] = True
        elif tag == 'u':
            self._flags["underline"] = True
        elif tag == 'a':
            self._link_text = ""
            for attr in attrs:
                if attr[0] == "href":
                    self._flags["link_target"] = attr[1]
                    break

    def handle_endtag(self, tag):
        if tag == 'b':
            self._flags["bold"] = False
        elif tag == 'i':
            self._flags["italic"] = False
        elif tag == 'u':
            self._flags["underline"] = False
        elif tag == 'a':
            self._segments.append(
              hangups.ChatMessageSegment(
                self._link_text,
                hangups.SegmentType.LINK,
                link_target=self._flags["link_target"],
                is_bold=self._flags["bold"],
                is_italic=self._flags["italic"],
                is_underline=self._flags["underline"]).serialize())
            self._flags["link_target"] = None
        elif tag == 'br':
            self._segments.append(
              hangups.ChatMessageSegment(
                "\n",
                1).serialize())
                #hangups.SegmentType.LINE_BREAK).serialize())

    def handle_data(self, data):
        if self._flags["link_target"] is not None:
            self._link_text += data
        else:
            self._segments.append(
              hangups.ChatMessageSegment(
                data,
                is_bold=self._flags["bold"],
                is_italic=self._flags["italic"],
                is_underline=self._flags["underline"],
                link_target=self._flags["link_target"]).serialize())

def simple_parse_to_segments(html):
    html = fix_urls(html)
    parser = simpleHTMLParser()
    return parser.feed(html)

def fix_urls(text):
    """adapted from http://stackoverflow.com/a/1071240"""
    pat_url = re.compile(  r'''
                     (?x)( # verbose identify URLs within text
   (http|https|ftp|gopher) # make sure we find a resource type
                       :// # ...needs to be followed by colon-slash-slash
            (\w+[:.]?){2,} # at least two domain groups, e.g. (gnosis.)(cx)
                      (/?| # could be just the domain name (maybe w/ slash)
                [^ \n\r"]+ # or stuff then space, newline, tab, quote
                    [\w/]) # resource name ends in alphanumeric or slash
       $|(?=[\s\.,>)'"\]]) # EOL or assert: followed by white or clause ending
                         ) # end of match group
                           ''')

    for url in re.findall(pat_url, text):
       if url[0]:
        text = text.replace(url[0], '%(url)s' % {"url" : url[0]})

    return text

#def main(argv):
argv=sys.argv
if (len(argv) != 3):
    print("Usage : hoToTcp /path/to/.cache/hangups/refresh_token.txt port")
    sys.exit(-1);
#    return -1;

print("Starting hoToTcp gateway...")

loop = asyncio.get_event_loop()

print("Creating Messages Queues")
queueHoToTcp = asyncio.Queue(maxsize=0, loop=loop)
queueTcpToHo = asyncio.Queue(maxsize=0, loop=loop)
print("Queues created")

print("Creating Hangups client")
ho = HoClient(loop, queueTcpToHo, queueHoToTcp, argv[1])
print("Hangups client created")

print("Creating TCP Server")
server = loop.run_until_complete(loop.create_server(TcpServer, 'localhost', argv[2]))
print("Server created")

print("hoToTcp gateway Started !")
print("****-----------------****")
loop.run_forever()
print("Loop finished, exiting...")
exit(0)
#return 0

#if __name__ == '__main__':
#    main(sys.argv)
#    sys.exit(main(sys.argv))

<|endoftext|>


<commit_before>#-*- coding: utf-8 -*-
import json
import enum
from ryu.app.simple_switch_13 import SimpleSwitch13
from ryu.controller  import ofp_event, event
from ryu.controller.handler import set_ev_cls,MAIN_DISPATCHER,CONFIG_DISPATCHER
from ryu.ofproto.ofproto_v1_3 import *
from ryu.ofproto.ofproto_v1_3_parser import OFPMatch
from ryu.ofproto.ofproto_parser import *
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ipv4
from qsysDataStructure import *
from ryu.controller import dpset

"""__DEBUG_MODE__ = 0#1:on,0:off
class SystemActionModei(enum.Enum):
   # あとでモード実装するはず？
learn = 0
quarantine = 1
"""

class QsysTest(SimpleSwitch13):
	#動作モード
    #ACTION_MODE = SystemActionMode.quarantine

    def __init__(self, *args, **kwargs):
        super(QsysTest, self).__init__(*args, **kwargs)
        self.mac_to_port = {}

    #packet_inハンドラ(override)
    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        allowTransportFlag = False
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})
        pkt = packet.Packet(msg.data)
        self.logger.info("packet-in {}".format(pkt,))
        _eth = pkt.get_protocol(ethernet.ethernet)
        if not _eth:
            self.logger.info("Not Ether type")
            return
        _arp = pkt.get_protocol(arp.arp)
        if not _arp:
            self.logger.info("Not ARP type")
        else:
            self.logger.info("Arp:{}".format(_arp))
        _ipv4 = pkt.get_protocol(ipv4.ipv4)
        if not _ipv4:
            self.logger.info("Not IPv4")
        else:
            self.logger.info("IPv4:{}".format(_ipv4))
        #スイッチのポート
        in_port = msg.match['in_port']
        #MACアドレス
        self.logger.info("Eth:{}".format(_eth))
        #IPv4アドレス
        #ipv4_src = ipv4_addr[0].src
        allowTransportFlag = True
        #allowTransportFlag = send_qsys(packet);#通信許可T/Fを返す
        if not(allowTransportFlag):#False
            #print('Drop:{}⇢{}'.format(ipv4_src))
            return
        #Transport to dst
        #print('Transport:{}⇢{}'.format(packet.ipv4_src))
        src = _eth.src
        dst = _eth.dst
        self.logger.info("in_port:{}".format(in_port))
        self.logger.info("dpid:{}".format(dpid))
        self.logger.info("mac_arc:{}".format(src))
        self.logger.info("ac_to_port:{}".format(self.mac_to_port))
        self.logger.info('json:{}'.format(json.dumps(ev.msg.to_jsondict(), ensure_ascii=True,
                                  indent=3, sort_keys=True)))
        #[swのid][MACAddr]のテーブルにSwitch input portを登録
        self.mac_to_port[dpid][mac_src] = in_port
        #該当するSWの中にMacAddrがあるか？
        if mac_dst in self.mac_to_port[dpid]:
            #Switch output portをテーブルから指定
            out_port = self.mac_to_port[dpid][mac_dst]
        else:
            #フラッディング
            out_port = ofproto.OFPP_FLOOD
        actions = [parser.OFPActionOutput(out_port)]
        out = datapath.ofproto_parser.OFPPacketOut(
            datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,
            actions=actions, data=msg.data)
        datapath.send_msg(out)

    def send_qsys(self, packet):
        return True#pktの到達許可

"""if __name__ == '__main__':
    import sys
    sys.argv.append(__name__)
    from ryu.cmd import manager
    manager.main()
"""
<commit_msg>no message<commit_after>#-*- coding: utf-8 -*-
import json
import enum
from ryu.app.simple_switch_13 import SimpleSwitch13
from ryu.controller  import ofp_event, event
from ryu.controller.handler import set_ev_cls,MAIN_DISPATCHER,CONFIG_DISPATCHER
from ryu.ofproto.ofproto_v1_3 import *
from ryu.ofproto.ofproto_v1_3_parser import OFPMatch
from ryu.ofproto.ofproto_parser import *
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ipv4
from qsysDataStructure import *
from ryu.controller import dpset

"""__DEBUG_MODE__ = 0#1:on,0:off
class SystemActionModei(enum.Enum):
   # あとでモード実装するはず？
learn = 0
quarantine = 1
"""

class QsysTest(SimpleSwitch13):
	#動作モード
    #ACTION_MODE = SystemActionMode.quarantine

    def __init__(self, *args, **kwargs):
        super(QsysTest, self).__init__(*args, **kwargs)
        self.mac_to_port = {}

    #packet_inハンドラ(override)
    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        allowTransportFlag = False
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})
        pkt = packet.Packet(msg.data)
        self.logger.info("packet-in {}".format(pkt))
        _eth = pkt.get_protocol(ethernet.ethernet)
        if not _eth:
            self.logger.info("Not Ether type")
            return
        _arp = pkt.get_protocol(arp.arp)
        if not _arp:
            self.logger.info("Not ARP type")
        else:
            self.logger.info("Arp:{}".format(_arp))
        _ipv4 = pkt.get_protocol(ipv4.ipv4)
        if not _ipv4:
            self.logger.info("Not IPv4")
        else:
            self.logger.info("IPv4:{}".format(_ipv4))
        #スイッチのポート
        in_port = msg.match['in_port']
        #MACアドレス
        self.logger.info("Eth:{}".format(_eth))
        #IPv4アドレス
        #ipv4_src = ipv4_addr[0].src
        allowTransportFlag = True
        #allowTransportFlag = send_qsys(packet);#通信許可T/Fを返す
        if not(allowTransportFlag):#False
            #print('Drop:{}⇢{}'.format(ipv4_src))
            return
        #Transport to dst
        #print('Transport:{}⇢{}'.format(packet.ipv4_src))
        src = _eth.src
        dst = _eth.dst
        self.logger.info("in_port:{}".format(in_port))
        self.logger.info("dpid:{}".format(dpid))
        self.logger.info("mac_arc:{}".format(src))
        self.logger.info("ac_to_port:{}".format(self.mac_to_port))
        self.logger.info('json:{}'.format(json.dumps(ev.msg.to_jsondict(), ensure_ascii=True,
                                  indent=3, sort_keys=True)))
        #[swのid][MACAddr]のテーブルにSwitch input portを登録
        self.mac_to_port[dpid][_eth.src] = in_port
        #該当するSWの中にMacAddrがあるか？
        if _eth.src in self.mac_to_port[dpid]:
            #Switch output portをテーブルから指定
            out_port = self.mac_to_port[dpid][_eth.dst]
        else:
            #フラッディング
            out_port = ofproto.OFPP_FLOOD
        actions = [parser.OFPActionOutput(out_port)]
        out = datapath.ofproto_parser.OFPPacketOut(
            datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,
            actions=actions, data=msg.data)
        datapath.send_msg(out)

    def send_qsys(self, packet):
        return True#pktの到達許可

"""if __name__ == '__main__':
    import sys
    sys.argv.append(__name__)
    from ryu.cmd import manager
    manager.main()
"""
<|endoftext|>


<commit_before>#!/usr/bin/env python
import socket
import os
import subprocess
import csv
import sys
import re
import time
import argparse

# Override builtin: raw_input was renamed to input in python3 (PEP 3111)
try:
    input = raw_input
except NameError:
    pass

def create_output_folder_name():
    """
    Returns the output folder name in format YYYY-MM-DD_output
    :return:
    """
    date_today = time.strftime("%Y-%m-%d")
    folder_name = "%s_output" % date_today
    return folder_name

def create_csv_file_name():
    """
    Returns the CSV file name in format Hr_Min_{AM/PM}.csv
    :return:
    """
    time_now = time.strftime("%I_%M_%p")
    csv_file_name = "%s.csv" % time_now
    if csv_file_name[0] == "0": # strip leading zero off
        csv_file_name = csv_file_name.lstrip('0')
    return csv_file_name

# Create the output folder name
folder_name = create_output_folder_name()

# Create the CSV file name
csv_file_name = create_csv_file_name()

def detect_os():
    """
    Detects OS of system and sets os commands for use in various functions.
    :return: dict()
    """
    os_info = {}
    if os.name == 'nt':  # Windows
        os_info['os'] = "win"
        os_info['arp_cmd'] = "arp -a {ip}"
        os_info['ping_cmd'] = "ping -n 1 {ip}"
    if os.name == 'posix':  # posix
        os_info['os'] = "posix"
        os_info['arp_cmd'] = "arp -a | grep -w {ip}"
        os_info['ping_cmd'] = "ping -c 1 {ip}"
    # check for OSX last because it also shows up as posix in os.name
    if sys.platform == 'darwin':  # OSX
        os_info['os'] = "osx"
        os_info['arp_cmd'] = "arp -a | grep -w {ip}"
        os_info['ping_cmd'] = "ping -c 1 {ip}"
    return os_info

detected_os = detect_os()

# Creates the output directory
def make_dir(folder_name):
    # Only create output folder if it doesn't exist yet
    if not os.path.exists("./%s" % folder_name):
        try:
            os.makedirs("./%s" % folder_name)
            print("Created output folder /%s" % folder_name)
        except OSError as err:
            print("Unable to create folder /%s" % folder_name)
            exists_error = re.search("exists", str(err))
            if exists_error: # in theory we should never trigger this
                print("Reason: Folder already exists.")
            perms_error = re.search("denied", str(err))
            if perms_error:
                print("Reason: Insufficient permissions.")
            if not exists_error and not perms_error:
                print("Encountered error while creating output folder:")
                print(err)

# Verifies correct format of IP xxx.xxx.xxx.xxx
def ipCheck(inputIP):
    ipregex = '\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)' \
              '{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b'
    validIP = re.match(ipregex, inputIP)
    if validIP:
        return True
    else:
        return False

# Given an IP, returns hostname
def nslooky(ip, detected_os):
    try:
        output = socket.gethostbyaddr(ip)
        return output[0]
    except Exception as err:
        if detected_os['os'] == 'osx':
            output = subprocess.Popen("smbutil status %s | grep Server" % ip, shell=True, stdout=subprocess.PIPE)
            output = output.communicate()
            if output[0] == "":
                output = "No hostname found"
                return output
            output = output[0].split(' ')[1].strip()
            return output
        not_found_error = re.search("not found", str(err))
        if not_found_error: # Win, catch [Errno 11004] host not found
            output = "No hostname found"
        else:
            output = "No hostname found"
        return output

# Returns name of pinged host
def getName(ip):
    try:
        name = nslooky(ip, detected_os)
    except Exception as err: # We shouldn't ever hit this, should catch this in nslooky()
        name = "Gen. except error in getName()"
    return name

# Creates titles (headers) in .csv output file
def titleCheck(folder_name, csv_file_name):
    exists = os.path.exists(r"./%s/%s" % (folder_name, csv_file_name))
    if exists == True:
        pass
    if exists == False:
        make_dir(folder_name)
        myfile = open("./%s/%s" % (folder_name, csv_file_name), "w")
        wr = csv.writer(myfile)
        titles = ["ip", "ping ms time", "hostname", "mac"]
        wr.writerow(titles)

# Returns ping ms response time of pinged host
def getPing_msResponse(ip, detected_os):
    ping = subprocess.Popen(detected_os['ping_cmd'].format(ip=ip), shell=True, stdout=subprocess.PIPE)
    pingResult = ping.communicate()
    ping_found = re.search(r'time[=<]?(\d*[\.]?\d*\s?ms)?', str(pingResult[0]))
    if ping_found and ping_found.group(1):
        ping_msResponse = ping_found.group(1)
    else:
        ping_msResponse = 'Host unreachable'
    return ping_msResponse

# Given an IP, returns MAC results
def getMac(ip, detected_os):
    def subprocArp(arpText):
        arp = subprocess.Popen(arpText, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        arp = arp.communicate()
        return arp
    arpResult = subprocArp(detected_os['arp_cmd'].format(ip=ip))
    find_mac = re.search(r'[\b\s]*(([0-9A-F]{2}[:-]){5}([0-9A-F]{2}))[\b\s]*',
                         str(arpResult[0].upper()))
    if find_mac:
        item = re.sub('-', ':', find_mac.group(1))
    else:
        item = 'No MAC addr. found'
    return item

def get_results(ip, folder_name, csv_file_name,
                start=1, end=255, get_all=False, csv_out=False):
    if csv_out:
        try:
            myfile = open("./%s/%s" % (folder_name, csv_file_name), "a")
            wr = csv.writer(myfile)
        except IOError as e:
            print("Could not open /{2}/{3}: I/O error({0}): {1}".format(
                  e.errno, e.strerror, folder_name, csv_file_name))
            sys.exit()
    print("\nResults:")
    if get_all:
        first_three = re.match(r'((\d{,3}\.\d{,3}\.\d{,3})\.)?(\d{,3})', ip)
        if int(end) <= 254:
            end += 1
        for address in range(int(start), int(end)):
            ip = first_three.group(1) + str(address)
            ping = getPing_msResponse(ip, detected_os)
            name = getName(ip)
            mac = getMac(ip, detected_os)
            if csv_out:
                wr.writerow([ip, ping, name, mac])
            print("%s %s %s %s" % (ip, ping, name, mac))
    else:
        ping = getPing_msResponse(ip, detected_os)
        name = getName(ip)
        mac = getMac(ip, detected_os)
        if csv_out:
            wr.writerow([ip, ping, name, mac])
        print("%s %s %s %s" % (ip, ping, name, mac))
    if csv_out:
        myfile.close()

def detect_ip(ip_address=None):
    """ Create a UDP socket connection to populate getsockname()
    The address does not actually need to resolve ie:
    Google DNS 8.8.8.8 used here
    :param ip_address:
    :return:
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('8.8.8.8', 80))
        ip_address = s.getsockname()[0]
    except socket.error:
        print("Failed to detect IP of current host!")
        choice = input("(I)nput host IP manually, or (Q)uit?: ")
        if choice.upper() == "I":
            while True:
                if not ip_address or not ipCheck(ip_address):
                    ip_address = input("INPUT IP: ")
                else:
                    break
        else:
            sys.exit("\nQuitting..")
    finally:
        s.close()
    return ip_address

def main(ip=None, start=1, end=255, get_all=False, csv_out=False):
    answer = int()
    ip_range = sorted([int(start), int(end)])  # ensure range from low to high
    while answer != 3:
        print('\n\nQuery based on IP: %s\n'
              '1) Continue with detected IP (entries for x.x.x.%s-%s)\n'
              '2) Enter another IP (creates one entry)\n'
              '3) Exit' % (ip, ip_range[0], int(ip_range[1])))
        try:
            if get_all:
                answer = 1
            else:
                answer = int(input("Selection? "))
            if answer == 1:
                get_all = True
                print('\n')
                if csv_out:
                    titleCheck(folder_name, csv_file_name)
                get_results(ip, folder_name, csv_file_name,
                            end=ip_range[1], start=ip_range[0],
                            get_all=get_all, csv_out=csv_out)
                get_all = False  # Clear the get_all flag to break loop
            elif answer == 2:
                choiceIP = input("Input IP: ")
                if ipCheck(choiceIP):
                    if csv_out:
                        titleCheck(folder_name, csv_file_name)
                    get_results(choiceIP, folder_name, csv_file_name,
                                start=ip_range[0], end=ip_range[1],
                                get_all=get_all, csv_out=csv_out)
                else:
                    print("Invalid IP")
            elif answer == 3:
                sys.exit()
        except ValueError:
            print("\n")
            print("Invalid entry")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="HostMAC")
    parser.add_argument('-csv', help='log output to csv', action='store_true',
                        required=False)
    parser.add_argument('-ip', default=detect_ip(),
                        help='specify ip, default: current ip', required=False)
    parser.add_argument('-all', help='check range 1-254', action='store_true',
                        required=False)
    parser.add_argument('-start', default=1, type=int, choices=range(1, 254),
                        metavar='', help='start of range', required=False)
    parser.add_argument('-end', default=255, type=int, choices=range(2, 255),
                        metavar='', help='end of range', required=False)
    args = parser.parse_args()
    try:
        main(ip=args.ip, start=args.start, end=args.end,
             get_all=args.all, csv_out=args.csv)
    except KeyboardInterrupt:
        print("\nCanceled by user.. Exiting.")
<commit_msg>add subproc_pipe_runner() function to avoid shell=True<commit_after>#!/usr/bin/env python
import socket
import os
import subprocess
import csv
import sys
import re
import time
import argparse
import shlex

# Override builtin: raw_input was renamed to input in python3 (PEP 3111)
try:
    input = raw_input
except NameError:
    pass

def create_output_folder_name():
    """
    Returns the output folder name in format YYYY-MM-DD_output
    :return:
    """
    date_today = time.strftime("%Y-%m-%d")
    folder_name = "%s_output" % date_today
    return folder_name

def create_csv_file_name():
    """
    Returns the CSV file name in format Hr_Min_{AM/PM}.csv
    :return:
    """
    time_now = time.strftime("%I_%M_%p")
    csv_file_name = "%s.csv" % time_now
    if csv_file_name[0] == "0": # strip leading zero off
        csv_file_name = csv_file_name.lstrip('0')
    return csv_file_name

# Create the output folder name
folder_name = create_output_folder_name()

# Create the CSV file name
csv_file_name = create_csv_file_name()

def detect_os():
    """
    Detects OS of system and sets os commands for use in various functions.
    :return: dict()
    """
    os_info = {}
    if os.name == 'nt':  # Windows
        os_info['os'] = "win"
        os_info['arp_cmd'] = "arp -a {ip}"
        os_info['ping_cmd'] = "ping -n 1 {ip}"
    if os.name == 'posix':  # posix
        os_info['os'] = "posix"
        os_info['arp_cmd'] = "arp -a | grep -w {ip}"
        os_info['ping_cmd'] = "ping -c 1 {ip}"
    # check for OSX last because it also shows up as posix in os.name
    if sys.platform == 'darwin':  # OSX
        os_info['os'] = "osx"
        os_info['arp_cmd'] = "arp -a | grep -w {ip}"
        os_info['ping_cmd'] = "ping -c 1 {ip}"
    return os_info

detected_os = detect_os()

def subproc_pipe_runner(ip, command):
    """
    Takes an ip and a "raw" shell input command. Splits it on "|" if present,
    and runs it without dependency on shell=True.
    :param command:
    :return:
    """
    command = command.replace("{ip}", "{0}")

    #print(ip)
    #print(command)
    command = command.format(ip)
    #print(command)

    # get both piped and unpiped commands into the same format (ie, a list with one value)
    if "|" in command:
        new_command = command.split("|")
    else:
        new_command = []
        new_command.append(command)

    #print(new_command)

    if len(new_command) == 1:
        process_one = subprocess.Popen(shlex.split("{0}".format(new_command[0])), stdout=subprocess.PIPE)
        #print("process one: ".format(process_one))
        #process_one.stdout.close()
        output = process_one.communicate()
        #print(output)
        return output
    if len(new_command) == 2:
        process_one = subprocess.Popen(shlex.split("{0}".format(new_command[0])), stdout=subprocess.PIPE)
        process_two = subprocess.Popen(shlex.split("{0}".format(new_command[1])), stdin=process_one.stdout, stdout=subprocess.PIPE)
        process_one.stdout.close()
        output = process_two.communicate()
        #print(output)
        return output

# Creates the output directory
def make_dir(folder_name):
    # Only create output folder if it doesn't exist yet
    if not os.path.exists("./%s" % folder_name):
        try:
            os.makedirs("./%s" % folder_name)
            print("Created output folder /%s" % folder_name)
        except OSError as err:
            print("Unable to create folder /%s" % folder_name)
            exists_error = re.search("exists", str(err))
            if exists_error: # in theory we should never trigger this
                print("Reason: Folder already exists.")
            perms_error = re.search("denied", str(err))
            if perms_error:
                print("Reason: Insufficient permissions.")
            if not exists_error and not perms_error:
                print("Encountered error while creating output folder:")
                print(err)

# Verifies correct format of IP xxx.xxx.xxx.xxx
def ipCheck(inputIP):
    ipregex = '\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)' \
              '{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b'
    validIP = re.match(ipregex, inputIP)
    if validIP:
        return True
    else:
        return False

# Given an IP, returns hostname
def nslooky(ip, detected_os):
    try:
        output = socket.gethostbyaddr(ip)
        return output[0]
    except Exception as err:
        if detected_os['os'] == 'osx':
            #output = subprocess.Popen("smbutil status %s | grep Server" % ip, shell=True, stdout=subprocess.PIPE)
            #output = output.communicate()

            output = subproc_pipe_runner(ip, "smbutil status %s | grep Server" % ip)

            if output[0] == "":
                output = "No hostname found"
                return output
            output = output[0].split(' ')[1].strip()
            return output
        not_found_error = re.search("not found", str(err))
        if not_found_error: # Win, catch [Errno 11004] host not found
            output = "No hostname found"
        else:
            output = "No hostname found"
        return output

# Returns name of pinged host
def getName(ip):
    try:
        name = nslooky(ip, detected_os)
    except Exception as err: # We shouldn't ever hit this, should catch this in nslooky()
        name = "Gen. except error in getName()"
    return name

# Creates titles (headers) in .csv output file
def titleCheck(folder_name, csv_file_name):
    exists = os.path.exists(r"./%s/%s" % (folder_name, csv_file_name))
    if exists == True:
        pass
    if exists == False:
        make_dir(folder_name)
        myfile = open("./%s/%s" % (folder_name, csv_file_name), "w")
        wr = csv.writer(myfile)
        titles = ["ip", "ping ms time", "hostname", "mac"]
        wr.writerow(titles)

# Returns ping ms response time of pinged host
def getPing_msResponse(ip, detected_os):
    #ping = subprocess.Popen(detected_os['ping_cmd'].format(ip=ip), shell=True, stdout=subprocess.PIPE)
    pingResult = subproc_pipe_runner(ip, detected_os['ping_cmd'])
    #pingResult = ping.communicate()
    ping_found = re.search(r'time[=<]?(\d*[\.]?\d*\s?ms)?', str(pingResult[0]))
    if ping_found and ping_found.group(1):
        ping_msResponse = ping_found.group(1)
    else:
        ping_msResponse = 'Host unreachable'
    return ping_msResponse

# Given an IP, returns MAC results
def getMac(ip, detected_os):
    # def subprocArp(arpText):
    #     arp = subprocess.Popen(arpText, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    #     arp = arp.communicate()
    #     return arp
    arpResult = subproc_pipe_runner(ip, detected_os['arp_cmd'])
    #arpResult = subprocArp(detected_os['arp_cmd'].format(ip=ip))
    find_mac = re.search(r'[\b\s]*(([0-9A-F]{2}[:-]){5}([0-9A-F]{2}))[\b\s]*',
                         str(arpResult[0].upper()))
    if find_mac:
        item = re.sub('-', ':', find_mac.group(1))
    else:
        item = 'No MAC addr. found'
    return item

def get_results(ip, folder_name, csv_file_name,
                start=1, end=255, get_all=False, csv_out=False):
    if csv_out:
        try:
            myfile = open("./%s/%s" % (folder_name, csv_file_name), "a")
            wr = csv.writer(myfile)
        except IOError as e:
            print("Could not open /{2}/{3}: I/O error({0}): {1}".format(
                  e.errno, e.strerror, folder_name, csv_file_name))
            sys.exit()
    print("\nResults:")
    if get_all:
        first_three = re.match(r'((\d{,3}\.\d{,3}\.\d{,3})\.)?(\d{,3})', ip)
        if int(end) <= 254:
            end += 1
        for address in range(int(start), int(end)):
            ip = first_three.group(1) + str(address)
            ping = getPing_msResponse(ip, detected_os)
            name = getName(ip)
            mac = getMac(ip, detected_os)
            if csv_out:
                wr.writerow([ip, ping, name, mac])
            print("%s %s %s %s" % (ip, ping, name, mac))
    else:
        ping = getPing_msResponse(ip, detected_os)
        name = getName(ip)
        mac = getMac(ip, detected_os)
        if csv_out:
            wr.writerow([ip, ping, name, mac])
        print("%s %s %s %s" % (ip, ping, name, mac))
    if csv_out:
        myfile.close()

def detect_ip(ip_address=None):
    """ Create a UDP socket connection to populate getsockname()
    The address does not actually need to resolve ie:
    Google DNS 8.8.8.8 used here
    :param ip_address:
    :return:
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('8.8.8.8', 80))
        ip_address = s.getsockname()[0]
    except socket.error:
        print("Failed to detect IP of current host!")
        choice = input("(I)nput host IP manually, or (Q)uit?: ")
        if choice.upper() == "I":
            while True:
                if not ip_address or not ipCheck(ip_address):
                    ip_address = input("INPUT IP: ")
                else:
                    break
        else:
            sys.exit("\nQuitting..")
    finally:
        s.close()
    return ip_address

def main(ip=None, start=1, end=255, get_all=False, csv_out=False):
    answer = int()
    ip_range = sorted([int(start), int(end)])  # ensure range from low to high
    while answer != 3:
        print('\n\nQuery based on IP: %s\n'
              '1) Continue with detected IP (entries for x.x.x.%s-%s)\n'
              '2) Enter another IP (creates one entry)\n'
              '3) Exit' % (ip, ip_range[0], int(ip_range[1])))
        try:
            if get_all:
                answer = 1
            else:
                answer = int(input("Selection? "))
            if answer == 1:
                get_all = True
                print('\n')
                if csv_out:
                    titleCheck(folder_name, csv_file_name)
                get_results(ip, folder_name, csv_file_name,
                            end=ip_range[1], start=ip_range[0],
                            get_all=get_all, csv_out=csv_out)
                get_all = False  # Clear the get_all flag to break loop
            elif answer == 2:
                choiceIP = input("Input IP: ")
                if ipCheck(choiceIP):
                    if csv_out:
                        titleCheck(folder_name, csv_file_name)
                    get_results(choiceIP, folder_name, csv_file_name,
                                start=ip_range[0], end=ip_range[1],
                                get_all=get_all, csv_out=csv_out)
                else:
                    print("Invalid IP")
            elif answer == 3:
                sys.exit()
        except ValueError:
            print("\n")
            print("Invalid entry")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="HostMAC")
    parser.add_argument('-csv', help='log output to csv', action='store_true',
                        required=False)
    parser.add_argument('-ip', default=detect_ip(),
                        help='specify ip, default: current ip', required=False)
    parser.add_argument('-all', help='check range 1-254', action='store_true',
                        required=False)
    parser.add_argument('-start', default=1, type=int, choices=range(1, 254),
                        metavar='', help='start of range', required=False)
    parser.add_argument('-end', default=255, type=int, choices=range(2, 255),
                        metavar='', help='end of range', required=False)
    args = parser.parse_args()
    try:
        main(ip=args.ip, start=args.start, end=args.end,
             get_all=args.all, csv_out=args.csv)
    except KeyboardInterrupt:
        print("\nCanceled by user.. Exiting.")
<|endoftext|>


<commit_before>import socket
import os
import subprocess
import csv
import sys
import re

# Creates the /output directory
def makeDir():
    try:
        os.makedirs("./output")
    except OSError:
        pass

# Verifies correct format of IP xxx.xxx.xxx.xxx
def ipCheck(inputIP):
    ipregex = '\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)' \
              '{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b'
    validIP = re.match(ipregex, inputIP)
    if validIP:
        return True
    else:
        return False

# Given an IP, returns hostname (of client running hostmac.py)
def nslooky(ip):
    if sys.platform == 'darwin': # OSX
        output = subprocess.Popen("smbutil status %s | grep Server" % ip, shell=True, stdout=subprocess.PIPE)
        output = output.communicate()
        output = output[0].split(' ')[1].strip()
        #print output
        return output
        #return output
    else:
        try:
            output = socket.gethostbyaddr(ip)
            return output[0]
        except:
            output = "No host name found"
            return output

# Creates titles (headers) in .csv output file
def titleCheck():
    exists = os.path.exists(r"./output/ip.csv")
    if exists == True:
        pass
    if exists == False:
        makeDir()
        myfile = open("./output/ip.csv", "ab+")
        wr = csv.writer(myfile)
        titles = ["ip", "ping ms time", "hostname", "mac"]
        wr.writerow(titles)

# Returns ping ms response time of pinged host
def getPing_msResponse(ip):
    if os.name == 'nt':  # Windows
        pingText = "ping -n 1 " + ip
    elif os.name =='posix':  # *nix or OSX
        pingText = "ping -c 1 " + ip
    ping = subprocess.Popen(pingText, shell=True, stdout=subprocess.PIPE)
    pingResult = ping.communicate()
    if os.name == 'nt':  # Windows
        ping_found = re.search(r'time.*ms', pingResult[0])
        if ping_found:
            ping_msResponseFull = ping_found.group()
            ping_msResponse = ping_msResponseFull[5:]
        else:
            ping_msResponse = 'Host Unreachable'
    elif os.name == 'posix':  # *nix or OSX
        ping_found = re.search(r'time=(.*\sms)?', pingResult[0])
        if ping_found:
            ping_msResponse = ping_found.group(1)
        else:
            ping_msResponse = 'Host Unreachable'
    return ping_msResponse

# Returns name of pinged host
def getName(ip):
    try:
        name = nslooky(ip)
        print "name in getName():", name
        name = name.split(".")[0]
    except:
        name = "Exception; error in getName()!"
    return name

# Given an IP, returns MAC results
def getMac(ip):
    #arpText = "arp -a " + ip
    #arp = subprocess.Popen(arpText, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    def subprocArp(arpText):
        arp = subprocess.Popen(arpText, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        arp = arp.communicate()
        #print "arp in subprocArp(): ", arp
        return arp

    #arpResult = arp.communicate()
    if os.name == 'nt':  # Windows
        #arpText = "arp -a " + ip
        arpResult = subprocArp("arp -a %s" % ip)
        try:
            if arpResult[0].startswith("No ARP"):
                item = "MAC not found-No ARP entry"
            if arpResult[0].split("\n")[1].startswith("Interface:"):
                item = arpResult[0].split("\n")[-2]
                item = item.split()[1]
                item = item.replace("-", ":").upper()
            if arpResult[1] == None:
                item = "ARP-bad argument"
        except IndexError:
            if arpResult[1].startswith("ARP: bad argument"):
                item = "ARP: bad argument"
        except:
            item = "General except error in getMac()"
    if os.name == 'posix':  # Linux
        arpResult = subprocArp("arp -a | grep -w %s" % ip)
        find_mac = re.search(r'\s(([0-9A-F]{2}[:-]){5}([0-9A-F]{2}))?\s',
                             arpResult[0].upper())
        if find_mac:
            item = find_mac.group(1)
        else:
            item = 'No MAC Found'
    return item

def getOne(ip):
    print
    try:
        myfile = open("./output/ip.csv", "ab+")
    except IOError as (errno, strerror):
        print "Could not open /output/ip.csv: I/O error({0}): {1}".format(errno, strerror)
        sys.exit()
    wr = csv.writer(myfile)
    ping = getPing_msResponse(ip)
    name = getName(ip)
    mac = getMac(ip)
    csvOut = [ip, ping, name, mac]
    wr.writerow(csvOut)
    print "%s %s %s %s" % (ip, ping, name, mac)
    myfile.close()

def getAll(ip):
    try:
        myfile = open("./output/ip.csv", "ab+")
    except IOError as (errno, strerror):
        print "Could not open /output/ip.csv: I/O error({0}): {1}".format(errno, strerror)
        sys.exit()
    wr = csv.writer(myfile)
    firstThree = ip.split(".")[0] + "." + ip.split(".")[1] + "." + ip.split(".")[2] + "."
    last = "1"
    while int(last) <= 254:
        ip = firstThree + last
        ping = getPing_msResponse(ip)
        name = getName(ip)
        mac = getMac(ip)
        csvOut = [ip, ping, name, mac]
        wr.writerow(csvOut)
        last = str(int(last) + 1)
        print "%s %s %s %s" % (ip, ping, name, mac)
    myfile.close()

def detect_ip(ip_address=None):
    """ Create a UDP socket connection to populate getsockname()
    The address does not actually need to resolve ie: 1.2.3.4
    :param ip_address:
    :return:
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('1.2.3.4', 0))
        ip_address = s.getsockname()[0]
    except socket.error:
        try:
            # OSX doesn't like port 0, use Google public DNS and port 80
            s.connect(('8.8.8.8', 80))
            ip_address = s.getsockname()[0]
        except socket.error:
            print("Failed to detect IP of current host!")
            choice = raw_input("(I)nput host IP manually, or (Q)uit?: ")
            if choice.upper() == "I":
                while True:
                    if not ip_address or not ipCheck(ip_address):
                        ip_address = raw_input("INPUT IP: ")
                    else:
                        break
            else:
                sys.exit("Quitting..")
    finally:
        s.close()
    return ip_address

while True:
    ip = detect_ip()
    print
    print "Detected IP: " + ip
    print
    print "1) Continue with detected IP (creates 254 entries)"
    print "2) Enter another IP (creates one entry)"
    print "3) Exit"
    print
    try:
        answer = int(raw_input("Selection? "))
        if answer == 1:
            print
            titleCheck()
            getAll(ip)
            sys.exit()
        elif answer == 2:
            print
            choiceIP = raw_input("Input IP: ")
            trueFalse = ipCheck(choiceIP)
            if trueFalse == True:
                titleCheck()
                getOne(choiceIP)
                sys.exit()
            if trueFalse == False:
                print
                print "Invalid IP"
        elif answer == 3:
            sys.exit()
    except ValueError:
        print
        print "Invalid entry"
<commit_msg>improved OSX functionality: detects IP and uses smbutil to try to find NetBIOS names<commit_after>import socket
import os
import subprocess
import csv
import sys
import re

# Creates the /output directory
def makeDir():
    try:
        os.makedirs("./output")
    except OSError:
        pass

# Verifies correct format of IP xxx.xxx.xxx.xxx
def ipCheck(inputIP):
    ipregex = '\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)' \
              '{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b'
    validIP = re.match(ipregex, inputIP)
    if validIP:
        return True
    else:
        return False

# Given an IP, returns hostname (of client running hostmac.py)
def nslooky(ip):
    try:
        output = socket.gethostbyaddr(ip)
        return output[0]
    except:
        if sys.platform == 'darwin': # OSX
            output = subprocess.Popen("smbutil status %s | grep Server" % ip, shell=True, stdout=subprocess.PIPE)
            output = output.communicate()
            if output[0] == "":
                output = "No host name found"
                return output
            output = output[0].split(' ')[1].strip()
            #print output
            return output
            #return output
        else:
            output = "No host name found"
            return output

# Creates titles (headers) in .csv output file
def titleCheck():
    exists = os.path.exists(r"./output/ip.csv")
    if exists == True:
        pass
    if exists == False:
        makeDir()
        myfile = open("./output/ip.csv", "ab+")
        wr = csv.writer(myfile)
        titles = ["ip", "ping ms time", "hostname", "mac"]
        wr.writerow(titles)

# Returns ping ms response time of pinged host
def getPing_msResponse(ip):
    if os.name == 'nt':  # Windows
        pingText = "ping -n 1 " + ip
    elif os.name =='posix':  # *nix or OSX
        pingText = "ping -c 1 " + ip
    ping = subprocess.Popen(pingText, shell=True, stdout=subprocess.PIPE)
    pingResult = ping.communicate()
    if os.name == 'nt':  # Windows
        ping_found = re.search(r'time.*ms', pingResult[0])
        if ping_found:
            ping_msResponseFull = ping_found.group()
            ping_msResponse = ping_msResponseFull[5:]
        else:
            ping_msResponse = 'Host Unreachable'
    elif os.name == 'posix':  # *nix or OSX
        ping_found = re.search(r'time=(.*\sms)?', pingResult[0])
        if ping_found:
            ping_msResponse = ping_found.group(1)
        else:
            ping_msResponse = 'Host Unreachable'
    return ping_msResponse

# Returns name of pinged host
def getName(ip):
    try:
        name = nslooky(ip)
        #print "name in getName():", name #debugging
        #name = name.split(".")[0]
    except:
        name = "Error in getName()"
    return name

# Given an IP, returns MAC results
def getMac(ip):
    #arpText = "arp -a " + ip
    #arp = subprocess.Popen(arpText, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    def subprocArp(arpText):
        arp = subprocess.Popen(arpText, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        arp = arp.communicate()
        #print "arp in subprocArp(): ", arp
        return arp

    #arpResult = arp.communicate()
    if os.name == 'nt':  # Windows
        #arpText = "arp -a " + ip
        arpResult = subprocArp("arp -a %s" % ip)
        try:
            if arpResult[0].startswith("No ARP"):
                item = "MAC not found-No ARP entry"
            if arpResult[0].split("\n")[1].startswith("Interface:"):
                item = arpResult[0].split("\n")[-2]
                item = item.split()[1]
                item = item.replace("-", ":").upper()
            if arpResult[1] == None:
                item = "ARP-bad argument"
        except IndexError:
            if arpResult[1].startswith("ARP: bad argument"):
                item = "ARP: bad argument"
        except:
            item = "General except error in getMac()"
    if os.name == 'posix':  # Linux
        arpResult = subprocArp("arp -a | grep -w %s" % ip)
        find_mac = re.search(r'\s(([0-9A-F]{2}[:-]){5}([0-9A-F]{2}))?\s',
                             arpResult[0].upper())
        if find_mac:
            item = find_mac.group(1)
        else:
            item = 'No MAC Found'
    return item

def getOne(ip):
    print
    try:
        myfile = open("./output/ip.csv", "ab+")
    except IOError as (errno, strerror):
        print "Could not open /output/ip.csv: I/O error({0}): {1}".format(errno, strerror)
        sys.exit()
    wr = csv.writer(myfile)
    ping = getPing_msResponse(ip)
    name = getName(ip)
    mac = getMac(ip)
    csvOut = [ip, ping, name, mac]
    wr.writerow(csvOut)
    print "%s %s %s %s" % (ip, ping, name, mac)
    myfile.close()

def getAll(ip):
    try:
        myfile = open("./output/ip.csv", "ab+")
    except IOError as (errno, strerror):
        print "Could not open /output/ip.csv: I/O error({0}): {1}".format(errno, strerror)
        sys.exit()
    wr = csv.writer(myfile)
    firstThree = ip.split(".")[0] + "." + ip.split(".")[1] + "." + ip.split(".")[2] + "."
    last = "1"
    while int(last) <= 254:
        ip = firstThree + last
        ping = getPing_msResponse(ip)
        name = getName(ip)
        mac = getMac(ip)
        csvOut = [ip, ping, name, mac]
        wr.writerow(csvOut)
        last = str(int(last) + 1)
        print "%s %s %s %s" % (ip, ping, name, mac)
    myfile.close()

def detect_ip(ip_address=None):
    """ Create a UDP socket connection to populate getsockname()
    The address does not actually need to resolve ie: 1.2.3.4
    :param ip_address:
    :return:
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('1.2.3.4', 0))
        ip_address = s.getsockname()[0]
    except socket.error:
        try:
            # OSX doesn't like port 0, use Google public DNS and port 80
            s.connect(('8.8.8.8', 80))
            ip_address = s.getsockname()[0]
        except socket.error:
            print("Failed to detect IP of current host!")
            choice = raw_input("(I)nput host IP manually, or (Q)uit?: ")
            if choice.upper() == "I":
                while True:
                    if not ip_address or not ipCheck(ip_address):
                        ip_address = raw_input("INPUT IP: ")
                    else:
                        break
            else:
                sys.exit("Quitting..")
    finally:
        s.close()
    return ip_address

while True:
    ip = detect_ip()
    print
    print "Detected IP: " + ip
    print
    print "1) Continue with detected IP (creates 254 entries)"
    print "2) Enter another IP (creates one entry)"
    print "3) Exit"
    print
    try:
        answer = int(raw_input("Selection? "))
        if answer == 1:
            print
            titleCheck()
            getAll(ip)
            sys.exit()
        elif answer == 2:
            print
            choiceIP = raw_input("Input IP: ")
            trueFalse = ipCheck(choiceIP)
            if trueFalse == True:
                titleCheck()
                getOne(choiceIP)
                sys.exit()
            if trueFalse == False:
                print
                print "Invalid IP"
        elif answer == 3:
            sys.exit()
    except ValueError:
        print
        print "Invalid entry"
<|endoftext|>


<commit_before>"""
Simple API to docker.
"""

import requests
from paramiko import SSHClient, SSHException, AutoAddPolicy
from git import Repository
from config import config
from subprocess import check_output
from datetime import datetime
from dateutil.parser import parse as parse_date
import socket

class Container:
    """
    Class representing a container, providing the necessary information and
    operations.
    """
    def __init__(self, data):
        """
        :param dict data: dict data: The dataset returned by the Docker API.
        """
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return containers()

    @classmethod
    def create(cls, name, image, volumes):
        return create(name, image, volumes)

    @property
    def id(self):
        """
        The containers Id.

        :rtype: str
        """
        return self.__data['Id']

    @property
    def image(self):
        """
        The image's id the container was created from.

        :rtype: str
        """
        return self.__data['Image']

    @property
    def name(self):
        """
        The containers name.

        :rtype: str
        """
        return self.__data['Name']

    @property
    def project(self):
        """
        The containers project. First segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[0].strip('/')

    @property
    def instance(self):
        """
        The containers instance. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[1]

    @property
    def hash(self):
        """
        The containers git hash. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[2]

    @property
    def domain(self):
        """
        The containers internal domain name.

        :rtype: str
        """
        if self.project is self.instance:
            return "%s.dork" % self.project
        else:
            return "%s.%s.dork" % (self.project, self.instance)

    @property
    def running(self):
        """
        Check if the container is running.

        :rtype: bool
        """
        return self.__data['State']['Running']

    @property
    def address(self):
        """
        The containers IP address, or [None] if the container is not running.

        :rtype: str
        """
        if self.running:
            return self.__data['NetworkSettings']['IPAddress']
        else:
            return None

    @property
    def source(self):
        """
        The directory on the host machine, mounted to the containers source
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_source_directory:
                directory = host
        return directory

    @property
    def repository(self):
        """
        Retrieve the containers source git repository.

        :rtype: Repository
        """
        return Repository(self.source)

    @property
    def build(self):
        """
        The directory on the host machine, mounted to the containers build
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_build_directory:
                directory = host
        return directory

    @property
    def accessible(self):
        """:rtype: bool"""
        if not self.running:
            return False
        else:
            return _container_accessible(self.address)

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    @property
    def time_started(self):
        """:rtype: datetime"""
        if self.running:
            return parse_date(self.__data['State']['StartedAt'])
        else:
            return None

    @property
    def time_stopped(self):
        """:rtype: datetime"""
        if self.running:
            return None
        else:
            return parse_date(self.__data['State']['FinishedAt'])

    def start(self):
        _container_start(self.id)

    def stop(self):
        _container_stop(self.id)

    def remove(self):
        _container_remove(self.id)

    def rename(self, name):
        _container_rename(self.id, name)

    def commit(self, repo):
        _container_commit(self.id, repo)

class Image:
    def __init__(self, data):
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return images()

    @classmethod
    def dangling(cls):
        return _dangling_images()

    @property
    def id(self):
        """:rtype: str"""
        return self.__data['Id']

    @property
    def name(self):
        """:rtype: str"""
        return self.__data['RepoTags'][0].split(':')[0]

    @property
    def project(self):
        """:rtype: str"""
        return self.name.split('/')[0]

    @property
    def hash(self):
        """:rtype: str"""
        return self.name.split('/')[1]

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    def delete(self):
        _image_remove(self.id)

class BaseImage:
    def __init__(self, project):
        self.project = project
        self.name = config().base_image
        self.hash = 'new'

# ======================================================================
# PUBLIC METHODS
# ======================================================================
def containers():
    for c in __get('containers/json', query={'all': 1}):
        yield Container(__get('containers/%s/json' % c['Id']))

def images():
    for i in __get('images/json'):
        data = __get('images/%s/json' % i['Id'])
        if 'RepoTags' in i:
            data['RepoTags'] = i['RepoTags']
            yield Image(data)

def create(name, image, volumes):
    """:type volumes: dict"""
    data = {
        'Image': image,
        'Volumes': {},
        'HostConfig': {
            'Binds': [],
        },
    }
    for host in volumes:
        container = volumes[host]
        data['Volumes'][container] = {}
        data['HostConfig']['Binds'].append("%s:%s" % (host, container))
    __post(
        'containers/create',
        query={'name': name},
        data=data,
        codes=(201,))

def _dangling_images():
    image_ids = check_output([
        'docker', 'images', '-q', '-f', 'dangling=true'
    ]).splitlines()
    for iid in image_ids:
        yield Image(__get('images/%s/json' % iid))

# ======================================================================
# PROTECTED METHODS
# ======================================================================
def _container_start(cid):
    __post('containers/%s/start' % cid, codes=(204, 304))

def _container_stop(cid):
    __post('containers/%s/stop' % cid, codes=(204, 304))

def _container_remove(cid):
    __delete('containers/%s' % cid, codes=(204,))

def _container_rename(cid, name):
    __post(
        'containers/%s/rename' % cid,
        query={'name': name}, codes=(204,))

def _container_commit(cid, repo):
    __post(
        'commit',
        query={'container': cid, 'repo': repo},
        codes=(201,))

def _container_accessible(address):
    client = SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(AutoAddPolicy())
    try:
        client.connect(address, username=config().dork_user, look_for_keys=True)
        return True
    except socket.error:
        return False

def _image_remove(iid):
    __delete('images/%s' % iid, codes=(200,))

# ======================================================================
# PRIVATE METHODS
# ======================================================================
class DockerException(Exception):
    def __init__(self, msg, code):
        super(DockerException, self).__init__(msg)
        self.code = code

def __get(path, query=(), codes=(200,)):
    """
    :param str path:
    :param dict[str,str] query:
    :param list[int] codes:
    :return: json
    """

    result = requests.get(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code in codes:
        return result.json()
    else:
        raise DockerException(result.status_code, result.text)

def __post(path, query=(), data=(), codes=(200,)):

    if data:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query, json=data)
    else:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)

def __delete(path, query=(), codes=(200,)):

    result = requests.delete(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)
<commit_msg>Cached docker io operations.<commit_after>"""
Simple API to docker.
"""

import requests
from paramiko import SSHClient, SSHException, AutoAddPolicy
from git import Repository
from config import config
from subprocess import check_output
from datetime import datetime
from dateutil.parser import parse as parse_date
import socket

class Container:
    """
    Class representing a container, providing the necessary information and
    operations.
    """
    def __init__(self, data):
        """
        :param dict data: dict data: The dataset returned by the Docker API.
        """
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return containers()

    @classmethod
    def create(cls, name, image, volumes):
        return create(name, image, volumes)

    @property
    def id(self):
        """
        The containers Id.

        :rtype: str
        """
        return self.__data['Id']

    @property
    def image(self):
        """
        The image's id the container was created from.

        :rtype: str
        """
        return self.__data['Image']

    @property
    def name(self):
        """
        The containers name.

        :rtype: str
        """
        return self.__data['Name']

    @property
    def project(self):
        """
        The containers project. First segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[0].strip('/')

    @property
    def instance(self):
        """
        The containers instance. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[1]

    @property
    def hash(self):
        """
        The containers git hash. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[2]

    @property
    def domain(self):
        """
        The containers internal domain name.

        :rtype: str
        """
        if self.project is self.instance:
            return "%s.dork" % self.project
        else:
            return "%s.%s.dork" % (self.project, self.instance)

    @property
    def running(self):
        """
        Check if the container is running.

        :rtype: bool
        """
        return self.__data['State']['Running']

    @property
    def address(self):
        """
        The containers IP address, or [None] if the container is not running.

        :rtype: str
        """
        if self.running:
            return self.__data['NetworkSettings']['IPAddress']
        else:
            return None

    @property
    def source(self):
        """
        The directory on the host machine, mounted to the containers source
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_source_directory:
                directory = host
        return directory

    @property
    def repository(self):
        """
        Retrieve the containers source git repository.

        :rtype: Repository
        """
        return Repository(self.source)

    @property
    def build(self):
        """
        The directory on the host machine, mounted to the containers build
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_build_directory:
                directory = host
        return directory

    @property
    def accessible(self):
        """:rtype: bool"""
        if not self.running:
            return False
        else:
            return _container_accessible(self.address)

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    @property
    def time_started(self):
        """:rtype: datetime"""
        if self.running:
            return parse_date(self.__data['State']['StartedAt'])
        else:
            return None

    @property
    def time_stopped(self):
        """:rtype: datetime"""
        if self.running:
            return None
        else:
            return parse_date(self.__data['State']['FinishedAt'])

    def start(self):
        _container_start(self.id)

    def stop(self):
        _container_stop(self.id)

    def remove(self):
        _container_remove(self.id)

    def rename(self, name):
        _container_rename(self.id, name)

    def commit(self, repo):
        _container_commit(self.id, repo)

class Image:
    def __init__(self, data):
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return images()

    @classmethod
    def dangling(cls):
        return _dangling_images()

    @property
    def id(self):
        """:rtype: str"""
        return self.__data['Id']

    @property
    def name(self):
        """:rtype: str"""
        return self.__data['RepoTags'][0].split(':')[0]

    @property
    def project(self):
        """:rtype: str"""
        return self.name.split('/')[0]

    @property
    def hash(self):
        """:rtype: str"""
        return self.name.split('/')[1]

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    def delete(self):
        _image_remove(self.id)

class BaseImage:
    def __init__(self, project):
        self.project = project
        self.name = config().base_image
        self.hash = 'new'

# ======================================================================
# PUBLIC METHODS
# ======================================================================
__containers = None
def containers(clear=False):
    global __containers
    if __containers is None or clear:
        __containers = [Container(__get('containers/%s/json' % c['Id']))
                          for c in __get('containers/json', query={'all': 1})]
    return __containers

__images = None
def images(clear=False):
    global __images
    if __images is None or clear:
        __images = []
        for i in __get('images/json'):
            data = __get('images/%s/json' % i['Id'])
            if 'RepoTags' in i:
                data['RepoTags'] = i['RepoTags']
                __images.append(Image(data))
    return __images

def create(name, image, volumes):
    """:type volumes: dict"""
    data = {
        'Image': image,
        'Volumes': {},
        'HostConfig': {
            'Binds': [],
        },
    }
    for host in volumes:
        container = volumes[host]
        data['Volumes'][container] = {}
        data['HostConfig']['Binds'].append("%s:%s" % (host, container))
    __post(
        'containers/create',
        query={'name': name},
        data=data,
        codes=(201,))
    containers(True)

def _dangling_images():
    image_ids = check_output([
        'docker', 'images', '-q', '-f', 'dangling=true'
    ]).splitlines()
    for iid in image_ids:
        yield Image(__get('images/%s/json' % iid))

# ======================================================================
# PROTECTED METHODS
# ======================================================================
def _container_start(cid):
    __post('containers/%s/start' % cid, codes=(204, 304))
    containers(True)

def _container_stop(cid):
    __post('containers/%s/stop' % cid, codes=(204, 304))
    containers(True)

def _container_remove(cid):
    __delete('containers/%s' % cid, codes=(204,))
    containers(True)

def _container_rename(cid, name):
    __post(
        'containers/%s/rename' % cid,
        query={'name': name}, codes=(204,))
    containers(True)

def _container_commit(cid, repo):
    __post(
        'commit',
        query={'container': cid, 'repo': repo},
        codes=(201,))
    images(True)

def _container_accessible(address):
    client = SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(AutoAddPolicy())
    try:
        client.connect(address, username=config().dork_user, look_for_keys=True)
        return True
    except socket.error:
        return False

def _image_remove(iid):
    __delete('images/%s' % iid, codes=(200,))
    images(True)

# ======================================================================
# PRIVATE METHODS
# ======================================================================
class DockerException(Exception):
    def __init__(self, msg, code):
        super(DockerException, self).__init__(msg)
        self.code = code

def __get(path, query=(), codes=(200,)):
    """
    :param str path:
    :param dict[str,str] query:
    :param list[int] codes:
    :return: json
    """

    result = requests.get(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code in codes:
        return result.json()
    else:
        raise DockerException(result.status_code, result.text)

def __post(path, query=(), data=(), codes=(200,)):

    if data:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query, json=data)
    else:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)

def __delete(path, query=(), codes=(200,)):

    result = requests.delete(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

__all__ = ('parse', 'parse_file', 'ParseError')

class ParseError(ValueError):
    pass

def parse_file(filename):
    with open(filename) as fileobj:
        return parse(fileobj)

def parse(fileobj):
    section_stack = []
    res = {}
    for line in fileobj:
        line = line.strip()
        if not line:
            continue
        elif line.startswith('['):
            (depth, section_name) = parse_section(line)
            diff = len(section_stack) - depth + 1
            if diff < 0:
                msg = 'Too high depth for subsection, missed previous'
                raise ParseError(msg)
            for _ in xrange(diff):
                section_stack.pop()

            reduce(dict.__getitem__, section_stack, res)[section_name] = {}
            section_stack.append(section_name)
        elif line.startswith('#'):
            pass
        elif '=' in line:
            (key, value) = parse_assignment(line)
            reduce(dict.__getitem__, section_stack, res)[key] = value
        else:
            raise ParseError('Unrecognized line: `{}`'.format(line))
    return res

def parse_section(line):
    depth = line.count('[')
    if depth != line.count(']'):
        msg = 'Unbalanced brackets in section definition: `{}`'.format(line)
        raise ParseError(msg)
    section_name = line.strip('[]')
    return (depth, section_name.strip())

def parse_assignment(line):
    (raw_key, raw_value) = line.split('=', 1)
    return (raw_key.strip(), parse_value(raw_value))

# maybe use shlex?
def parse_value(raw_value):
    value = raw_value.strip()
    if value.startswith('[') and value.endswith(']'):
        return map(parse_value, value[1:-1].split(','))
    elif value.startswith('"') and value.endswith('"'):
        return value[1:-1]
    elif value.startswith("'") and value.endswith("'"):
        return value[1:-1]
    elif value.isdigit():
        return int(value)
    elif value.lower() == 'true':
        return True
    elif value.lower() == 'false':
        return False
    elif not value:
        return None
    else:
        return value
<commit_msg>unnecessary<commit_after># -*- coding: utf-8 -*-

class ParseError(ValueError):
    pass

def parse_file(filename):
    with open(filename) as fileobj:
        return parse(fileobj)

def parse(fileobj):
    section_stack = []
    res = {}
    for line in fileobj:
        line = line.strip()
        if not line:
            continue
        elif line.startswith('['):
            (depth, section_name) = parse_section(line)
            diff = len(section_stack) - depth + 1
            if diff < 0:
                msg = 'Too high depth for subsection, missed previous'
                raise ParseError(msg)
            for _ in xrange(diff):
                section_stack.pop()

            reduce(dict.__getitem__, section_stack, res)[section_name] = {}
            section_stack.append(section_name)
        elif line.startswith('#'):
            pass
        elif '=' in line:
            (key, value) = parse_assignment(line)
            reduce(dict.__getitem__, section_stack, res)[key] = value
        else:
            raise ParseError('Unrecognized line: `{}`'.format(line))
    return res

def parse_section(line):
    depth = line.count('[')
    if depth != line.count(']'):
        msg = 'Unbalanced brackets in section definition: `{}`'.format(line)
        raise ParseError(msg)
    section_name = line.strip('[]')
    return (depth, section_name.strip())

def parse_assignment(line):
    (raw_key, raw_value) = line.split('=', 1)
    return (raw_key.strip(), parse_value(raw_value))

# maybe use shlex?
def parse_value(raw_value):
    value = raw_value.strip()
    if value.startswith('[') and value.endswith(']'):
        return map(parse_value, value[1:-1].split(','))
    elif value.startswith('"') and value.endswith('"'):
        return value[1:-1]
    elif value.startswith("'") and value.endswith("'"):
        return value[1:-1]
    elif value.isdigit():
        return int(value)
    elif value.lower() == 'true':
        return True
    elif value.lower() == 'false':
        return False
    elif not value:
        return None
    else:
        return value
<|endoftext|>