Skip to content

Commit

Permalink
Implemented roDeviceInfo.getExternalIP() (#397)
Browse files Browse the repository at this point in the history
* Implemented `roDeviceInfo.getExternalIP()`

* Simplify `isValidIP`
  • Loading branch information
lvcabral authored Nov 16, 2024
1 parent 2467183 commit ec2e4fb
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 4 deletions.
30 changes: 29 additions & 1 deletion src/worker/brsTypes/components/RoDeviceInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { RoAssociativeArray, AAMember } from "./RoAssociativeArray";
import { RoArray } from "./RoArray";
import { v4 as uuidv4 } from "uuid";
import * as crypto from "crypto";
/// #if !BROWSER
import { XMLHttpRequest } from "../../polyfill/XMLHttpRequest";
/// #endif

export class RoDeviceInfo extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
Expand Down Expand Up @@ -914,7 +917,32 @@ export class RoDeviceInfo extends BrsComponent implements BrsValue {
args: [],
returns: ValueKind.String,
},
impl: (_interpreter) => {
impl: (interpreter: Interpreter) => {
const url = "https://api.ipify.org";
try {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, false); // Note: synchronous
xhr.responseType = "text";
xhr.send();
if (xhr.status !== 200) {
if (interpreter.isDevMode) {
interpreter.stderr.write(
`warning,[getExternalIp] Error getting ${url}: status ${xhr.status} - ${xhr.statusText}`
);
}
return new BrsString("");
}
const ip = xhr.responseText;
if (interpreter.isValidIp(ip)) {
return new BrsString(ip);
}
} catch (err: any) {
if (interpreter.isDevMode) {
interpreter.stderr.write(
`warning,[getExternalIp] Error getting ${url}: ${err.message}`
);
}
}
return new BrsString("");
},
});
Expand Down
16 changes: 16 additions & 0 deletions src/worker/interpreter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2116,6 +2116,22 @@ export class Interpreter implements Expr.Visitor<BrsType>, Stmt.Visitor<BrsType>
throw err;
}

/**
* Method to evaluate if a string is a valid IP address
* @param ip the string to evaluate
* @returns whether the string is a valid IP address
*/
public isValidIp(ip: string): boolean {
const parts = ip.split(".");
return (
parts.length === 4 &&
parts.every((part) => {
const num = Number(part);
return !isNaN(num) && num >= 0 && num <= 255;
})
);
}

private formatErrorVariable(err: BrsError) {
const btArray = this.formatBacktrace(err.location, false, err.backTrace) as RoArray;
let errDetail = RuntimeErrorDetail.Internal;
Expand Down
4 changes: 3 additions & 1 deletion test/brsTypes/components/RoDeviceInfo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,9 @@ describe("RoDeviceInfo", () => {
let method = deviceInfo.getMethod("getExternalIp");

expect(method).toBeTruthy();
expect(method.call(interpreter)).toEqual(new BrsString(""));
let result = method.call(interpreter);
expect(result).toBeInstanceOf(BrsString);
expect(interpreter.isValidIp(result.value)).toBe(true);
});
});
describe("getIPAddrs", () => {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/BrsComponents.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ describe("end to end brightscript functions", () => {
"true",
"true",
"WiredConnection",
"",
"true",
" 1",
" 3",
"HDTV",
Expand Down
15 changes: 14 additions & 1 deletion test/e2e/resources/components/roDeviceInfo.brs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sub main()
print deviceInfo.getLinkStatus()
print deviceInfo.enableLinkStatusEvent(true)
print deviceInfo.getConnectionType()
print deviceInfo.getExternalIp()
print isValidIP(deviceInfo.getExternalIp())
print deviceInfo.getIPAddrs().count()
print deviceInfo.getConnectionInfo().count()
print deviceInfo.getDisplayType()
Expand All @@ -65,3 +65,16 @@ sub main()
print deviceInfo.enableAudioGuideChangedEvent(true)

end sub

function isValidIP(ip as String) as Boolean
' Regular expression pattern for a valid IPv4 address
ipPattern = "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
' Create a regex object
regex = CreateObject("roRegex", ipPattern)
' Check if the IP matches the pattern
if regex.IsMatch(ip)
return true
else
return false
end if
end function

0 comments on commit ec2e4fb

Please sign in to comment.