Added API calls for Secure Connection,Virus Total Check and Redirects

This commit is contained in:
2024-07-07 21:54:10 +08:00
parent 304d5932f7
commit bca444d56d
5 changed files with 118 additions and 74 deletions

31
api/qrCodeAPI.tsx Normal file
View 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;
};

View File

@@ -1,47 +1,34 @@
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 { 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
interface ScannedDataBoxProps {
data: string;
dataType: string;
clearScanData: () => void;
}
// Define ScanResult interface
interface ScanResult {
scanResult: {
secureConnection: boolean;
virusTotalCheck: boolean;
redirects: number;
};
}
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData }) => {
const [scanResult, setScanResult] = useState<ScanResult | null>(null);
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData, scanResult }) => {
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("DataType", dataType);
// Set scan result based on data
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);
}, [data]);
// Determine the result text based on scan result
const getResultText = () => {
if (!scanResult) {
return 'UNKNOWN';
}
if (!scanResult.secureConnection && !scanResult.virusTotalCheck) {
return 'DANGEROUS';
} else if (scanResult.redirects > 0) {
@@ -65,22 +52,16 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
}
};
// Handle sharing the data
const handleShare = async () => {
const shareQRCodeData = async () => {
try {
await Share.share({
message: data,
});
console.log('Data shared:', data);
await Sharing.shareAsync(data);
} 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 handleOpen = () => {
const openWebView = () => {
setIsWebViewVisible(true);
console.log('Opening data in WebView:', data);
};
return (
@@ -111,17 +92,17 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
{/* Display scan checks */}
<Text style={styles.checksText}>Checks</Text>
<Text style={styles.checksText}>Secure Connection: {scanResult?.secureConnection ? '✔️' : '✘'}</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}>Secure Connection: {scanResult.secureConnection ? '✔️' : '✘'}</Text>
<Text style={styles.checksText}>Virus Total Check: {scanResult.virusTotalCheck ? '✔️' : '✘'}</Text>
<Text style={styles.checksText}>Redirects: {scanResult.redirects}</Text>
{/* Action buttons */}
<View style={styles.iconContainer}>
<TouchableOpacity style={styles.iconButton} onPress={handleShare}>
<TouchableOpacity style={styles.iconButton} onPress={shareQRCodeData}>
<Ionicons name="share-social" size={18} color="#2196F3" />
<Text style={styles.iconText}>Share</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.iconButton} onPress={handleOpen}>
<TouchableOpacity style={styles.iconButton} onPress={openWebView}>
<Ionicons name="open" size={18} color="#2196F3" />
<Text style={styles.iconText}>Open</Text>
</TouchableOpacity>
@@ -160,19 +141,26 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
</View>
</View>
</Modal>
{/* Modal for SecureWebView */}
<Modal
visible={isWebViewVisible}
transparent={true}
animationType="fade"
animationType="slide"
onRequestClose={() => setIsWebViewVisible(false)}
>
<View style={styles.modalContainer}>
<View style={styles.webViewContainer}>
<TouchableOpacity style={styles.closeWebViewButton} onPress={() => setIsWebViewVisible(false)}>
<Ionicons name="close-circle-outline" size={24} color="#fff" />
<WebView
source={{ uri: 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>
<SecureWebView url={data} />
</View>
</View>
</Modal>
</View>
@@ -316,18 +304,11 @@ const styles = StyleSheet.create({
color: '#fff',
},
webViewContainer: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
webView: {
flex: 1,
marginTop: 40,
},
closeWebViewButton: {
position: 'absolute',
top: 10,
right: 10,
zIndex: 1,
width: '100%',
height: '80%',
backgroundColor: 'white',
borderRadius: 7.5,
overflow: 'hidden'
},
});

9
package-lock.json generated
View File

@@ -17,6 +17,7 @@
"expo-camera": "~15.0.10",
"expo-image-manipulator": "^12.0.5",
"expo-image-picker": "~15.0.5",
"expo-sharing": "~12.0.1",
"expo-status-bar": "~1.12.1",
"react": "18.2.0",
"react-native": "0.74.2",
@@ -7882,6 +7883,14 @@
"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": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.12.1.tgz",

View File

@@ -25,7 +25,8 @@
"react-native-safe-area-context": "^4.10.4",
"react-native-webview": "^13.10.4",
"react-redux": "^9.1.2",
"redux": "^5.0.1"
"redux": "^5.0.1",
"expo-sharing": "~12.0.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",

View File

@@ -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 { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
import { useDispatch } from 'react-redux';
import { QRCodeContext } from '../types';
import axios from 'axios'; // For URL calls
import { Ionicons } from '@expo/vector-icons'; // For icons
import { useNavigation } from '@react-navigation/native';
import * as ImagePicker from 'expo-image-picker';
import ScannedDataBox from '../components/ScannedDataBox';
import { addQRCode } from '../actions/qrCodeActions';
interface QRScannerScreenProps {
clearScanData: () => void;
}
import { useDispatch } from 'react-redux';
import { addQRCode } from '../actions/qrCodeActions'; // Assuming you have actions defined for Redux
import { detectQRCodeType, verifyURL, checkRedirects } from '../api/qrCodeAPI'; // Import utility functions
// Main Function
const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanData }) => {
const navigation = useNavigation(); // call Navigation bar
const dispatch = useDispatch(); // Use dispatch for Redux actions
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 [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 [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
useEffect(() => {
const initializeApp = async () => {
@@ -49,17 +55,24 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
const handlePayload = async (payload: string) => {
setScanned(true);
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 = {
data: payload,
type,
scanResult: {
secureConnection: true, // Placeholder, replace with actual logic
virusTotalCheck: true, // Placeholder, replace with actual logic
redirects: 0 // Placeholder, replace with actual logic
secureConnection: secureConnectionResult.isSecure,
virusTotalCheck: !secureConnectionResult.isMalicious,
redirects: redirectResult.redirects
},
bookmarked: false, // Add the bookmarked property
bookmarked: false // by default
};
setScannedData(payload);
@@ -185,7 +198,16 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
{scannedData !== '' && (
<View style={styles.scannedDataBox}>
<ScannedDataBox data={scannedData} dataType={dataType} clearScanData={clearScanDataInternal} />
<ScannedDataBox
data={scannedData}
dataType={dataType}
clearScanData={clearScanDataInternal}
scanResult={{
secureConnection,
virusTotalCheck,
redirects
}}
/>
</View>
)}
</View>