H2S66: Web APIs and protocols # lit-rev:


H3S1: Web-sockets API:

Wikipedia: WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C.

Hu: The server is your server; there is no external server that runs this thing, for free. The WebSocketServer file sets up a server, on your server, and handles client’s input from the browser in protocol’d ways. Question: where are API calls in the code in 4) If there are no API calls, then is websockets just a set of instructions, for how to write a server in PHP?

I can learn anything, and explain it, to anyone, in technical language 🔑 and my speed of learning matches the complexity of the content 🔑

Wang<pg-9>: WebSocket is a protocol, but there is also a WebSocket API, which enables your
applications to control the WebSocket protocol and respond to events triggered by the
server
. The API is developed by the W3C (World Wide Web Consortium) and the protocol
by the IETF (Internet Engineering Task Force). The WebSocket API is now supported
by modern |
browsers and includes methods and attributes needed to use a full duplex,
bidirectional WebSocket connection. The API enables you to perform necessary actions
like opening and closing the connection, sending and receiving messages, and listening
for events triggered by the server.

H4S1: Included address:

$Address = 'ws://localhost:8095';

Above: <phpWebSocketServer, adressPort.inc.php> Below, via Lengstorf, Leggetter<a-r, pg-30>

 <script>
 var ws = new WebSocket( 'ws://echo.websocket.org' );
 ws.onopen = function() {
 console.log( 'connected' );
 console.log( '> hello' );
 ws.send( 'hello' );
 };
 ws.onmessage = function( ev ) { console.log( '< ' + ev.data ); };
 ws.onclose = function() { console.log( 'closed' ); };
 ws.onerror = function() { console.log( 'error' ); };
 </script>

Observations: This is a basic echo test, designed by L&L<a-r><pg-30>; There are 5 built.in-functions used, but it’s not clear, where they are defined. According to L&L, this basic test can be run in any HTML file, without additional dependencies. Note that websocket.org has a non.HTTP-portal, ws://, rather than https://, that defines its ability to be connected, via socket. // add quote about chakras, Britannica.

H4S2: Writing.custom-servers<Turing-shared!>:

dev-Mozilla: WebSocket servers are often separate and specialized servers (for load-balancing or other practical reasons), so you will often use a reverse proxy (such as a regular HTTP server) to detect WebSocket handshakes, pre-process them, and send those clients to a real WebSocket server. This means that you don’t have to bloat your server code with cookie and authentication handlers (for example). Hu: In terms of folder hierarchy, a WebSockets establishment folder # should occupy level 2, a direct-subdirect, within your root-main, at the maininc level<Turing> Cont<WP.MIC-H2S75>

H4S3: The WebSocket handshake:

dev-Mozilla: First, the server must listen for incoming socket connections<from-JS> using a standard TCP socketHu: TCP-sockets are built.in-to any standard web-install, such as localhost-WAMP, and any standard web-host. dev-Mozilla: Warning: The server may listen on any port it chooses, but if it chooses any port other than 80 or 443<historical!>, it may have problems with firewalls and/or proxies. Browsers generally require a secure connection for WebSockets, although they may offer an exception for local devices.

The handshake is the “Web” in WebSockets. It’s the bridge from HTTP to WebSockets<innovative!><notation><simple>. In the handshake, details of the connection are negotiated, and either party can back out before completion if the terms are unfavorable. The server must be careful to understand everything the client asks for, otherwise security issues can occur.

H5S1: Client handshake request:

dev-Mozilla: Even though you’re building a server, a client still has to start the WebSocket handshake process by contacting the server and requesting a WebSocket connection. The client will send a pretty standard HTTP request with headers that looks like this (the HTTP version must be 1.1 or greater, and the method must be GET): [D, L]. [D, R] via Lengstorf, Leggetter<a-r> [D.L-2 via RFC 6455 a-r] [D.R-2, via Wang pg-41]: in this example, we can see that the standard Sec-Websocket-Key, given in the 3 other examples, which is copy-pasted directly from the example from RFC-6455, can be different, which is the point; this is supposed to be a random.genkey, for security purposes, and the validation of whether this key can be returned, in a different from, from the server, validates # that you are communicating with the correct party, and that the developer wrote the decryptionalgo | correctly.

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
GET /echo HTTP/1.1
Host: echo.websocket.org
Origin: http://www.websocket.org
Sec-WebSocket-Key: 7+C600xYybOv2zmJ69RQsw==
Sec-WebSocket-Version: 13
Upgrade: websocket

H6S1: Sec-Websocket-Key: <RFC 6455 4.2.2> NOTE: As an example, if the value of the |Sec-WebSocket-Key| header field in the client’s handshake were “dGhlIHNhbXBsZSBub25jZQ==”, the server would append the string “258EAFA5-E914-47DA-95CA-C5AB0DC85B11” to form the string “dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA- C5AB0DC85B11”. The server would then take the SHA-1 hash of this string, giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value is then base64-encoded, to give the value “s3pPLMBiTxaQ9kYGzzhZRbK+xOo=”, which would be returned in the |Sec-WebSocket-Accept| header field. <11.3.1>: The |Sec-WebSocket-Key| header field is used in the WebSocket opening handshake. It is sent from the client to the server to provide part of the information used by the server to prove that it received a valid WebSocket opening handshake. This helps ensure that the server does not accept connections from non-WebSocket clients (e.g., HTTP clients) that are being abused to send data to unsuspecting WebSocket servers. The |Sec-WebSocket-Key| header field MUST NOT appear more than once in an HTTP request.

H7S1: base64-encoding, via RFC 4648<a-r>:

Table 1: The Base 64 Alphabet

     Value Encoding  Value Encoding  Value Encoding  Value Encoding
         0 A            17 R            34 i            51 z
         1 B            18 S            35 j            52 0
         2 C            19 T            36 k            53 1
         3 D            20 U            37 l            54 2
         4 E            21 V            38 m            55 3
         5 F            22 W            39 n            56 4
         6 G            23 X            40 o            57 5
         7 H            24 Y            41 p            58 6
         8 I            25 Z            42 q            59 7
         9 J            26 a            43 r            60 8
        10 K            27 b            44 s            61 9
        11 L            28 c            45 t            62 +
        12 M            29 d            46 u            63 /
        13 N            30 e            47 v
        14 O            31 f            48 w         (pad) =
        15 P            32 g            49 x
        16 Q            33 h            50 y

H7S2: sha1 encoding: // add

H5S2: Server handshake response:

dev-Mozilla: When the server receives the handshake request, it should send back a special response that indicates that the protocol will be changing from HTTP to WebSocket. That header looks something like the following (remember each header line ends with \r\n and put an extra \r\n after the last one to indicate the end of the header): [D, L]. [D, R] via Lengstorf, Leggetter<a-r> [D, below] via RFC 6455. [D.below-R] Wang: The Sec-Web-Accept code here cryptographicallymatches the key from the send-portion.

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
101 Switching Protocols
Connection: Upgrade
Date: Wed, 20 Jun 2012 03:39:49 GMT
Sec-WebSocket-Accept: fYoqiH14DgI+5ylEMwM2sOLzOi0=
Server: Kaazing Gateway
Upgrade: WebSocket

Lengstorf, Leggetter<a-r><pg-11>: This exchange is called a handshake, and it’s required to establish a WebSocket connection. Once a successful handshake occurs between the server and the client, a two-way communication channel is established, and both the client and server can send data to each other independently.

H5S3: Web.sockets-session: dev-Mozilla: Your server must keep track of clients’ sockets so you don’t keep handshaking again with clients who have already completed the handshake. The same client IP address can try to connect multiple times. However, the server can deny them if they attempt too many connections in order to save itself from Denial-of-Service attacks. For example, you might keep a table of usernames or ID numbers along with the corresponding WebSocket and other data that you need to associate with that connection.

H5S4: Sub-protocols: <Wang pg-49>: At the network | level, these protocols are negotiated using the Sec-WebSocket-Protocol header. Protocol names are header values sent from the client in the initial upgrade request: Sec-WebSocketProtocol: com.kaazing.echo, example.protocol.name. This header indicates that the client can use either protocol (com.kaazing.echo or example.protocol.name) and the server can choose which protocol to use. If you send this header in an upgrade request to [server-URL], the server response will include the following header: Sec-WebSocket-Protocol: com.kaazing.echo. This response indicates that the server has elected to speak the com.kaazing.echo protocol. Selecting a protocol does not change the syntax of the WebSocket Protocol itself. Instead, these protocols are layered on top of the WebSocket Protocol to provide higher-level semantics for frameworks and applications. Hu: Only one protocol can be negotiated at a time, using Sec-WebSocket-Protocol.

H5S5: Extensions: <Wang pg-50>: Like protocols, extensions are negotiated with a Sec- header. The connecting client sends a Sec-WebSocket-Extensions | header containing the names of the extension (or extensions) it supports. While you cannot negotiate more than one protocol at a time, you can negotiate
more than one | extension at a time. Extensions are so named because they extend the WebSocket Protocol. Extensions can add new opcodes and data fields to the framing format. You may find it more difficult to deploy a new | extension than a new protocol (or “subprotocol”) because browser vendors must explicitly build in support for these extensions. You’ll probably find it much easier to write a JavaScript library that implements a protocol<Turing-Wang><fbno> than to wait for all browser vendors to standardize an extension and all users to update their browsers to the version supporting that extension.

H4S4: Messages:

Hu: Industry word #: frames. Wang<pg-9>: The protocol consists of an opening handshake followed by basic message framing, and is layered over TCP.

H4S5: Encoding:

Lengstorf, Leggetter<a-r><pg-11>: Data sent after the handshake is enclosed in frames, which are essentially chunks of information. Each | frame starts with a 0x00 byte and ends with a 0xFF byte, meaning that every message sent has only two bytes of overhead in addition to the message’s size.

Only winning move: 39…Ka8 M-#4! https://lichess.org/3mStJpob/black#77

H5S1: Base.framing-protocol<RFC.6455-5,2>

[D, via RFC-6455]: H6S1: FIN: 1 bit: Indicates that this is the final fragment in a message. The first fragment MAY also be the final fragment. H6S2: RSV1, RSV2, RSV3: 1 bit each: MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. H6S3: Opcode: 4 bits: Defines the interpretation of the “Payload data”. H6S4: Mask<Hu: or, “is there a mask binary”, not the mask itself>: 1 bit: Defines whether the “Payload data” is masked. If set to 1, a masking | key is present in masking-key, and this is used to unmask the “Payload data” as per Section 5.3. All frames sent from client to server have this bit set to 1. Section 5.1: A server MUST NOT mask any frames that it sends to the client. H6S5: Payload length: 7 bits, 7+16 bits, or 7+64 bits<Anki, fbno>: H6S6: Masking-key: 0 or 4 bytes: All frames sent from the client to the server are masked by a 32-bit value that is contained within the frame. <RFC.6455-5,3>: The masking key is a 32-bit value chosen at random<Hu: Presumably, this is a recommendation by RFC[karma!], but they protocol itself does not check whether the value was chosen at random, because the protocol does not read the code | used to generate the feed> by the client. When preparing a masked frame, the client MUST pick a fresh masking key from the set of allowed 32-bit values. The masking key needs to be unpredictable; thus, the masking key MUST be derived from a strong source of entropy, and the masking key for a given frame MUST NOT make it simple for a server/proxy to predict the masking key for a subsequent frame. The unpredictability of the masking key is essential to prevent authors of malicious applications from selecting the bytes that appear on the wire. RFC 4086 [RFC4086] discusses what entails a suitable source of entropy for security-sensitive applications. H6S7: Payload | data: (x+y) bytes: The “Payload | data” is defined as “Extension data” concatenated with “Application | data. H6S8: Extension data: x bytes. The “Extension data” is 0 bytes unless an extension has been negotiated. H6S9: Application data: y | bytes.

Anki study:

H6S4: {{c2::Mask::M}}: 1 bit: Defines whether the "{{c1::Payload data::P-d}}" is {{c2::masked}}. If set to 1, a {{c2::masking}} | {{c4::key}} is present in {{c2::masking}}-{{c4::key}}, and this is used to {{c4::un::prefix}}{{c2::mask}} the "{{c1::Payload data}}" as per Section 5.3. All {{c5::frames::f-noun}} sent from {{c7::client}} to {{c6::server::s-noun}} have this bit set to {{c9::1::1 or 0}}. Section 5.1: A {{c6::server}} {{c8::MUST NOT::Must or must not}} {{c2::mask}} any {{c5::frames}} that it sends to the {{c7::client}}. 

Read on at<WP.MIC-H2S78> for specific instructions on decoding payload,<WP.MIC-H2S77> for an example of an encode/decode-function in PHP, and<WP.MIC-H2S79> for how messages are chained in fragmentation #<WP.MIC-H2S80> for TCP as a q.tum-portal.

H5S2: The payload-length is the 17th-32nd bits, or a total of 16-bits, inclusive; this can be looped, to generate a 16.bit-payload<Turing>! H6S11: Exactly the first 16-bits, from 0 to 15, inclusive, are specifiers, applying to the entire frame #

H5S2: Sample string<stateless><Turing>: <FIN:>0|<RSV-1>0|<RSV-2>0|<RSV-3>0|<op-code>0000|<length.spec-1, 0-125, or 126/7 pass-code to next>0000000|<126 to 63,999-kb[80%, WP.MIC-H2S81]>0000000000000000|<64.kb+, inclusive of the previous 2 bytes>00000000,00000000,00000000,00000000,00000000,00000000|<Masking-key, if>00000000,00000000,00000000,00000000|<Payload, rest>:0s Hu: Each decimal point # in this string is a bit<WP.MIC-H2S11,H3S2.H4S2>

H4S6: Closing-conn:

Wang<pg-47>: When a WebSocket closes, the endpoint that is terminating the connection can send
a numerical code and a reason string to indicate why it is choosing to close the socket. Hu: Obviously, a Web.Socket-conn can close automatically # when a particular user eliminates the possibility of the connection’s continuity<Turing>, such as by unplugging their computer, or internet, but the conn can also be manually triggered to close, even when the conditions for conn-persists #, and this can be initiated, to completion #, by either | party. Wang: The code and reason are encoded in the payload of a frame with the close opcode<the portion of a machine language | instruction that specifies the operation to be performed, via Wikipedia> (8). The code is represented as an unsigned | 16-bit integer. The reason is a short UTF-8 encoded | string. RFC 6455 defines several specific closing codes. Codes 1000–1015 are specified for use in the WebSocket connection layer. These codes indicate that something has failed in
the network or in the protocol. Hu: Code 1000, for example, specifies a normal closing reason. Depending on the closing reason, which can be programmed, based on client.side-events, the feedback might lead to troubleshooting on the server-side.

H4S7: Coding-load<Turing>!

Hu: At this point <WP.MIC-H2S73>, I’m ready to quote # the approximate coding complexity of building with WebSockets, as well as define a basic architecture:

H5S1: Request | templates: 10 lines, for both H5S2: Cli-1 to Ser-1, 5 lines H5S3: Ser-1 to MySQL, 1 line func-call, 4 lines in inc H5S3: Ser-1 to ser-2, 5 lines H5S4: Ser-2 to cli-2, 5 lines, different from H5S2, due to directionality<Turing> H5S5 Ser-2 to MySQL, we can either discount this, or say it will also be 1 line, as the func is defined in H5S3. H5S6: Conn-include<optional>, including any portal opening, 5, upwards of 10, pessimistically, max H5S7: Decoding include; there may be as many of these, as there are unique protocols, but each one, 5, upwards of 10, pessim-max #, only needs to be defined once, with a single func-call, whenever a decode is needed. H5S8: Conditional logic: with this basic structure set up, now we just do simple | coding, and the conditional logic<WP.MIC-H2S58>, we won’t count, as the coding-load to WebSockets, because conditions are a general that we use, to program for our own business-logic, until they meet the WebSocket-interface, with is a transmission protocol, not a programming language<Turing-dirty!>

H5S2: Web.Socket-built,in.architecture<innovative!>

Hu: I’m already familiar with MySQL, and thinking in the flavor of includes, allows important extrapolations, that simplifies the programming process. There are a number of repetitive | tasks that Web-Sockets will be responsible for handling, and these tasks will be defined, in the include-architecture:

H6S1: Writing.to-tasks:

H6S2: Receiving.to-tasks:

Insofar as every type of content can be exchanged both ways, such as in a messaging application, the H6S1/2 needs to be symmetrical, to an extent #v-t<prevalent!>

Cont<WP.MIC-H2S67>

H4S8: URL, file-str, and origin considerations:

Hu: Any true Web.Sockets-info will flow from a ws:// scheme<H3S5>, but users might never land on a page # that reads ws://, either because that page was a redir, or an include<Turing>. However, there may be times, when users can land on a ws:// page, to get a Web.Socket-default,exp, and one may also have Web.Socket-dominant files, even if they remain .php, or .html. How do I allow users to land on a ws:// page, if I use HTTP/S by default, in WAMP-stack?

<RFC-6455><1.7>: H5S1: Port: By default, the WebSocket Protocol uses port 80 for regular WebSocket connections and port 443 for WebSocket | connections tunneled over Transport Layer Security (TLS)

H3S2: TCP/IP:

Britannica<a-r>: The Internet is a packet-switched network, in which information is broken down into small packets, sent individually over many different routes at the same time, and then reassembled at the receiving end. TCP is the component that collects and reassembles the packets of data, while IP is responsible for making sure the packets are sent to the right destination. TCP/IP was developed in the 1970s and adopted as the protocol standard for ARPANET (the predecessor to the Internet) in 1983.

H4S1: TCP socket:

IBM-docs: A socket programming interface provides the routines required for inter.process-communication between | applications, either on the local system or spread in a distributed, TCP/IP based network environment. Once a peer-to-peer connection is established, a socket descriptor is used to uniquely identify the connection.

Offline-sockets<Lowes>

One end of a peer-to-peer connection of a TCP/IP based distributed network application described by a socket is uniquely defined by

  • Internet address: for example 127.0.0.1 (in an IPv4 network) or FF01::101 (in an IPv6 network).
  • Communication protocol
    • User Datagram Protocol (UDP)
    • Transmission Control Protocol (TCP)
  • Port: A numerical value, identifying an application. We distinguish between
    • “well known” ports, for example port 23 for Telnet
    • user defined ports

Socket applications were usually C or C++ applications using a variation of the socket API originally defined by the Berkeley Software Distribution (BSD).

H3S3: Web-RTC:

H3S4: HTTP:

Wang<pg-4>: Listing 1-1. HTTP/1.1 Request Headers from the Client to the Server

GET /PollingStock/PollingStock HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5)
Gecko/20091102 Firefox/3.5.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8080/PollingStock/
Cookie: showInheritedConstant=false; showInheritedProtectedConst
ant=false; showInheritedProperty=false; showInheritedProtectedPr
operty=false; showInheritedMethod=false; showInheritedProtectedM
ethod=false; showInheritedEvent=false; showInheritedStyle=false;
showInheritedEffect=false;

Hu: I never had to write, or even have seen, an HTTP-req, while building in WAMP, locally, so does Apache or PHP-install handle this? It must, at some point, translate one of my MySQL or require data requests into an HTTP request<80% 10/29/22>.

Wang<pg-4>: Listing 1-2. HTTP/1.1 Response Headers from the Server to the Client

HTTP/1.x 200 OK
X-Powered-By: Servlet/2.5
Server: Sun Java System Application Server 9.1_02
Content-Type: text/html;charset=UTF-8
Content-Length: 321
Date: Wed, 06 Dec 2012 00:32:46 GMT

H4S1: HTTP is half-duplex:

Wang<pg-4>: By nature, HTTP is also half duplex, meaning that traffic flows in a single direction at
a time: the client sends a request to the server (one direction); the server then responds
to the request (one direction).

H3S5: Channeled information flow bidirectionally into a web-server<Turing>:

Hu: A web-server, conceived of as a living, breathing organism, divides up its information-intake into different senses, each of which accepts a different data-type<#n-p x Turing>; however, the correct data type, has to strike at the correct sensory organ; shining a flashlight up to your ear, will not lead to your perception of light<insight!> Analogously, the correct data type to a web-server must flow through the correct origin, and an origin is defined as:

“Two URIs are considered from the same origin if and only if they have the same scheme, host and port. The path is not considered in the origin value. The following examples show mismatched schemes, hosts, and ports (and therefore different origins):”

Wang<a-r>
https://www.example.com and http://www.example.com
http://www.example.com and http://example.com
http://example.com:8080 and http://example.com:8081

The following examples are URLs of the same origin:

http://www.example.com/page1.html and http://www.example.com/page2.html.

Hu: As of ’22, 90% of web content flows through a single sense, the HTTP-origin<sometimes-HTTPS, if SSL is installed>; if any other protocol, such as WebSockets or Web-RTC were used, then that information would, by definition, flow through a different origin, even if it were from the same domain<Turing>. This insight provides a complexity | evaluation to adding a new origin to one’s content delivery: you have to manage a separate origin, from something as basic as HTTP. However, with the paradigm of condition.oriented-prog<WP.MIC-H2S58>, this need not double the complexity of your entire software-architecture<Turing> because the conditional management of the flow of information should be greater, in total information density, than the description of the sensory modality of their input and output; this applies to your brain as well.

References:

https://developer.mozilla.org/en-US/docs/Web/API

WebSockets:

https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

https://hgsweb.de/phpwebsocketDoc/book/index.php

https://en.wikipedia.org/wiki/WebSocket

https://github.com/napengam/phpWebSocketServer/blob/master/include/adressPort.inc.php

Lengstorf, Jason, and Phil Leggetter. Realtime Web Apps: HTML, Websocket, PHP, and JQuery. Apress.

Wang, Vanessa, et al. HTML5 WebSocket: Build Real-Time Applications w/ HTML5. Apress.

TCP/IP:

https://www.britannica.com/technology/TCP-IP

https://www.ibm.com/docs/en/SSB27H_6.2.0/fa2ti_what_is_socket_connection.html#:~:text=A%20socket%20programming%20interface%20provides,to%20uniquely%20identify%20the%20connection.

https://www.rfc-editor.org/rfc/rfc6455

https://www.rfc-editor.org/rfc/rfc4648#section-4

https://www.php.net/manual/en/function.sha1.php

https://www.php.net/manual/en/function.base64-encode.php

https://www.php.net/manual/en/function.base64-decode.php

https://www.php.net/manual/en/language.operators.bitwise.php


Leave a Reply

Your email address will not be published. Required fields are marked *