From 615335a638c66daaf0742ba5b1eb85e71eeff8d8 Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Mon, 25 Mar 2019 21:19:04 +0100 Subject: [PATCH] Initial commit --- LICENSE | 4 ++ Makefile | 18 +++++++ README.rst | 39 ++++++++++++++ addon.xml | 22 ++++++++ icon.png | Bin 0 -> 7237 bytes lib/win_inet_pton.py | 126 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 209 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.rst create mode 100644 addon.xml create mode 100644 icon.png create mode 100644 lib/win_inet_pton.py 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 0000000000000000000000000000000000000000..ca4c53adbfa8d06d0e282d45f9cad195e89d571e GIT binary patch literal 7237 zcmd6segn*PtcXta6B_iEY!_ZO!(hW*?NtZN|0+Q0*Idt6f zyPh}Ce{kQg_FmUH=epM3d#&~T?6X2um1UkhCVvb7z!N!HNp%1Kp{F1K8;l;tp(32< z;kk>Hu8W5K2N!n}CksH#+}_lJM$Xp6(n8(B#N5NN-{KtrP;AOcifMkH-81xZAku0) zJm@Fp#L>;2G$No%IAG+yoYp5GaFu%IUu+;swO88s1zP{pU;HSjZs%mSWk-t&_g@Ho ziEeH*(#E3>d+FdhBsqGE-7A^C1iw#lrA#WCUbnyt#(}cSyFtw7-zZ)*e;ZV!;=a29 zNvMo$PYqt&P;I6i3a&&XS3`gb7`- zv`0p^b-1;)MNL*O`QZBg`Z~2-O6{8@DySvw3zXooW6z-8C5dSQ;;G)FJNM2feEjLd zx3|rD)gR_v#+4k6R(Adtml_@39JU-R9bjWzy^THoA^I+voLSQK=;gxxv4pq1MZl+rfr(Ml0Vruz#l?pv_XVq#QTaK(c^5Me4-ZdI&yGWrnX0PAhx@y>dz3GRnFG*< zYl`Fy+VJgzX_ven;FEj6T&?FSBnn?11$Z5_-lSNU$-TqJSibGu zoT2eUntS50sOvoa84cbSIQicb75taglNv+5r1c8#NYx=&9}CZ2t$7j^JseA;(v z()sgS*PHN?KGWXruYc+jezzPsvjVzEPEhLLBP75pwe_xcrfz7`QwGJ!HK`&Ycx>ng z)V4=aBR=;GKHph7%DPVE-D2DC;tL>aCy`ZAd6+rhZ>ETI5s`cN=n?>?Y42KZ7r9+y z>QFgSYR8cG$l9cYRMZ^>fE@hPN!9XZDp>ee+3&*~xxX_@XA%WEnnK~`P9lM4DsjhC zqUys?TDw6~Frg?iTPidBGrbs}K66yr`+fpsd`!ge6C3}!1y7hVVf&#rQHQYz4XU{V z!ViEYN#qqgy{7%2%8!Elxs138BGO)T*B3kR(H8ki(v@dO`78n0Q0eO#h>G6OVZ7yF z8mIk2^9=ixE@M-d!<0SaM+n0HMIp4oQlaqVfGuA6~$k_n%8)9A?C1k3- zaw~RyQBhH4r5aJ-{#;!wE>R+eL&I4KA4TWn70}NEnVg;V+!|dDrzEwy>1WFHbolfA zawIu9nezz6=c!%E=KLs{AQ^JZ9*U5VFe{F^)~zksE6mSO?CW=SPT#ygV_M*ZOFTsa zp)wj8gjZXXl$7);M&(hZ7DYZ>-p5=;iexCp2@zVBy+L$!VK=B{jWGnBQ{iEP2ryk; zUv~%|;^E;PX_d_Ax0dkB;f)oNy{Czbj~8liTs_+!C-h!Cr@}?Q8-Poyf3bIk5!#x! zFU5EwolL-h8ABiH{?>5qhvf%zA|euY7%ZH74MP<9M_fWe0v)l6{jnKFnwpxrx=C+N zUikx}X=BE&$gYBlEQgB&!%%lMX~SDvL+b9yRiLPspnTIgyQnCPce2FjZX;DDR_QvZ ztc;!g?mWk@6vu(H6-B|aQ(97@Ibn3gR9A>{`-V>rf(VlKSMh+#j9SP?mfP<356g`1 zR?0d$BvHSkIMLb0^Q+Dk3O56P=^!=kl0h!sX+z`Yo7|bUNtaNb7!nTw052f|#YC!w z^M#ly$}-CrK2v2Ow|S9Dm5qZT&R`JM+WO~@Bg^?w-OqTNzVG~bt5Jd}Den}YVe_&R ze3HR!53y>y-`M^7m27qCYdGba5WTtdY<*UKe(%&|PupW%z-vtOQ>6ZTk)366^>8J_ z^i;Ogm(vvAB6E%J?plP6Z7e_9q8ND|eNvf_uhn^QbN7>!d+UDi-lo$;j_qxFdiv1N z(0BS@7*!~KfKE)q*;x?_w|_1G(OgS%k8cY2G&=1c&yuZ+SgC0k4*e9th8u5N5?!7Q zaG-UmdZe0K#At46YJ?Twhr5%?jybGt#oX63^)O(d6~gV{->(ev9cuRI58xMLe2d;U zhd1Yu6Ik-nOk3-eg4fqrTQS-9CLlaIQ6dNa*;$dR_2TlcuQ6r0whK#3g&tToS8$4#yjUJv2?a{0uKU$XiT zGrP8tn~ndK=EKP6Vtd(^oaD;QWIs0od5y9S1LcHss7Yx2DYJB1#8XV;)^L~*HXMHf zXCp`Et3qW7Vz*vG^xue3fsLW?FQ419enoH4zAV)Ay&5oH5x6~{JB$wIOZQ7H1UfIXT` zv@tWsIQ@HE-hJ*9PX)o_p?2^zc|EW45jxNFhfi;(FUM(~$ku zEAr~y`+<$2d=zKhZ;g= z{Io*u4`ikN=CI9ufUVBl(lTm{7_E^~Qr*eizLG{9rbrwjye+x7Pl_e9A|g>;H5FMj zemcjVEg{9lDjDyj#7EwUxS-Fik{?d%|Jc$_SxycI1M`?H5WS?v#zsOW<;&SwhESMK z+!+YONQDJfgm-FRFU6+4hY8h?5R!pcyek?OtJt&>=xYVU}OycPwp?x{g)7b8qwnbpx^XKNd$H?u7(4H zYPA@LscF#)4K}#uo*7&%Mp&u_HZ8Iv??+uf$OrnvK0L!uUjqK1g)$M7gbPotx$BH2 zkP0G8$@n^cB>YqI<3XJ0&(L=EO0o9SWx9T-C$ydM`v_iQsP2T_X793A`f(ZjO}PKVA)tH<}lf1OxXsZ(9BSu$PuQ^VN3yV zQ@{QdPVN+z*X#!d5p1uIWQzFy^2Z`!*FEa=+N{*FOcGEn(ZY)l)t?yUdT+TWw?DRH z#TzqRaYJ|#E`4;uGDsZxlQ%BsDxv1)>2=REnNg8)udIScL)3|9iRT*Ixh#^1;QjG8shTJ$uPc#8mh-7>;j3$JyDCuIbInV4&@1>;9G0vj4DnFfhF=Rf60K%A?T>63)VD7mGsjsiq{ z&Xz-{eb1J!qC`Azk6i=qe=&rUqHV0gSyxzY&KWM~&xQ3j5q|!UFOlbNs%HL!#F;Mw zp_R2^W%2L)P4_or*j9))=zlfG-Q7pSU?xd6d5-lGrb}&hcsyYX&LjBSf7er#%8Rwj z6jf9fD@=T#`^#VkKe_>550d!C_w4!O{i&7R67GBd{w^+-GY5N271EHBlG^LG-DijR zzR+}jskw;t_QnDRnlQ}>qZ!zn2>S~ZPz4(sn5p2o$>F(65R}m2yj8O>)PEH65x2G~ z?zy_<^;=)Ym83??fLrQ;pVPvhrsk%4=g!X0CpC4vS{C;9_B8h!m41=6k3QTtH#a95 zd$QQ5)9$mfu^HAon4tOJ;D+fRrE#Onb}&k%LV~C>2LCa^*2Ee?MVUa4$Ut48QuJ(&7u`%Im#e&#l$4d+b{tExzdlZJU5cv4{Gvz}W;*5tp434muPyl> zr{xaX$qdRBw<)cuiJH1PSXcmk@?yRniMaq1UkFvT=z#nx-{|<<+}iP|-_Q`73#dQ4 zjF%-z16o5>qGRM?u{oTMPTTOXF!i5;Z~hXP>Kd^>zw$*KG-wrTllzZp7#JAnY#!|G z3=aQh)Tr=u6^M1ZE~u#~xsm7Ft*~lw$jIC|7d(K&6u2v23lguU>dqjAeoll8yZsH4f?eB zT&IksFvY~gi1nm1Y^w)^MN()H7cg%GmD@MnJq-z_0Vk;-QfpNU%N*|zi2CvEZxJgD zdp%ps%1FM2&t^j@JTV#m{HmHY1-@`(ppx1=^Hr{|SInN)nI%)O{d}X+SP8Hj&Cop} zOiP_tdmcEoiMsM0esAe<^~(75<@S`X|mp+V!G@-8heL+leWD zexfZBx5x~unqHi0L)-h&x#2?c(lcXl-%P4wALtd-IYXR{fdAmebbgO9Jx|Jr%K+cPv>y zlAdStx)jASsc6K8+B6)<+mtS zoAv|zz`_16O$RLra~x;?)q5s`uf^s z)q>gSyu7qDQrKeXxBP&AM!@cgs2rP+c0zFHc3gS8MMz-Ml0R<5Q=C>&{%p$({1E`x zd;8n+SG_d6!omg?=IG_0H9I^1{yFF=CVyC5;K9yfXCu^i4iXWh3y}89+xP&g*tJo0 z#3mNPG)i7JPs-(%gu%R_KkDjwZ8|=$4K27n&$E%ehvkJo88^!1-Af`U#E<;irt_ij zjAVXlR4}|G88euL(96?H=0yd~vmssx_8`vsoo5924{VBDV>SNe+u-1NYGQ4e0o~RY z_2(^R1tfi6-{@mK+FJ%E!`$>SJ&A&%zMY?)CH+2!;05KDq*{%czxfRzBWZjt=<;mJ zQukDl0AjAw0mhR8d?x93Y48;@<17|>SB^iQHKzT7L|^5Y2;92JGJuIc59nfOHc`8B z!k=JZ1o;s(`8}Z6^3^`oRabMb2>^lw?QeK8hwe}}S7~tDIb*d-Kb7vn;$qzW!_?GF zj$Nz)gwIMPuaCYqt?MHUc6(?@rOcN|obT;8=zLX;S#JkJ^189N;yGS=pYQ3RaS<-o zGMAp2$XCDw!sEh>cCi0fA7ed4$fWY=F4QjuB(ANUkfH=lk`w9sdY;PFHn=l87!Wat zXJ@Io%6TFV)xU_=-E=!8ga7i!K=>|wHD5Khv$KQOx9^i+JYxhP*ht#>l$4#F&X5Fl z!<5+A*z(~RL_=O)FyC~gSxAmj3q9s2?_!(lZo+ND6}_qNL;B&`kXlS4pJnGYDt~u= zd7|x;uxI2#k`_#7+lsldQQQA3w6nY0R8=IB{%_N+0F(Q{znIk6AAcNFgKFbrGL&xw zVhdY7rdJ4*SkLg&)(-HC`UQ{PrPkS~CBAT#&Eb(#naZ>)C@r;!9qAK$Yq}!mq7y!p zQCL=Ha-~7Rr){n>BCO`+?^b&?>v`kJ#vbju@qRk}JFj$>?AXST!I#!O#Fu`X`?Qf= z=fQ>rSJq{1hFTMH!tqHRYyS0DqSbDY3=4~ z(}}K%w2Eodqi;_{^K&dfxP?3IAg45W1qFz!wzyTYbWTUp!P9gWqJ@3V{i(dzqE+o7 zwxOE~ohozS8!GajYqkHZs)8p8XH8zG>QvQfmgo*)R`Jd6;dH^|cY2y7yyOVRJ_a?Yl(1Gn^WUr#a5tMY;dULQokoa)BsUoiRNbr_mZ3%Q6VTTX>30 zW^;zVqobpeE6=Wb{#Nz2JF{j4Uj-uJ|?DRHZx?PF}Q+T6adf-kHGr* zef{Ci*`L{umUbu0(nTKb7Zw)GdJ(9dUjZ8uPEJnK`87)W#zL3mEh!YE zG84!YS66pxuTxzYj)$e?+q^Cg z=Fk2)(|@9OKu=#L8#NsqCnPvqPYFw_e@y5zv!~L+sXlPLo|~JKAsFmy&-Fdb5Hd8J zKVwOE?*G;;z&Mh@PP(==j#HgyA@vRM)vbDNDPD@ym# zEH7UcHWY8I<|9dALeYiExV45XC8olq z#l!|8@RPFp1_vwT&4b}ZL4zgZp9yy;pxF^eyh1>!#P4E|I-_Qd;h}3q7~T6nP;Iv zJwh0pvN_aX?N=S+YzV?*Bh?dwz-l literal 0 HcmV?d00001 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()