Added API calls for Secure Connection,Virus Total Check and Redirects
This commit is contained in:
31
api/qrCodeAPI.tsx
Normal file
31
api/qrCodeAPI.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const API_BASE_URL = 'http://192.168.10.247:8080/v1/api/qrcodetypes';
|
||||||
|
|
||||||
|
export const detectQRCodeType = async (data: string) => {
|
||||||
|
console.log('API Call - Detect QR Code Type:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/detect`, { data });
|
||||||
|
console.log('API Response - QR Code Type:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const verifyURL = async (data: string) => {
|
||||||
|
console.log('API Call - Verify URL:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/verifyURL`, { data });
|
||||||
|
console.log('API Response - Verify URL:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const virusTotalCheck = async (data: string) => {
|
||||||
|
console.log('API Call - Virus Total Check:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/virusTotalCheck`, { data });
|
||||||
|
console.log('API Response - Virus Total Check:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkRedirects = async (data: string) => {
|
||||||
|
console.log('API Call - Check Redirects:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/checkRedirects`, { data });
|
||||||
|
console.log('API Response - Check Redirects:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
@@ -1,47 +1,34 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { View, Text, StyleSheet, Image, TouchableOpacity, Modal, Share } from 'react-native';
|
import { View, Text, StyleSheet, Image, TouchableOpacity, Modal } from 'react-native';
|
||||||
import QRCode from 'react-native-qrcode-svg';
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
import SecureWebView from './SecureWebView'; // Import the SecureWebView component
|
import * as Sharing from 'expo-sharing';
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
|
||||||
// Define Props for ScannedDataBox component
|
// Define Props for ScannedDataBox component
|
||||||
interface ScannedDataBoxProps {
|
interface ScannedDataBoxProps {
|
||||||
data: string;
|
data: string;
|
||||||
dataType: string;
|
dataType: string;
|
||||||
clearScanData: () => void;
|
clearScanData: () => void;
|
||||||
|
scanResult: {
|
||||||
|
secureConnection: boolean;
|
||||||
|
virusTotalCheck: boolean;
|
||||||
|
redirects: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define ScanResult interface
|
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData, scanResult }) => {
|
||||||
interface ScanResult {
|
|
||||||
secureConnection: boolean;
|
|
||||||
virusTotalCheck: boolean;
|
|
||||||
redirects: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData }) => {
|
|
||||||
const [scanResult, setScanResult] = useState<ScanResult | null>(null);
|
|
||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
const [isWebViewVisible, setIsWebViewVisible] = useState(false); // State to control WebView modal visibility
|
const [isWebViewVisible, setIsWebViewVisible] = useState(false);
|
||||||
|
|
||||||
console.log("ScannedDataBox -> Data", data);
|
console.log("ScannedDataBox -> Data", data);
|
||||||
console.log("DataType", dataType);
|
console.log("DataType", dataType);
|
||||||
|
|
||||||
// Set scan result based on data
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Assuming scanResult is directly related to data
|
|
||||||
setScanResult({
|
|
||||||
secureConnection: data.includes('https'), // Example logic
|
|
||||||
virusTotalCheck: !data.includes('danger'), // Example logic
|
|
||||||
redirects: data.includes('redirect') ? 1 : 0, // Example logic
|
|
||||||
});
|
|
||||||
console.log("Scan result set:", scanResult);
|
console.log("Scan result set:", scanResult);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
// Determine the result text based on scan result
|
// Determine the result text based on scan result
|
||||||
const getResultText = () => {
|
const getResultText = () => {
|
||||||
if (!scanResult) {
|
|
||||||
return 'UNKNOWN';
|
|
||||||
}
|
|
||||||
if (!scanResult.secureConnection && !scanResult.virusTotalCheck) {
|
if (!scanResult.secureConnection && !scanResult.virusTotalCheck) {
|
||||||
return 'DANGEROUS';
|
return 'DANGEROUS';
|
||||||
} else if (scanResult.redirects > 0) {
|
} else if (scanResult.redirects > 0) {
|
||||||
@@ -65,22 +52,16 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle sharing the data
|
const shareQRCodeData = async () => {
|
||||||
const handleShare = async () => {
|
|
||||||
try {
|
try {
|
||||||
await Share.share({
|
await Sharing.shareAsync(data);
|
||||||
message: data,
|
|
||||||
});
|
|
||||||
console.log('Data shared:', data);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error sharing the data:', error);
|
console.error('Error sharing QR code data:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle opening the data in a sandboxed WebView
|
const openWebView = () => {
|
||||||
const handleOpen = () => {
|
|
||||||
setIsWebViewVisible(true);
|
setIsWebViewVisible(true);
|
||||||
console.log('Opening data in WebView:', data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -111,17 +92,17 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
|||||||
|
|
||||||
{/* Display scan checks */}
|
{/* Display scan checks */}
|
||||||
<Text style={styles.checksText}>Checks</Text>
|
<Text style={styles.checksText}>Checks</Text>
|
||||||
<Text style={styles.checksText}>Secure Connection: {scanResult?.secureConnection ? '✔️' : '✘'}</Text>
|
<Text style={styles.checksText}>Secure Connection: {scanResult.secureConnection ? '✔️' : '✘'}</Text>
|
||||||
<Text style={styles.checksText}>Virus Total Check: {scanResult?.virusTotalCheck ? '✔️' : '✘'}</Text>
|
<Text style={styles.checksText}>Virus Total Check: {scanResult.virusTotalCheck ? '✔️' : '✘'}</Text>
|
||||||
<Text style={styles.checksText}>Redirects: {scanResult ? scanResult.redirects : 'N/A'}</Text>
|
<Text style={styles.checksText}>Redirects: {scanResult.redirects}</Text>
|
||||||
|
|
||||||
{/* Action buttons */}
|
{/* Action buttons */}
|
||||||
<View style={styles.iconContainer}>
|
<View style={styles.iconContainer}>
|
||||||
<TouchableOpacity style={styles.iconButton} onPress={handleShare}>
|
<TouchableOpacity style={styles.iconButton} onPress={shareQRCodeData}>
|
||||||
<Ionicons name="share-social" size={18} color="#2196F3" />
|
<Ionicons name="share-social" size={18} color="#2196F3" />
|
||||||
<Text style={styles.iconText}>Share</Text>
|
<Text style={styles.iconText}>Share</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.iconButton} onPress={handleOpen}>
|
<TouchableOpacity style={styles.iconButton} onPress={openWebView}>
|
||||||
<Ionicons name="open" size={18} color="#2196F3" />
|
<Ionicons name="open" size={18} color="#2196F3" />
|
||||||
<Text style={styles.iconText}>Open</Text>
|
<Text style={styles.iconText}>Open</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -160,19 +141,26 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
{/* Modal for SecureWebView */}
|
|
||||||
<Modal
|
<Modal
|
||||||
visible={isWebViewVisible}
|
visible={isWebViewVisible}
|
||||||
transparent={true}
|
transparent={true}
|
||||||
animationType="fade"
|
animationType="slide"
|
||||||
onRequestClose={() => setIsWebViewVisible(false)}
|
onRequestClose={() => setIsWebViewVisible(false)}
|
||||||
>
|
>
|
||||||
<View style={styles.webViewContainer}>
|
<View style={styles.modalContainer}>
|
||||||
<TouchableOpacity style={styles.closeWebViewButton} onPress={() => setIsWebViewVisible(false)}>
|
<View style={styles.webViewContainer}>
|
||||||
<Ionicons name="close-circle-outline" size={24} color="#fff" />
|
<WebView
|
||||||
</TouchableOpacity>
|
source={{ uri: data }}
|
||||||
<SecureWebView url={data} />
|
javaScriptEnabled={false}
|
||||||
|
domStorageEnabled={false}
|
||||||
|
allowFileAccess={false}
|
||||||
|
originWhitelist={['*']}
|
||||||
|
onShouldStartLoadWithRequest={(request) => true}
|
||||||
|
/>
|
||||||
|
<TouchableOpacity style={styles.closeModalButton} onPress={() => setIsWebViewVisible(false)}>
|
||||||
|
<Text style={styles.closeModalButtonText}>Close</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
</View>
|
</View>
|
||||||
@@ -316,18 +304,11 @@ const styles = StyleSheet.create({
|
|||||||
color: '#fff',
|
color: '#fff',
|
||||||
},
|
},
|
||||||
webViewContainer: {
|
webViewContainer: {
|
||||||
flex: 1,
|
width: '100%',
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
height: '80%',
|
||||||
},
|
backgroundColor: 'white',
|
||||||
webView: {
|
borderRadius: 7.5,
|
||||||
flex: 1,
|
overflow: 'hidden'
|
||||||
marginTop: 40,
|
|
||||||
},
|
|
||||||
closeWebViewButton: {
|
|
||||||
position: 'absolute',
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
zIndex: 1,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -17,6 +17,7 @@
|
|||||||
"expo-camera": "~15.0.10",
|
"expo-camera": "~15.0.10",
|
||||||
"expo-image-manipulator": "^12.0.5",
|
"expo-image-manipulator": "^12.0.5",
|
||||||
"expo-image-picker": "~15.0.5",
|
"expo-image-picker": "~15.0.5",
|
||||||
|
"expo-sharing": "~12.0.1",
|
||||||
"expo-status-bar": "~1.12.1",
|
"expo-status-bar": "~1.12.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.74.2",
|
"react-native": "0.74.2",
|
||||||
@@ -7882,6 +7883,14 @@
|
|||||||
"invariant": "^2.2.4"
|
"invariant": "^2.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-sharing": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-wBT+WeXwapj/9NWuLJO01vi9bdlchYu/Q/xD8slL/Ls4vVYku8CPqzkTtDFcjLrjtlJqyeHsdQXwKLvORmBIew==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-status-bar": {
|
"node_modules/expo-status-bar": {
|
||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.12.1.tgz",
|
||||||
|
|||||||
@@ -25,7 +25,8 @@
|
|||||||
"react-native-safe-area-context": "^4.10.4",
|
"react-native-safe-area-context": "^4.10.4",
|
||||||
"react-native-webview": "^13.10.4",
|
"react-native-webview": "^13.10.4",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
"redux": "^5.0.1"
|
"redux": "^5.0.1",
|
||||||
|
"expo-sharing": "~12.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, Image } from 'react-native';
|
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, Image } from 'react-native';
|
||||||
import { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
|
import { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
|
||||||
import { useDispatch } from 'react-redux';
|
import { QRCodeContext } from '../types';
|
||||||
import axios from 'axios'; // For URL calls
|
import axios from 'axios'; // For URL calls
|
||||||
import { Ionicons } from '@expo/vector-icons'; // For icons
|
import { Ionicons } from '@expo/vector-icons'; // For icons
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import * as ImagePicker from 'expo-image-picker';
|
import * as ImagePicker from 'expo-image-picker';
|
||||||
import ScannedDataBox from '../components/ScannedDataBox';
|
import ScannedDataBox from '../components/ScannedDataBox';
|
||||||
import { addQRCode } from '../actions/qrCodeActions';
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { addQRCode } from '../actions/qrCodeActions'; // Assuming you have actions defined for Redux
|
||||||
interface QRScannerScreenProps {
|
import { detectQRCodeType, verifyURL, checkRedirects } from '../api/qrCodeAPI'; // Import utility functions
|
||||||
clearScanData: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main Function
|
// Main Function
|
||||||
const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanData }) => {
|
||||||
const navigation = useNavigation(); // call Navigation bar
|
const navigation = useNavigation(); // call Navigation bar
|
||||||
|
const dispatch = useDispatch(); // Use dispatch for Redux actions
|
||||||
|
|
||||||
const [showSplash, setShowSplash] = useState<boolean>(true); // call splash screen
|
const [showSplash, setShowSplash] = useState<boolean>(true); // call splash screen
|
||||||
const dispatch = useDispatch();
|
const qrCodeContext = useContext(QRCodeContext); // From ./types.ts
|
||||||
|
const { qrCodes, setQrCodes } = qrCodeContext || { qrCodes: [], setQrCodes: () => {} };
|
||||||
|
|
||||||
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
||||||
const [scanned, setScanned] = useState<boolean>(false);
|
const [scanned, setScanned] = useState<boolean>(false);
|
||||||
@@ -25,6 +26,11 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
|||||||
const [dataType, setDataType] = useState<string>(''); // State for data type
|
const [dataType, setDataType] = useState<string>(''); // State for data type
|
||||||
const [enableTorch, setEnableTorch] = useState<boolean>(false); // State for torch
|
const [enableTorch, setEnableTorch] = useState<boolean>(false); // State for torch
|
||||||
|
|
||||||
|
// Add state variables for scan results
|
||||||
|
const [secureConnection, setSecureConnection] = useState<boolean | null>(null);
|
||||||
|
const [virusTotalCheck, setVirusTotalCheck] = useState<boolean | null>(null);
|
||||||
|
const [redirects, setRedirects] = useState<number | null>(null);
|
||||||
|
|
||||||
// Request Camera Permission and initialize the app
|
// Request Camera Permission and initialize the app
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeApp = async () => {
|
const initializeApp = async () => {
|
||||||
@@ -49,17 +55,24 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
|||||||
const handlePayload = async (payload: string) => {
|
const handlePayload = async (payload: string) => {
|
||||||
setScanned(true);
|
setScanned(true);
|
||||||
console.log("Scanning Completed. Payload is:", payload);
|
console.log("Scanning Completed. Payload is:", payload);
|
||||||
const type = await sendToAPIServer(payload);
|
|
||||||
|
const type = await detectQRCodeType(payload);
|
||||||
|
const secureConnectionResult = await verifyURL(payload);
|
||||||
|
const redirectResult = await checkRedirects(payload);
|
||||||
|
|
||||||
|
setSecureConnection(secureConnectionResult.isSecure);
|
||||||
|
setVirusTotalCheck(!secureConnectionResult.isMalicious); // Assuming you have virusTotalCheck logic integrated here
|
||||||
|
setRedirects(redirectResult.redirects);
|
||||||
|
|
||||||
const qrCode = {
|
const qrCode = {
|
||||||
data: payload,
|
data: payload,
|
||||||
type,
|
type,
|
||||||
scanResult: {
|
scanResult: {
|
||||||
secureConnection: true, // Placeholder, replace with actual logic
|
secureConnection: secureConnectionResult.isSecure,
|
||||||
virusTotalCheck: true, // Placeholder, replace with actual logic
|
virusTotalCheck: !secureConnectionResult.isMalicious,
|
||||||
redirects: 0 // Placeholder, replace with actual logic
|
redirects: redirectResult.redirects
|
||||||
},
|
},
|
||||||
bookmarked: false, // Add the bookmarked property
|
bookmarked: false // by default
|
||||||
};
|
};
|
||||||
|
|
||||||
setScannedData(payload);
|
setScannedData(payload);
|
||||||
@@ -185,7 +198,16 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
|||||||
|
|
||||||
{scannedData !== '' && (
|
{scannedData !== '' && (
|
||||||
<View style={styles.scannedDataBox}>
|
<View style={styles.scannedDataBox}>
|
||||||
<ScannedDataBox data={scannedData} dataType={dataType} clearScanData={clearScanDataInternal} />
|
<ScannedDataBox
|
||||||
|
data={scannedData}
|
||||||
|
dataType={dataType}
|
||||||
|
clearScanData={clearScanDataInternal}
|
||||||
|
scanResult={{
|
||||||
|
secureConnection,
|
||||||
|
virusTotalCheck,
|
||||||
|
redirects
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user