commit 615335a638c66daaf0742ba5b1eb85e71eeff8d8 Author: Dag Wieers Date: Mon Mar 25 21:19:04 2019 +0100 Initial commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f58fba --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +This software released into the public domain. Anyone is free to copy, +modify, publish, use, compile, sell, or distribute this software, +either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e66769a --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +addon_xml = addon.xml + +# Collect information to build as sensible package name +name = $(shell xmllint --xpath 'string(/addon/@id)' $(addon_xml)) +version = $(shell xmllint --xpath 'string(/addon/@version)' $(addon_xml)) +git_hash = $(shell git rev-parse --short HEAD) + +zip_name = $(name)-$(version)-$(git_hash).zip +exclude_files = .git/ .git/\* Makefile +exclude_paths = $(patsubst %,$(name)/%,$(exclude_files)) + +all: zip + +zip: + @echo -e "\e[1;37m=\e[1;34m Building new package\e[0m" + rm -f ../$(zip_name) + cd ..; zip -r $(zip_name) $(name) -x $(exclude_paths) + @echo -e "\e[1;37m=\e[1;34m Successfully wrote package as: \e[1;37m../$(zip_name)\e[0m" diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..f759590 --- /dev/null +++ b/README.rst @@ -0,0 +1,39 @@ +win_inet_pton +============= + +Native inet_pton and inet_ntop implementation for Python on Windows (with ctypes). + +Credit Where Credit Is Due +-------------------------- + +This package is based on code that was originally written by https://github.com/nnemkin here: https://gist.github.com/nnemkin/4966028 + +Why? +---- + +I needed this functionality in https://github.com/SerenitySoftwareLLC/cahoots to get full windows support. I figured, since there were other people looking for a solution to this on the net, I should publish it. + +Usage +----- + + .. code-block:: bash + + python -m pip install win_inet_pton + +Just import it, and it will auto-add the methods to the socket library: + + .. code-block:: python + + import win_inet_pton + import socket + + socket.inet_pton(...) + socket.inet_ntop(...) + +License +------- + +This software released into the public domain. Anyone is free to copy, +modify, publish, use, compile, sell, or distribute this software, +either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. diff --git a/addon.xml b/addon.xml new file mode 100644 index 0000000..35f0ac1 --- /dev/null +++ b/addon.xml @@ -0,0 +1,22 @@ + + + + + + + + Native python inet_pton implementation on Windows (with ctypes) + Native inet_pton and inet_ntop implementation for Python on Windows (with ctypes). + all + + + Public Domain + + https://github.com/hickeroar/win_inet_pton + https://github.com/dagwieers/script.module.win_inet_pton + dag@wieers.com + + icon.png + + + diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..ca4c53a Binary files /dev/null and b/icon.png differ diff --git a/lib/win_inet_pton.py b/lib/win_inet_pton.py new file mode 100644 index 0000000..e717672 --- /dev/null +++ b/lib/win_inet_pton.py @@ -0,0 +1,126 @@ +# This software released into the public domain. Anyone is free to copy, +# modify, publish, use, compile, sell, or distribute this software, +# either in source code form or as a compiled binary, for any purpose, +# commercial or non-commercial, and by any means. + +import socket +import os +import sys + + +def inject_into_socket(): + import ctypes + + class in_addr(ctypes.Structure): + _fields_ = [("S_addr", ctypes.c_ubyte * 4)] + + class in6_addr(ctypes.Structure): + _fields_ = [("Byte", ctypes.c_ubyte * 16)] + + if hasattr(ctypes, "windll"): + # InetNtopW( + # INT family, + # const VOID *pAddr, + # PWSTR pStringBuf, + # size_t StringBufSize + # ) -> PCWSTR + InetNtopW = ctypes.windll.ws2_32.InetNtopW + + # InetPtonW( + # INT family, + # PCWSTR pszAddrString, + # PVOID pAddrBuf + # ) -> INT + InetPtonW = ctypes.windll.ws2_32.InetPtonW + + # WSAGetLastError() -> INT + WSAGetLastError = ctypes.windll.ws2_32.WSAGetLastError + else: + + def not_windows(): + raise SystemError("Invalid platform. ctypes.windll must be available.") + + InetNtopW = not_windows + InetPtonW = not_windows + WSAGetLastError = not_windows + + def inet_pton(address_family, ip_string): + if sys.version_info[0] > 2 and isinstance(ip_string, bytes): + raise TypeError("inet_pton() argument 2 must be str, not bytes") + + if address_family == socket.AF_INET: + family = 2 + addr = in_addr() + elif address_family == socket.AF_INET6: + family = 23 + addr = in6_addr() + else: + raise OSError("unknown address family") + + ip_string = ctypes.c_wchar_p(ip_string) + ret = InetPtonW(ctypes.c_int(family), ip_string, ctypes.byref(addr)) + + if ret == 1: + if address_family == socket.AF_INET: + return ctypes.string_at(addr.S_addr, 4) + else: + return ctypes.string_at(addr.Byte, 16) + elif ret == 0: + raise socket.error("illegal IP address string passed to inet_pton") + else: + err = WSAGetLastError() + if err == 10047: + e = socket.error("unknown address family") + elif err == 10014: + e = OSError("bad address") + else: + e = OSError("unknown error from inet_ntop") + e.errno = err + raise e + + def inet_ntop(address_family, packed_ip): + if address_family == socket.AF_INET: + addr = in_addr() + if len(packed_ip) != ctypes.sizeof(addr.S_addr): + raise ValueError("packed IP wrong length for inet_ntop") + + ctypes.memmove(addr.S_addr, packed_ip, 4) + buffer_len = 16 + family = 2 + + elif address_family == socket.AF_INET6: + addr = in6_addr() + if len(packed_ip) != ctypes.sizeof(addr.Byte): + raise ValueError("packed IP wrong length for inet_ntop") + + ctypes.memmove(addr.Byte, packed_ip, 16) + buffer_len = 46 + family = 23 + else: + raise ValueError("unknown address family") + + buffer = ctypes.create_unicode_buffer(buffer_len) + + ret = InetNtopW( + ctypes.c_int(family), + ctypes.byref(addr), + ctypes.byref(buffer), + ctypes.sizeof(buffer), + ) + if ret is None: + err = WSAGetLastError() + if err == 10047: + e = ValueError("unknown address family") + else: + e = OSError("unknown error from inet_ntop") + e.errno = err + + return ctypes.wstring_at(buffer, buffer_len).rstrip("\x00") + + # Adding our two functions to the socket library + socket.inet_pton = inet_pton + socket.inet_ntop = inet_ntop + + +if os.name == "nt" and not hasattr(socket, "inet_pton"): + inject_into_socket()