I'm working on a function that calculates the decimal equivalent of an IP, in order to get the result I'm using this formula:
decimal = ((octet1 * 16777216) + (octet2 * 65536) + (octet13 * 256) + (octet4))
Does anybody know how to reverse this process, I mean, how can I get the IP address from the decimal number.
I'm looking for some mathematical formula, I already know about nslookup command.
Thanks in advance.
To decimal:
decimal = (octet1 * 256^3) + (octet2 * 256^2) + (octet3 * 256^1) + octet4
To octets:
octet1 = Floor(decimal / 256^3)
octet2 = Floor((decimal - (octet1 * 256^3)) / 256^2)
octet3 = Floor((decimal - (octet1 * 256^3) - (octet2 * 256^2)) / 256^1)
octet4 = decimal - (octet1 * 256^3) - (octet2 * 256^2) - (octet3 * 256^1)
Example using 1.2.3.4
decimal = (1 * 256^3) + (2 * 256^2) + (3 * 256^1) + 4
decimal = 16909060
Calculation
octet1 = Floor(16909060 / 256^3)
octet1 = 1
Calculation
octet2 = Floor((16909060 - (1 * 256^3)) / 256^2)
octet2 = 2
Calculation
octet3 = Floor((16909060 - (1 * 256^3) - (2 * 256^2)) / 256^1)
octet3 = 3
Calculation
octet4 = 16909060 - (1 * 256^3) - (2 * 256^2) - (3 * 256^1)
octet4 = 4
Calculation
Implementation Using Go
package main
import (
"errors"
"flag"
"fmt"
"math"
"os"
"strconv"
"strings"
)
var (
ip = flag.String("i", "", "IP address in dotted notation")
dec = flag.Int("d", 0, "IP address in decimal notation")
)
func ipv4ToDec(ip string) (int, error) {
var result int
octets := strings.Split(ip, ".")
if len(octets) != 4 {
return 0, errors.New("IP should consist of 4 '.' seperated numbers")
}
for i := 0; i < 4; i++ {
v, err := strconv.Atoi(octets[3-i])
if err != nil {
return 0, errors.New("unable to convert octet to number")
}
if v < 0 || v > 255 {
return 0, errors.New("octet should be between 0 and 255")
}
result += v * int(math.Pow(256, float64(i)))
}
return result, nil
}
func decToIpv4(dec int) (string, error) {
var octets []string
for i := 0; i < 4; i++ {
octet := dec / int(math.Pow(256, float64(3-i)))
if octet > 255 {
return "", errors.New("octet larger than 255")
}
dec -= octet * int(math.Pow(256, float64(3-i)))
octets = append(octets, strconv.Itoa(octet))
}
return strings.Join(octets, "."), nil
}
func main() {
flag.Parse()
if ((*ip != "" && *dec != 0) || (*ip == "" && *dec == 0)) {
fmt.Println("Use either -i or -d.")
os.Exit(1)
}
if *ip != "" {
result, err := ipv4ToDec(*ip)
if err != nil {
fmt.Println("Conversion failed: ", err)
os.Exit(1)
}
fmt.Println(result)
}
if *dec != 0 {
result, err := decToIpv4(*dec)
if err != nil {
fmt.Println("Conversion failed: ", err)
os.Exit(1)
}
fmt.Println(result)
}
}
Usage:
$ ./ip-conv -i 1.2.3.4
16909060
$ ./ip-conv -d 16909060
1.2.3.4
$ ./ip-conv -i 192.168.0.1
3232235521
# Using the output of IP->decimal as input to decimal->IP
$ ./ip-conv -d $(./ip-conv -i 192.168.0.1)
192.168.0.1
Multiplying and dividing is a waste of computational power. Remember that you're dealing with bit patterns:
o1.o2.o3.o4 to numeric:
n = o1<<24 | o2<<16 | o3<<8 | o4
numeric to octets:
o1 = n>>24
o2 = (n>>16) & 255
o3 = (n>>8) & 255
o4 = n & 255
Related
I've been trying to create a function in GDScript to process and calculate a string using PEMDAS rules. Below is my try on the subject. It can so far only use the MDAS rules:
Is there a better way to achieve such a function?
func _ready() -> void:
### USE CASES ###
print(Compute_String("1+2*3+3=")) # Output = 10
print(Compute_String("1+2*3*3=")) # Output = 19
print(Compute_String("1*2*3+3=")) # Output = 9
print(Compute_String("1+2+3*3=")) # Output = 12
print(Compute_String("5*2+7-3/2=")) # Output = 15.5
print(Compute_String("9+5.5*2.25=")) # Output = 21.375
print(Compute_String("5*2+7-3/2")) # Output = 1.#QNAN (Missing equals)
print(Compute_String("5*2+7-/2=")) # Output = 1.#QNAN (Adjacent operators)
print(Compute_String("*2+7-3/2=")) # Output = 1.#QNAN (Begins with operator)
print(Compute_String("")) # Output = 1.#QNAN (Empty)
print(Compute_String("=")) # Output = 1.#QNAN (Considered as empty)
print(Compute_String("1 +2=")) # Output = 1.#QNAN (Contains space)
print(Compute_String("(1+2)*3=")) # Output = 1.#QNAN (Parentheses not supported)
func Compute_String(_string: String) -> float:
var _result: float = NAN
var _elements: Array = []
if not _string.empty() and _string[_string.length() - 1] == "=":
var _current_element: String = ""
for _count in _string.length():
if _string[_count].is_valid_float() or _string[_count] == ".": _current_element += _string[_count]
else:
if _string[_count - 1].is_valid_float() and (_string[_count + 1].is_valid_float() if _string[_count] != "=" else true):
_elements.append_array([_current_element,_string[_count]]) ; _current_element = ""
else: return NAN
if not _elements.empty():
_elements.resize(_elements.size() - 1)
while _get_operators_count(_elements) != 0:
var _id: Array = [0, 0.0, 0.0]
if "*" in _elements:
_id = _add_adjacent(_elements, "*") ; _remove_adjacent(_elements, _id[0]) ; _elements.insert(_id[0] - 1, _id[1] * _id[2])
elif "/" in _elements:
_id = _add_adjacent(_elements, "/") ; _remove_adjacent(_elements, _id[0]) ; _elements.insert(_id[0] - 1, _id[1] / _id[2])
elif "+" in _elements:
_id = _add_adjacent(_elements, "+") ; _remove_adjacent(_elements, _id[0]) ; _elements.insert(_id[0] - 1, _id[1] + _id[2])
elif "-" in _elements:
_id = _add_adjacent(_elements, "-") ; _remove_adjacent(_elements, _id[0]) ; _elements.insert(_id[0] - 1, _id[1] - _id[2])
else: return NAN
if _elements.size() == 1: _result = _elements[0]
return _result
func _get_operators_count(_elements: Array) -> int:
var _result: int = 0 ; for _element in _elements: if not str(_element).is_valid_float(): _result += 1 ; return _result
func _add_adjacent(_elements: Array, _operator) -> Array:
return [_elements.find(_operator), float(_elements[_elements.find(_operator) - 1]), float(_elements[_elements.find(_operator) + 1])]
func _remove_adjacent(_elements: Array, _operator_idx: int) -> void:
_elements.remove(_operator_idx + 1) ; _elements.remove(_operator_idx) ; _elements.remove(_operator_idx - 1)
In TYPO3 mailto links are decrypted by the following code snippet.
Is there a way to use this with mailto links, which contain subject and body text?
e.g.: email#example.org?subject=This is my subject&body=This is my bodytext: more text...etc.
// decrypt helper function
function decryptCharcode(n,start,end,offset) {
n = n + offset;
if (offset > 0 && n > end) {
n = start + (n - end - 1);
} else if (offset < 0 && n < start) {
n = end - (start - n - 1);
}
return String.fromCharCode(n);
}
// decrypt string
function decryptString(enc,offset) {
var dec = "";
var len = enc.length;
for(var i=0; i < len; i++) {
var n = enc.charCodeAt(i);
if (n >= 0x2B && n <= 0x3A) {
dec += decryptCharcode(n,0x2B,0x3A,offset); // 0-9 . , - + / :
} else if (n >= 0x40 && n <= 0x5A) {
dec += decryptCharcode(n,0x40,0x5A,offset); // A-Z #
} else if (n >= 0x61 && n <= 0x7A) {
dec += decryptCharcode(n,0x61,0x7A,offset); // a-z
} else {
dec += enc.charAt(i);
}
}
return dec;
}
// decrypt spam-protected emails
function linkTo_UnCryptMailto(s) {
location.href = decryptString(s,-3);
}
if it does not run by default (maybe it depends on usage, from where to what app, but I remember that I used it already).
You might need to encode special characters for usage in URLs.
Try to use PHP function urlencode.
So you could replace all spaces with %20 or +.
Hmm, that works for me (TYPO3 v10).
TypoScript setup:
config.spamProtectEmailAddresses = -3
https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/Setup/Config/Index.html#spamprotectemailaddresses
Fluid:
<f:link.email email="my#email.tld?subject=123&body=Hello there!">link</f:link.email>
That opens my E-Mail-Client with subject and body (Firefox 84, Thunderbird).
How can I obtain value from header that have multiple comma separated values. For instance,
url := "https://accounts.google.com/.well-known/openid-configuration"
resp, err := http.Get(url)
field := resp.Header.Get("Cache-Control") // "public, max-age=3600"
In this case I want get max-age value. I see 2 cases:
using strings.Split(), Trim() and etc (I think it's not good idea)
using bufio.Scanner with SplitFunc (little bit better)
Any good idea or best practice?
Edit 1. Using strings.FieldsFunc()
const input = " public,max-age=3000, anothercase "
sep := func(c rune) bool {
return c == ',' || c == ' '
}
values := strings.FieldsFunc(input, sep)
Regarding benchmarks
BenchmarkTrim-4 2000000 861 ns/op 48 B/op 1 allocs/op
Edit 2. Using Scaner()
So lets benchmark it
func ScanHeaderValues(data []byte, atEOF bool) (advance int, token []byte, err error) {
// Skip leading spaces.
var start int
for start = 0; start < len(data); start++ {
if data[start] != ' ' {
break
}
}
// Scan until comma
for i := start; i < len(data); i++ {
if data[i] == ',' {
return i + 1, data[start:i], nil
}
}
// If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
if atEOF && len(data) > start {
return len(data), data[start:], nil
}
// Request more data.
return start, nil, nil
}
func BenchmarkScanner(b *testing.B) {
const input = " public,max-age=3000, anothercase "
scanner := bufio.NewScanner(strings.NewReader(input))
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
advance, token, err = ScanHeaderValues(data, atEOF)
return
}
scanner.Split(split)
b.ResetTimer()
for i := 0; i < b.N; i++ {
for scanner.Scan() {
// a := scanner.Text()
// b.Logf("%+v\n", a)
}
}
}
And result:
BenchmarkTrim-4 2000000 861 ns/op 48 B/op 1 allocs/op
BenchmarkScanner-4 50000000 21.2 ns/op 0 B/op 0 allocs/op
If you have any other better solution I would like see it.
Nothing wrong with:
url := "https://accounts.google.com/.well-known/openid-configuration"
resp, err := http.Get(url)
fields := strings.Split(resp.Header.Get("Cache-Control"), ",")
for i, field := range field {
fields[i] = strings.Trim(field, " ")
}
Edit: Edit now works if space after comma is missing
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <tgmath.h>
#include <limits.h>
#include <stdbool.h>
#include <errno.h>
#define NEGATIVE -1
#define POSITIVE 1
#define OCTAL 8
#define DECIMAL 10
#define HEXADECIMAL 16
#define BASE_MIN 2
#define BASE_MAX 36
long int strtol (const char * str, char ** endPtr, int base)
{
if(base < 0 || base == 1 || base > BASE_MAX)
{
errno = EINVAL;
return 0L;
}
else
{
bool conversion = true;
int i = 0, sign = POSITIVE, save;
while(isspace(*(str + i)))
i++;
if(*(str + i) == '\0')
{
conversion = false;
save = i;
}
if(*(str + i) == '-')
{
sign = NEGATIVE;
i++;
}
else if(*(str + i) == '+')
i++;
if(base == 0) // find out base
{
if(*(str + i) == '0')
{
if(toupper(*(str + i + 1)) == 'X')
{
base = HEXADECIMAL;
i++;
}
else
base = OCTAL;
i++;
}
else
base = DECIMAL;
}
else if(base == OCTAL)
{
if(*(str + i) == '0')
i++;
}
else if(base == HEXADECIMAL)
{
if(*(str + i) == '0')
if(*(str + i + 1) == 'x' || *(str + i + 1) == 'X')
i += 2;
}
int start = i, end, exp, check = i;
long int long_int, sum, multiplier;
if(conversion) // find out the correct part of the string corresponding to the number
{
if(base < DECIMAL)
{
while(*(str + i) >= '0' && *(str + i) < base + '0') // numbers from 0 to base - 1
i++;
}
else if(base == DECIMAL)
{
while(*(str + i) >= '0' && *(str + i) <= '9') // numbers from 0 to 9
i++;
}
else
{
while((*(str + i) >= '0' && *(str + i) <= '9') || (toupper(*(str + i)) >= 'A' && toupper(*(str + i)) < 'A' + base - 10))
i++;// numbers from 0 to 9 and uper and lowercase letters from a to a + base - 11
}
}
if(i == check && conversion) //no digits at all
{
conversion = false;
save = i;
}
else if(endPtr != NULL && conversion) // assign pointer
*endPtr = (char *) (str + i);
if(conversion)
{
for(end = i - 1, exp = 0, long_int = 0L; end >= start; end--, exp++)
{
multiplier = pow(base, exp);
sum = 0L;
if(*(str + end) >= '0' && *(str + end) <= '9')
sum = (*(str + end) - '0') * multiplier;
else if(*(str + end) >= 'A' && *(str + i) <= (base == BASE_MAX ? 'Z' : 'F'))
sum = (*(str + end) - 'A' + 10) * multiplier;
else if(*(str + end) >= 'a' && *(str + i) <= (base == BASE_MAX ? 'z' : 'f'))
sum = (*(str + end) - 'a' + 10) * multiplier;
if(long_int <= LONG_MIN + sum)
{
errno = ERANGE;
return LONG_MIN;
}
if(long_int >= LONG_MAX - sum)
{
errno = ERANGE;
return LONG_MAX;
}
else
long_int += sum;
}
return sign * long_int;
}
else
{
if(endPtr != NULL)
{// if base is 16 we check if the string given is not in the form 0xIncorrect string in that way we need to return xIncorrect part of the string
if(base == HEXADECIMAL && save >= 2 && toupper(*(str + save - 1)) == 'X' && *(str + save - 2) == '0')
*endPtr = (char *) str + save - 1;
else if(base == OCTAL && save >= 1 && *(str + save - 1) == '0')
*endPtr = (char *) str + save;// if the string is of base 8 and in the form 0incorrect string
else //then we return everything after the 0 as the endptr string
*endPtr = (char *) str;//in other cases no conversion was done so we return original pointer
}
return 0L;
}
}
}
I've got problem with writing implementation of strtol() function. The thing is i compiled it on 64 bit machine and the output was correct but today i checked it on another machine that is 32-bit and something got wrong. 32-bit machine showed the result that for example string "7FFFFFFF" is out of range when on 64-bits the results is that strtol succeded which is the same as for th standard function. I also checked errno value and for 32-bit machine it's set to ERANGE which shouldn't be and it's not not on 64-bit. I have program that checks if your implementation gives the same output as the standard one for different strings. I spent few hours looking for possible bug but i'm out of ideas? Any tips?
public string Encrypt(string plainText) {
StringBuilder sb = new StringBuilder();
foreach (char c in plainText) {
if (Char.IsLetterOrDigit(c)) {
int num = (int)c;
num = ((num + 10) * 2) + 2;
sb.AppendFormat("{0} ", num.ToString());
}
else if (c == ' ') {
sb.Append("| ");
}
else if (c == '\n') {
sb.AppendLine();
}
}
return sb.ToString();
}
The encryption code uses the formula num = ((num + 10) * 2) + 2;
Reversing that is num = ((num - 2) / 2) - 10;
Now convert it back from an integer to a character.
You will need to recognise spaces and newlines in the cyphertext separately.