80 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { TextInput } from "./TextInput";
 | |
| 
 | |
| export function IPInput(p: {
 | |
|   label: string;
 | |
|   editable: boolean;
 | |
|   value?: string;
 | |
|   onValueChange?: (newVal: string | undefined) => void;
 | |
|   version: 4 | 6;
 | |
| }): React.ReactElement {
 | |
|   const { onValueChange, ...props } = p;
 | |
|   return (
 | |
|     <TextInput
 | |
|       onValueChange={(v) => {
 | |
|         onValueChange?.(p.version === 4 ? sanitizeIpV4(v) : sanitizeIpV6(v));
 | |
|       }}
 | |
|       {...props}
 | |
|     />
 | |
|   );
 | |
| }
 | |
| 
 | |
| function sanitizeIpV4(s: string | undefined): string | undefined {
 | |
|   if (s === "" || s === undefined) return s;
 | |
| 
 | |
|   let split = s.split(".");
 | |
|   if (split.length > 4) split.splice(4);
 | |
| 
 | |
|   let needAnotherIteration = false;
 | |
| 
 | |
|   const res = split
 | |
|     .map((v) => {
 | |
|       if (v === "") return "";
 | |
| 
 | |
|       const num = Number(v);
 | |
|       if (isNaN(num) || num < 0) return "0";
 | |
|       if (num > 255) {
 | |
|         needAnotherIteration = true;
 | |
|         return v.slice(0, 2) + "." + v.slice(2);
 | |
|       }
 | |
|       return num.toString();
 | |
|     })
 | |
|     .join(".");
 | |
| 
 | |
|   return needAnotherIteration ? sanitizeIpV4(res) : res;
 | |
| }
 | |
| 
 | |
| function sanitizeIpV6(s: string | undefined): string | undefined {
 | |
|   if (s === "" || s === undefined) return s;
 | |
| 
 | |
|   const split = s.split(":");
 | |
|   if (split.length > 8) split.splice(8);
 | |
| 
 | |
|   let needAnotherIteration = false;
 | |
| 
 | |
|   let res = split
 | |
|     .map((e) => {
 | |
|       if (e === "") return e;
 | |
| 
 | |
|       const num = parseInt(e, 16);
 | |
|       if (isNaN(num)) return "0";
 | |
| 
 | |
|       let s = num.toString(16);
 | |
|       if (num > 0xffff) {
 | |
|         needAnotherIteration = true;
 | |
|         return s.slice(0, 4) + ":" + s.slice(4);
 | |
|       }
 | |
| 
 | |
|       return s;
 | |
|     })
 | |
|     .join(":");
 | |
| 
 | |
|   const firstIndex = res.indexOf("::");
 | |
|   let nextIndex = res.lastIndexOf("::");
 | |
|   while (nextIndex !== firstIndex) {
 | |
|     res = res.slice(0, nextIndex) + res.slice(nextIndex + 1);
 | |
|     nextIndex = res.lastIndexOf("::");
 | |
|   }
 | |
| 
 | |
|   return needAnotherIteration ? sanitizeIpV6(res) : res;
 | |
| }
 |