diff --git a/iped-app/pom.xml b/iped-app/pom.xml index 07d95c32e9..9d0e7045bc 100644 --- a/iped-app/pom.xml +++ b/iped-app/pom.xml @@ -125,7 +125,7 @@ org.python python-jep-dlib - 3.9.12-4.0.3-19.23.1 + 3.9.12-4.0.3-19.23.1-2 zip false ${release.dir} @@ -315,7 +315,7 @@ tesseract tesseract-zip - 5.3.2-24-g3922 + 5.3.2-24-g3922_1 zip false ${tools.dir} diff --git a/iped-app/resources/config/IPEDConfig.txt b/iped-app/resources/config/IPEDConfig.txt index 98d7e024c6..5962493875 100644 --- a/iped-app/resources/config/IPEDConfig.txt +++ b/iped-app/resources/config/IPEDConfig.txt @@ -97,10 +97,12 @@ enableMinIO = false enableOCR = false # Enable audio transcription. -# Default implementation uses VOSK transcription on local CPU (slow and not good accuracy). -# You can change it to a local Facebook Wav2Vec2 implementation (slower on CPU, faster on GPU and good accuracy) -# or remote Microsoft Azure or Google Cloud services (faster and good accuracy). -# Configure it in conf/AudioTranscriptConfig.txt +# Default implementation uses VOSK transcription on local CPU (faster but bad accuracy). +# You can change the algorithm into conf/AudioTranscriptConfig.txt: +# - Wav2Vec2 algorithm (slower and good accuracy) +# - Whisper algorithm (much slower but better accuracy) +# - Google Cloud (about $1.00 per hour cost) +# - Microsoft Azure (about $1.00 per hour cost) enableAudioTranscription = false # Enables carving. "addUnallocated" must be enabled to scan unallocated space. diff --git a/iped-app/resources/config/LocalConfig.txt b/iped-app/resources/config/LocalConfig.txt index eb36d891aa..e131f9d5b9 100644 --- a/iped-app/resources/config/LocalConfig.txt +++ b/iped-app/resources/config/LocalConfig.txt @@ -2,7 +2,7 @@ # Local environment configuration ######################################################################## -# Defines program localization/language. Currently there are localizations for 'en', 'pt-BR', 'it-IT', 'de-DE' & 'es-AR' +# Defines program localization/language. Currently there are localizations for 'en', 'pt-BR', 'it-IT', 'de-DE', 'es-AR' and 'fr-FR'. locale = en # Temporary directory for processing: "default" uses the system temporary folder. diff --git a/iped-app/resources/config/conf/AudioTranscriptConfig.txt b/iped-app/resources/config/conf/AudioTranscriptConfig.txt index 67ac350618..7814aa1331 100644 --- a/iped-app/resources/config/conf/AudioTranscriptConfig.txt +++ b/iped-app/resources/config/conf/AudioTranscriptConfig.txt @@ -9,14 +9,23 @@ # you should download it from https://alphacephei.com/vosk/models and put in 'models/vosk/[lang]' folder. implementationClass = iped.engine.task.transcript.VoskTranscriptTask -# Uses a local/remote wav2vec2 implementation for transcription. Accuracy is much better than most Vosk models. -# The local impl is AT LEAST 1 order of magnitude slower than Vosk on high end CPUs. Using a good GPU is highly recommended! -# The remote impl is useful if you have a central server/cluster with many GPUs to be shared among processing nodes. -# For both the local or remote options, please check the installation steps: https://github.com/sepinf-inc/IPED/wiki/User-Manual#wav2vec2 -# If you use the local implementation, you must set 'huggingFaceModel' param below. -# If you use the remote implementation, you must set 'wav2vec2Service' param below. +# Uses a local wav2vec2 implementation for transcription. Accuracy is much better than most Vosk models. +# This is up to 10x slower than Vosk on high end CPUs. Using a good GPU is highly recommended! +# Please check the installation steps: https://github.com/sepinf-inc/IPED/wiki/User-Manual#wav2vec2 +# If you enable this, you must set 'huggingFaceModel' param below. #implementationClass = iped.engine.task.transcript.Wav2Vec2TranscriptTask -#implementationClass = iped.engine.task.transcript.RemoteWav2Vec2TranscriptTask + +# Uses a local Whisper implementation for transcription. Accuracy is better than wav2vec2 depending on the model. +# This is up to 4x slower than wav2vec2 depending on compared models. Using a high end GPU is strongly recommended! +# Please check the installation steps: https://github.com/sepinf-inc/IPED/wiki/User-Manual#whisper +# If you enable this, you must set 'whisperModel' param below. +#implementationClass = iped.engine.task.transcript.WhisperTranscriptTask + +# Uses a remote service for transcription. +# The remote service is useful if you have a central server/cluster with many GPUs to be shared among processing nodes. +# Please check steps on https://github.com/sepinf-inc/IPED/wiki/User-Manual#remote-transcription +# If you enable this, you must set 'remoteServiceAddress' param below. +#implementationClass = iped.engine.task.transcript.RemoteTranscriptionTask # If you want to use the Microsoft Azure service implementation, comment above and uncomment below. # You MUST include Microsoft client-sdk.jar into plugins folder. @@ -91,11 +100,32 @@ minWordScore = 0.5 # huggingFaceModel = jonatasgrosman/wav2vec2-xls-r-1b-french ######################################### -# RemoteWav2Vec2TranscriptTask options +# Local WhisperTranscriptTask options +######################################### + +# Possible values: tiny, base, small, medium, large-v3, dwhoelz/whisper-large-pt-cv11-ct2 +# large-v3 is much better than medium, but 2x slower and uses 2x more memory. +# If you know the language you want to transcribe, please set the 'language' option above. +# 'language = auto' uses the 'locale' set on LocalConfig.txt +# 'language = detect' uses auto detection, but it can cause mistakes +whisperModel = medium + +# Compute type precision. This affects accuracy, speed and memory usage. +# Possible values: float32 (better), float16 (recommended for GPU), int8 (faster) +precision = int8 + +# Batch size (number of parallel transcriptions). If you have a GPU with enough memory, +# increasing this value to e.g. 16 can speed up transcribing long audios up to 10x. +# Test what is the better value for your GPU before hitting OOM. +# This works just if you are using whisperx library instead of faster_whisper +batchSize = 1 + +######################################### +# RemoteAudioTranscriptTask options ######################################### # IP:PORT of the service/central node used by the RemoteWav2Vec2TranscriptTask implementation. -# wav2vec2Service = 127.0.0.1:11111 +# remoteServiceAddress = 127.0.0.1:11111 ######################################### # MicrosoftTranscriptTask options diff --git a/iped-app/resources/config/conf/CategoriesConfig.json b/iped-app/resources/config/conf/CategoriesConfig.json index e1874f42b8..962c9e640e 100644 --- a/iped-app/resources/config/conf/CategoriesConfig.json +++ b/iped-app/resources/config/conf/CategoriesConfig.json @@ -108,7 +108,7 @@ {"name": "Ares Galaxy", "mimes": ["application/x-ares-galaxy","application/x-ares-galaxy-entry"]}, {"name": "E-Mule", "mimes": ["application/x-emule", "application/x-emule-part-met", "application/x-emule-searches", "application/x-emule-preferences-ini", "application/x-emule-preferences-dat", "application/x-emule-known-met-entry", "application/x-emule-part-met-entry"]}, {"name": "Shareaza", "mimes": ["application/x-shareaza-searches-dat", "application/x-shareaza-library-dat", "application/x-shareaza-library-dat-entry", "application/x-shareaza-download"]}, - {"name": "Torrent", "mimes": ["application/x-bittorrent-resume-dat", "application/x-bittorrent"]}, + {"name": "Torrent", "mimes": ["application/x-bittorrent-resume-dat","application/x-bittorrent-settings-dat", "application/x-bittorrent"]}, {"name": "Other Peer-to-peer", "mimes": ["application/x-p2p"]} ]}, {"name": "Browser Artifacts", "categories":[ @@ -151,7 +151,16 @@ ]} ]}, {"name": "Extraction Summary", "mimes": ["application/x-ufed-html-summary"]}, - {"name": "Calls", "mimes": ["application/x-ufed-html-calls", "application/x-ufed-call", "call/x-threema-call", "call/x-whatsapp-call", "call/x-telegram-call", "call/x-discord-call", "application/x-ios-calllog-db", "application/x-ios8-calllog-db"]}, + {"name": "Calls", "categories":[ + {"name": "Discord Calls", "mimes":["call/x-discord-call"]}, + {"name": "Facebook Calls", "mimes":[]}, + {"name": "Phone Calls", "mimes":[]}, + {"name": "Signal Calls", "mimes":[]}, + {"name": "Telegram Calls", "mimes":["call/x-telegram-call"]}, + {"name": "Threema Calls", "mimes":["call/x-threema-call"]}, + {"name": "WhatsApp Calls", "mimes":["call/x-whatsapp-call"]}, + {"name": "Other Calls", "mimes":["application/x-ufed-html-calls", "application/x-ufed-call", "application/x-ios-calllog-db", "application/x-ios8-calllog-db"]} + ]}, {"name": "SMS Messages", "mimes": ["application/x-ufed-html-sms", "application/x-ufed-sms", "application/x-ios-sms-db"]}, {"name": "MMS Messages", "mimes": ["application/x-ufed-html-mms", "application/x-ufed-mms"]}, {"name": "Instant Messages", "mimes": ["message/x-chat-message", "message/x-threema-message", "application/x-ufed-instantmessage", "message/x-whatsapp-message", "message/x-skype-message", "message/x-skype-filetransfer", "message/x-telegram-message", "message/x-discord-message"]}, diff --git a/iped-app/resources/config/conf/CustomSignatures.xml b/iped-app/resources/config/conf/CustomSignatures.xml index a208f29ba6..33a65aceff 100644 --- a/iped-app/resources/config/conf/CustomSignatures.xml +++ b/iped-app/resources/config/conf/CustomSignatures.xml @@ -441,13 +441,25 @@ <_comment>BitTorrent Client Resume.dat file - + + + + + <_comment>BitTorrent Client Settings.dat file + + + + + + + + diff --git a/iped-app/resources/config/conf/MakePreviewConfig.txt b/iped-app/resources/config/conf/MakePreviewConfig.txt index 2f625a46e1..330684de12 100644 --- a/iped-app/resources/config/conf/MakePreviewConfig.txt +++ b/iped-app/resources/config/conf/MakePreviewConfig.txt @@ -7,7 +7,7 @@ supportedMimes = application/x-msaccess; application/x-lnk; application/x-firefox-savedsession supportedMimes = application/x-sqlite3; application/sqlite-skype; application/x-win10-timeline; application/x-gdrive-cloud-graph; application/x-gdrive-snapshot supportedMimes = application/x-whatsapp-db; application/x-whatsapp-db-f; application/x-whatsapp-chatstorage; application/x-whatsapp-chatstorage-f; application/x-threema-chatstorage; application/x-shareaza-searches-dat; application/x-msie-cache -supportedMimes = application/x-prefetch; text/x-vcard; application/x-bittorrent-resume-dat; application/x-bittorrent; application/x-emule-preferences-dat; application/vnd.android.package-archive +supportedMimes = application/x-prefetch; text/x-vcard; application/x-emule-preferences-dat; application/vnd.android.package-archive; application/x-bittorrent-settings-dat # List of mimetypes which parsers insert links to other case items into preview -supportedMimesWithLinks = application/x-emule; application/x-emule-part-met; application/x-ares-galaxy; application/x-shareaza-library-dat; application/x-shareaza-download \ No newline at end of file +supportedMimesWithLinks = application/x-emule; application/x-emule-part-met; application/x-ares-galaxy; application/x-shareaza-library-dat; application/x-shareaza-download; application/x-bittorrent-resume-dat; application/x-bittorrent \ No newline at end of file diff --git a/iped-app/resources/config/conf/OCRConfig.txt b/iped-app/resources/config/conf/OCRConfig.txt index 690c8d640b..6f4a714ca6 100644 --- a/iped-app/resources/config/conf/OCRConfig.txt +++ b/iped-app/resources/config/conf/OCRConfig.txt @@ -5,7 +5,7 @@ # You can use the parameter -ocr "bookmark_name" to restrict the OCR to a specific bookmark (just works when creating reports from cmd line). # Dictionary language to be used for OCR. You can specify multiple languages e.g. por+eng but you will pay an important processing cost. -# Languages supported: eng, por, ita, deu, spa +# Languages supported: eng, por, ita, deu, spa, fra OCRLanguage = por # Skip known files found in the hash lookup database. diff --git a/iped-app/resources/config/conf/ParserConfig.xml b/iped-app/resources/config/conf/ParserConfig.xml index 4e12c508f3..1546b791dd 100644 --- a/iped-app/resources/config/conf/ParserConfig.xml +++ b/iped-app/resources/config/conf/ParserConfig.xml @@ -351,6 +351,7 @@ + diff --git a/iped-app/resources/config/conf/metadataTypes.txt b/iped-app/resources/config/conf/metadataTypes.txt index 1d4dfe0401..3c1f666922 100644 --- a/iped-app/resources/config/conf/metadataTypes.txt +++ b/iped-app/resources/config/conf/metadataTypes.txt @@ -3392,6 +3392,8 @@ og:type = java.lang.String og:url = java.lang.String ontent-Type" = java.lang.String p2pHistoryEntries = java.lang.Integer +childPornHashHits = java.lang.Integer +p2p:torrentFilesFoundInCase = java.lang.Integer containerTrackId = java.lang.String parentTrackId = java.lang.String trackId = java.lang.String diff --git a/iped-app/resources/config/profiles/forensic/conf/ParserConfig.xml b/iped-app/resources/config/profiles/forensic/conf/ParserConfig.xml new file mode 100644 index 0000000000..584a4cbc23 --- /dev/null +++ b/iped-app/resources/config/profiles/forensic/conf/ParserConfig.xml @@ -0,0 +1,14 @@ + + + + + + + + + true + + + + + \ No newline at end of file diff --git a/iped-app/resources/config/profiles/pedo/conf/ParserConfig.xml b/iped-app/resources/config/profiles/pedo/conf/ParserConfig.xml new file mode 100644 index 0000000000..584a4cbc23 --- /dev/null +++ b/iped-app/resources/config/profiles/pedo/conf/ParserConfig.xml @@ -0,0 +1,14 @@ + + + + + + + + + true + + + + + \ No newline at end of file diff --git a/iped-app/resources/localization/iped-categories.properties b/iped-app/resources/localization/iped-categories.properties index 0be75b7742..e7a22ba5d6 100644 --- a/iped-app/resources/localization/iped-categories.properties +++ b/iped-app/resources/localization/iped-categories.properties @@ -92,6 +92,14 @@ Folders=Folders Scanned\ Documents=Scanned\ Documents Extraction\ Summary=Extraction\ Summary Calls=Calls +Discord\ Calls=Discord\ Calls +Facebook\ Calls=Facebook\ Calls +Other\ Calls=Other\ Calls +Phone\ Calls=Phone\ Calls +Signal\ Calls=Signal\ Calls +Telegram\ Calls=Telegram\ Calls +Threema\ Calls=Threema\ Calls +WhatsApp\ Calls=WhatsApp\ Calls SMS\ Messages=SMS\ Messages MMS\ Messages=MMS\ Messages Instant\ Messages=Instant\ Messages diff --git a/iped-app/resources/localization/iped-categories_de_DE.properties b/iped-app/resources/localization/iped-categories_de_DE.properties index 172c25754d..82dbf2b8aa 100644 --- a/iped-app/resources/localization/iped-categories_de_DE.properties +++ b/iped-app/resources/localization/iped-categories_de_DE.properties @@ -16,7 +16,7 @@ Other\ Documents=sonstige\ Dokumente Emails\ and\ Mailboxes=E-Mails\ und\ Postfächer Emails=E-Mails Mailboxes=Postfächer -Appointments=Appointments[TBT] +Appointments=Termine GDrive\ Synced\ Files=GDrive\ synchronisierte\ Dateien GDrive\ File\ Entries=GDrive\ Datei\ Einträge Databases=Datenbanken @@ -92,6 +92,14 @@ Folders=Verzeichnisse Scanned\ Documents=gescannte\ Dokumente Extraction\ Summary=Extraktions-Zusammenfassung Calls=Anrufe +Discord\ Calls=Discord\ Calls[TBT] +Facebook\ Calls=Facebook\ Calls[TBT] +Other\ Calls=Other\ Calls[TBT] +Phone\ Calls=Phone\ Calls[TBT] +Signal\ Calls=Signal\ Calls[TBT] +Telegram\ Calls=Telegram\ Calls[TBT] +Threema\ Calls=Threema\ Calls[TBT] +WhatsApp\ Calls=WhatsApp\ Calls[TBT] SMS\ Messages=SMS\ Nachrichten MMS\ Messages=MMS\ Nachrichten Instant\ Messages=Sofortnachrichten diff --git a/iped-app/resources/localization/iped-categories_es_AR.properties b/iped-app/resources/localization/iped-categories_es_AR.properties index 5dc341a725..a53f253c4d 100644 --- a/iped-app/resources/localization/iped-categories_es_AR.properties +++ b/iped-app/resources/localization/iped-categories_es_AR.properties @@ -92,6 +92,14 @@ Folders=Carpetas Scanned\ Documents=Documentos\ Escaneados Extraction\ Summary=Resumen\ Extracción Calls=Reg.\ Llamadas +Discord\ Calls=Discord\ Calls[TBT] +Facebook\ Calls=Facebook\ Calls[TBT] +Other\ Calls=Other\ Calls[TBT] +Phone\ Calls=Phone\ Calls[TBT] +Signal\ Calls=Signal\ Calls[TBT] +Telegram\ Calls=Telegram\ Calls[TBT] +Threema\ Calls=Threema\ Calls[TBT] +WhatsApp\ Calls=WhatsApp\ Calls[TBT] SMS\ Messages=Mensajes\ SMS MMS\ Messages=Mensajes\ MMS Instant\ Messages=Mensajes\ Instantáneos diff --git a/iped-app/resources/localization/iped-categories_fr_FR.properties b/iped-app/resources/localization/iped-categories_fr_FR.properties new file mode 100644 index 0000000000..1641d5f3a1 --- /dev/null +++ b/iped-app/resources/localization/iped-categories_fr_FR.properties @@ -0,0 +1,170 @@ +Categories=Catégories +Documents=Documents +RTF\ Documents=Documents\ RTF +PDF\ Documents=Documents\ PDF +HTML\ Documents=Documents\ HTML +XML\ Files=Fichiers\ XML +Georeferenced\ Files=Fichiers\ Géotagués +Text\ Documents=Documents\ Texte +Spreadsheets=Tableur +Presentations=Présentations +OLE\ files=Fichiers\ OLE +Links=Liens +Link\ files=Liens\ vers\ Fichiers +URL\ links= Liens\ vers\ URL +Other\ Documents=Autres\ Documents +Emails\ and\ Mailboxes=E-mails\ et\ Boîtes\ Mail +Emails=E-mails +Mailboxes=Boîtes\ Mails +Appointments=Entrées\ dans\ Calendrier +GDrive\ Synced\ Files=Fichiers\ de\ Synchronisation\ GDrive +GDrive\ File\ Entries=Enregistrements\ de\ Fichiers\ GDrive +Databases=Bases\ de\ Données +Compressed\ Archives=Fichiers\ Compressés +Contacts=Contacts +Chats=Chats +Others\ Chats=Autres\ Chats +Windows\ Artifacts=Artéfacts\ Windows +Event\ Files=Fichiers\ d'Évènements +Event\ Records=Enregistrements\ d'Évènements +Prefetch\ and\ Superfetch=Prefetch\ et\ Superfetch +User\ Activities=Activités\ Utilisateur +User\ Activities\ Entries=Entrées\ des\ Activités\ Utilisateur +Windows\ Registry=Registre\ de\ Windows +Main\ Registry\ Files=Fichiers\ Principaux\ du\ Registre +Other\ Registry\ Files=Autres\ Fichiers\ du\ Registre +Registry\ Full\ Reports=Rapports\ Complets\ du\ Registre +Registry\ Custom\ Reports=Rapports\ Personnalisés\ du\ Registre +Registry\ OS\ Info=Registre\ -\ Information\ sur\ l'OS +Registry\ Installed\ Apps=Registre\ -\ Applications\ Installées +Registry\ Network\ Info=Registre\ -\ Informations\ Réseau +Registry\ Storage\ Info=Registre\ -\ Informations\ Stockage +Registry\ Device\ Info=Registre\ -\ Informations\ Appareil +Registry\ Program\ Run=Registre\ -\ Liste\ des\ Programmes\ Exécutés +Registry\ Auto\ Run=Registre\ -\ Exécution \Automatique\ de\ Programmes +Registry\ Log\ Info=Registre\ -\ Informations\ sur\ les\ Logs +Registry\ Malware\ Info=Registre\ -\ Informations\ sur\ les\ Malware +Registry\ Web\ Info=Registre\ -\ Informations\ Internet +Registry\ User\ Info=Registre\ -\ Informations\ sur\ l'Utilisateur +Registry\ User\ Accounts=Registre\ -\ Comptes\ Utilisateur +Registry\ User\ Activity=Registre\ -\ Activités\ Utilisateur +Registry\ User\ Files=Registre\ -\ Fichiers\ Utilisateur +Registry\ User\ Network\ Activity=Registre\ -\ Activités\ Réseau\ de\ l'Utilisateur +Registry\ User\ Config=Registre\ -\ Configurations\ Utilisateur +Registry\ User\ Virtualization=Registre\ -\ Virtualisation\ Utilisateur +Registry\ User\ Communication=Registre\ -\ Communications\ Utilisateur +Windows\ Recycle=Corbeille\ de\ Windows +USN\ Journal=Journal\ USN +Programs\ and\ Libraries=Programmes\ et\ Librairies +Android\ Applications=Applications\ Android +Unallocated=Non\ Alloué +File\ Slacks=Fichiers\ Slacks +Multimedia=Multimédia +Audios=Audios +Images=Images +Temporary\ Internet\ Images=Images\ Temporaires\ Internet +Images\ in\ System\ Folders=Images\ dans\ Dossiers\ Système +Other\ Images=Autres\ Images +Videos=Vidéos +Video\ Thumbnails=Vignettes Vidéos +Plain\ Texts=Textes\ Bruts +Temporary\ Internet\ Texts=\Textes\ Temporaires\ Internet +Texts\ in\ System\ Folders=Textes\ dans\ Dossiers\ Système +Other\ Texts=Autres\ Textes +Other\ files=Autres\ Fichiers +Empty\ Files=Fichiers\ Vides +Peer-to-peer=Peer-to-peer +Ares\ Galaxy=Ares\ Galaxy +E-Mule=E-Mule +Shareaza=Shareaza +Torrent=Torrent +Other Peer-to-peer=Autres\ Peer-to-peer +Browser\ Artifacts=Artéfacts\ des\ Navigateurs +Internet\ History=Historique\ Internet +Internet\ History\ Entries=Entrées\ Historique\ Internet +Web\ Bookmarks=Favoris\ Internet +Image\ Disks=Image\ Disques +ISO\ disks=ISO\ Disques +Virtual\ disks=Disques\ Virtuel +Other\ disks=Autre\ Disques +Mozilla\ Firefox\ Saved\ Session=Sauvegarde\ de\ Sessions\ Mozilla\ Firefox +Folders=Dossiers +Scanned\ Documents=Documents\ Scannés +Extraction\ Summary=Résumé\ de\ l'Extraction +Calls=Appels +Discord\ Calls=Discord\ Calls[TBT] +Facebook\ Calls=Facebook\ Calls[TBT] +Other\ Calls=Other\ Calls[TBT] +Phone\ Calls=Phone\ Calls[TBT] +Signal\ Calls=Signal\ Calls[TBT] +Telegram\ Calls=Telegram\ Calls[TBT] +Threema\ Calls=Threema\ Calls[TBT] +WhatsApp\ Calls=WhatsApp\ Calls[TBT] +SMS\ Messages=SMS +MMS\ Messages=MMS +Instant\ Messages=Messages\ Instantanés +Bluetooth\ Devices=Appareils\ Bluetooth +SIM\ Data=Données\ SIM +Calendar=Calendrier +Logs=Logs +User\ Accounts=Comptes\ Utilisateur +Searches=Recherches +Notes=Notes +Wireless\ Networks=Réseaux\ Sans\ Fil +Notifications=Notifications +Locations=Géolocalisation +Cookies=Cookies +Configuration=Configuration +Passwords=Mot\ de\ passe +Autofill=Remplissage\ Automatique +Cell\ Towers=Antennes\ Relai +Power\ Events=Incidents\ Réseau\ Électrique +User\ Dictionaries=Dictionnaire\ Utilisateur +IP\ Connections=Connexions\ IP +Recordings=Enregistrements +Mobile\ Cards=Cartes\ Mobile +Applications\ Usage=Utilisation\ des\ Applications +Device\ Information=Informations\ Appareil +iPhone\ Backup=Sauvegardes\ d'iPhone +Torchat=Torchat +Tor=Tor +TorTCFragment=Extraits\ de\ Communications\ Tor +Cloud\ Drives=Cloud +Google\ Drive=Google\ Drive +Telegram=Telegram +Brazilian\ Software=Logiciel\ Brésilien +Internal\ Revenue\ of\ Brazil=Direction\ Générale\ des\ Finances\ Publiques\ du\ Brésil +Social\ Security\ and\ CAIXA\ Bank=Sécurité\ Sociale\ et\ Banque\ CAIXA +Tax\ Returns\ and\ Receipts\ IRPF=Déclarations\ de\ Revenus\ et\ Reçus\ IRPF +Tax\ Returns\ and\ Receipts\ DIRF=Déclarations\ de\ Revenus\ et\ Reçus\ DIRF +Tax\ Returns\ and\ Receipts\ DIPJ=Déclarations\ de\ Revenus\ et\ Reçus\ DIPJ +Tax\ Returns\ and\ Receipts\ CNPJ=Déclarations\ de\ Revenus\ et\ Reçus\ CNPJ +Tax\ Returns\ and\ Receipts\ DSIMPLES=Déclarations\ de\ Revenus\ et\ Reçus\ DSIMPLES +Tax\ Returns\ and\ Receipts\ DCTF=Déclarations\ de\ Revenus\ et\ Reçus\ DCTF +Tax\ Returns\ and\ Receipts\ PER\ DCOMP=Déclarations\ de\ Revenus\ et\ Reçus\ PER\ DCOMP +Other\ Tax\ Returns\ and\ Receipts=Autres\ Déclarations\ de\ Revenus\ et\ Reçus +PDF\ Bills\ of\ Exchange=Lettres\ de\ Change\ PDF +SPED\ Program\ Files=Fichiers\ Programme\ SPED +Receitanet\ Program\ Files=Fichiers\ Programme\ Receitanet +RFB\ Program\ Files=Fichiers\ Programme\ RFB +SEFIP_GEFIP\ Files=Fichiers\ Programme\ SEFIP_GEFIP +SEFIP\ Databases=Base\ de\ Données\ SEFIP +SEFIP\ Executables=Executables\ SEFIP +SEFIP\ Files=Fichiers\ SEFIP +Social\ Connectivity\ Program\ Executables=Executables\ Connectivité\ Sociale +Social\ Connectivity\ Program\ Files=Fichiers\ Connectivité\ Sociale +GRRF\ Files=Fichiers\ GRRF +Activities\ Sensor=Capteur\ d'Activités +Chat\ Activities=Activités\ dans\ Chats +Credit\ Cards=Cartes\ de\ Crédit +Device\ Connectivity=Connectivité\ de\ l'Appareil +Device\ Events=Évènements\ de\ l'Appareil +File\ Downloads=Téléchargements +File\ Uploads=Fichiers\ Uploadés +Fuzzy\ Data=Données\ Fuzzy +Financial\ Accounts=Comptes\ Financiers +Transfers\ of\ Funds=Transferts\ de\ Fonds +Journeys=Voyages +Networks\ Usage=Utilisation\ des\ Réseaux +Recognized\ Devices=Appareils\ Identifiés +Social\ Media\ Activities=Activités\ sur\ les\ Réseaux\ Sociaux diff --git a/iped-app/resources/localization/iped-categories_it_IT.properties b/iped-app/resources/localization/iped-categories_it_IT.properties index c57a81650f..9cad62d11b 100644 --- a/iped-app/resources/localization/iped-categories_it_IT.properties +++ b/iped-app/resources/localization/iped-categories_it_IT.properties @@ -92,6 +92,14 @@ Folders=Cartelle Scanned\ Documents=Documenti\ scansionati Extraction\ Summary=Sommario\ estrazione Calls=Chiamate +Discord\ Calls=Discord\ Calls[TBT] +Facebook\ Calls=Facebook\ Calls[TBT] +Other\ Calls=Other\ Calls[TBT] +Phone\ Calls=Phone\ Calls[TBT] +Signal\ Calls=Signal\ Calls[TBT] +Telegram\ Calls=Telegram\ Calls[TBT] +Threema\ Calls=Threema\ Calls[TBT] +WhatsApp\ Calls=WhatsApp\ Calls[TBT] SMS\ Messages=Messaggi\ SMS MMS\ Messages=Messaggi\ MMS Instant\ Messages=Messaggi\ istantanei diff --git a/iped-app/resources/localization/iped-categories_pt_BR.properties b/iped-app/resources/localization/iped-categories_pt_BR.properties index 6839af35ee..4907213556 100644 --- a/iped-app/resources/localization/iped-categories_pt_BR.properties +++ b/iped-app/resources/localization/iped-categories_pt_BR.properties @@ -37,7 +37,7 @@ Registry\ Full\ Reports=Relatórios\ Completos\ de\ Registro Registry\ Custom\ Reports=Relatórios\ Específicos\ de\ Registro Registry\ OS\ Info=Registro\ -\ Sistema\ Operacional Registry\ Installed\ Apps=Registro\ -\ Programas\ Instalados -Registry\ Network\ Info=Registro: Informações\ de\ Rede +Registry\ Network\ Info=Registro\ -\ Informações\ de\ Rede Registry\ Storage\ Info=Registro\ -\ Informações\ de\ Armazenamento Registry\ Device\ Info=Registro\ -\ Informações\ de\ Dispositivos Registry\ Program\ Run=Registro\ -\ Execução\ de\ Programas @@ -66,7 +66,7 @@ Temporary\ Internet\ Images=Imagens\ Temporárias\ de\ Internet Images\ in\ System\ Folders=Imagens\ em\ Pastas\ de\ Sistema Other\ Images=Outras\ Imagens Videos=Vídeos -Video\ Thumbnails=Miniaturas de Vídeos +Video\ Thumbnails=Miniaturas\ de\ Vídeos Plain\ Texts=Textos\ Simples Temporary\ Internet\ Texts=Textos\ Temporários\ de\ Internet Texts\ in\ System\ Folders=Textos\ em\ Pastas\ de\ Sistema @@ -92,6 +92,14 @@ Folders=Pastas Scanned\ Documents=Possíveis\ Digitalizações Extraction\ Summary=Resumo\ da\ Extração Calls=Chamadas +Discord\ Calls=Chamadas\ Discord +Facebook\ Calls=Chamadas\ Facebook +Other\ Calls=Outras\ Chamadas +Phone\ Calls=Chamadas\ Telefônicas +Signal\ Calls=Chamadas\ Signal +Telegram\ Calls=Chamadas\ Telegram +Threema\ Calls=Chamadas\ Threema +WhatsApp\ Calls=Chamadas\ WhatsApp SMS\ Messages=Mensagens\ SMS MMS\ Messages=Mensagens\ MMS Instant\ Messages=Mensagens\ Instantâneas @@ -154,7 +162,7 @@ Device\ Events=Eventos\ de\ Dispositivos File\ Downloads=Download\ de\ Arquivos File\ Uploads=Upload \ de\ Arquivos Fuzzy\ Data=Dados\ Indistintos -Financial\ Accounts=Contas Financeiras +Financial\ Accounts=Contas\ Financeiras Transfers\ of\ Funds=Transferências\ de\ Fundos Journeys=Jornadas Networks\ Usage=Uso\ de\ Redes diff --git a/iped-app/resources/localization/iped-desktop-messages_de_DE.properties b/iped-app/resources/localization/iped-desktop-messages_de_DE.properties index 5c0e3187ee..79a06db85b 100644 --- a/iped-app/resources/localization/iped-desktop-messages_de_DE.properties +++ b/iped-app/resources/localization/iped-desktop-messages_de_DE.properties @@ -103,7 +103,7 @@ ColumnsManager.LoadingCols=Lade verwendete Spalten... ColumnsManager.Filter=[Eingeben zum Filtern] ColumnsManager.WindowsEvt=Windows Ereignisse CopyProperties.Copying=Kopiere -CopyProperties.CSVDateFormat=MM/TT/JJJJ HH:mm:ss z +CopyProperties.CSVDateFormat=dd/MM/yyyy HH:mm:ss z CopyProperties.CSVDelimiter=; CopyProperties.from=\ von DuplicatesTableModel.Duplicates=\ Duplikate @@ -322,9 +322,9 @@ ReportDialog.TableHeader1=Lesezeichen ReportDialog.TableHeader2=nur Vorschau ReportDialog.Title=erstelle Bericht ParentTableModel.ParentCount=übergeordnetes Element -ResultTableModel.DateFormat=MM/dd/yyyy HH:mm:ss z +ResultTableModel.DateFormat=dd/MM/yyyy HH:mm:ss z ResultTableModel.Error=FEHLER -ResultTableModel.FATDateFormat=MM/dd/yyyy +ResultTableModel.FATDateFormat=dd/MM/yyyy ResultTableRowSorter.Sorting=Sortiere... RowComparator.SortCanceled=Sortierung abgebrochen. SearchStateFilter.BookmarksFile=Lesezeichen-Datei @@ -393,7 +393,7 @@ TimeLineGraph.unselectAllEventTypes=Unselect all event types(TBT) TimeLineGraph.checkEventItems=Check corresponding event type items(TBT) TimeLineGraph.uncheckEventItems=Uncheck corresponding event type items(TBT) IntervalDefinitionDialog.Title=Zeitlininechart festgelegte Bereiche -IntervalDefinitionDialog.dateFormat=MM/dd/yyyy +IntervalDefinitionDialog.dateFormat=dd/MM/yyyy IntervalDefinitionDialog.hourFormat=HH:mm:ss IntervalDefinitionDialog.Exit=Beenden App.appliedFilters=Filters (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_es_AR.properties b/iped-app/resources/localization/iped-desktop-messages_es_AR.properties index 7035a96eff..51ffee2b71 100644 --- a/iped-app/resources/localization/iped-desktop-messages_es_AR.properties +++ b/iped-app/resources/localization/iped-desktop-messages_es_AR.properties @@ -103,7 +103,7 @@ ColumnsManager.LoadingCols=Cargando columnas usadas... ColumnsManager.Filter=[Escribir para filtrar] ColumnsManager.WindowsEvt=Eventos de Windows CopyProperties.Copying=Copiando -CopyProperties.CSVDateFormat=MM/dd/aaaa HH:mm:ss z +CopyProperties.CSVDateFormat=dd/MM/yyyy HH:mm:ss z CopyProperties.CSVDelimiter=, CopyProperties.from=\ de DuplicatesTableModel.Duplicates=\ Duplicados @@ -322,9 +322,9 @@ ReportDialog.TableHeader1=Marcador ReportDialog.TableHeader2=Solo miniaturas ReportDialog.Title=Crear informe ParentTableModel.ParentCount=Elemento principal -ResultTableModel.DateFormat=MM/dd/aaaa HH:mm:ss z +ResultTableModel.DateFormat=dd/MM/yyyy HH:mm:ss z ResultTableModel.Error=ERROR -ResultTableModel.FATDateFormat=MM/dd/aaaa +ResultTableModel.FATDateFormat=dd/MM/yyyy ResultTableRowSorter.Sorting=Ordenando... RowComparator.SortCanceled=Clasificación cancelada. SearchStateFilter.BookmarksFile=Archivo de marcadores @@ -393,7 +393,7 @@ TimeLineGraph.unselectAllEventTypes=Unselect all event types(TBT) TimeLineGraph.checkEventItems=Check corresponding event type items(TBT) TimeLineGraph.uncheckEventItems=Uncheck corresponding event type items(TBT) IntervalDefinitionDialog.Title=Rangos definidos en el gráfico de tiempo -IntervalDefinitionDialog.dateFormat=MM/dd/yyyy +IntervalDefinitionDialog.dateFormat=dd/MM/yyyy IntervalDefinitionDialog.hourFormat=HH:mm:ss IntervalDefinitionDialog.Exit=Salir App.appliedFilters=Filters (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_fr_FR.properties b/iped-app/resources/localization/iped-desktop-messages_fr_FR.properties new file mode 100644 index 0000000000..7ed824bdc6 --- /dev/null +++ b/iped-app/resources/localization/iped-desktop-messages_fr_FR.properties @@ -0,0 +1,444 @@ +App.Case=Cas +App.Checked=[Éléments cochés] +App.ExportZip=Export en fichier ZIP +App.FilterTip=Filtres +App.ClearFilter=Supprimer le Filtre +App.ClearFilters=Supprimer les Filtres +App.FilterDuplicates=Filtre de la Liste des doublons +App.FilterDuplicatesTip=Filtre des doublons à partir du résultat +App.Gallery=Galerie +App.Help=Aide +App.Hits=Résultats positifs +App.Map=Carte +App.Links=Liens +App.Metadata=Métadonnées +App.NoFilter=[Non filtré] +App.Options=Options +App.RecursiveListing=Récursivité +App.Search=Recherche +App.SearchBoxTip=[Type ou choix de la recherche. Touche [TAB] pour autocomplétion] +App.SearchLabel=Recherche : +App.Table=Tableau +App.ToggleTimelineView=Basculer la ligne de temps en tableau +App.Update=Mise à jour +App.Wait=Attendre... +AppLazyInitializer.errorMsg.line1=Erreur d''ouverture du cas. Le traitement s''est-il terminé sans erreur ?\n +AppLazyInitializer.errorMsg.line2=Si oui, contacter le support et communiquer le journal d''évènements\n +AppLazyInitializer.errorMsg.line3=\nRésumé de erreur:\n +AppLazyInitializer.errorTitle=Erreur d''initialisation +AppListener.NoHits=Aucun résultat positif +AppListener.UncheckAll=Confirmez-vous vouloir décocher tous les éléments ? +AppListener.UncheckAll.Title=Confirmation +AppMain.NoCasesFile=Les fichiers du cas sont introuvables : +AppMain.warn.Title=Initialisation +BookmarksController.HistoryDelimiter=-----------------------Historique----------------------- +BookmarksController.LoadError=Erreur de chargement des favoris \! +BookmarksController.LoadError.Title=Erreur +BookmarksController.LoadSuccess=Chargement des favoris avec succès +BookmarksController.LoadSuccess.Title=Succès +BookmarksController.SaveError=Erreur de sauvegarde des favoris \! +BookmarksController.SaveError.Title=Erreur +BookmarksController.SaveSuccess=Sauvegarde des favoris avec succès +BookmarksController.SaveSuccess.Title=Succès +BookmarksManager.Add=Ajouter +BookmarksManager.Add.Tip=Ajouter des éléments au favori sélectionné +BookmarksManager.AddDuplicates=Ajouter les doublons (Hash) +BookmarksManager.AlertMultipleSelectedBookmarks=Selectionnez seulement un favori \! +BookmarksManager.AlertNoCheckedtems=Aucun élement coché \! +BookmarksManager.AlertNoHighlightedItems=Aucun élément surligné \! +BookmarksManager.AlertNoSelectedBookmarks=Aucun favori sélectionné \! +BookmarksManager.Checked=Éléments cochés +BookmarksManager.ConfirmDelete=Voulez-vous vraiment supprimer les favoris sélectionnés ? +BookmarksManager.ConfirmDelTitle=Confirmer +BookmarksManager.Dataset=Données : +BookmarksManager.Delete=Supprimer +BookmarksManager.Delete.Tip=Supprimer les favoris sélectionnés +BookmarksManager.Edit=Modifier +BookmarksManager.Edit.Color=Couleur +BookmarksManager.Edit.Name=Nom +BookmarksManager.Edit.Tip=Modifier la couleur et le nom du favori sélectionné +BookmarksManager.Edit.Title=Modifier favori +BookmarksManager.Highlighted=Surligner les éléments +BookmarksManager.KeyStrokeBookmark=Taper la touche (ou combinaison de touches) pour définir un racourci clavier [Créer].
Alt+touche maintenue appuyée [Effacer]. +BookmarksManager.KeyStrokeAlert1=Créer un raccourci pour sélectionner un favori. +BookmarksManager.KeyStrokeAlert2=Maintenir Alt pour effacer une favori. +BookmarksManager.KeyStrokeAlert3=Modifier le raccourci. +BookmarksManager.KeyStrokeAlert4=Maintenir la touche de raccourci pour une autre action. +BookmarksManager.New=Nouveau +BookmarksManager.New.Tip=Nouveau favori +BookmarksManager.NewBookmark.Tip=Saisissez le nom du favori +BookmarksManager.Remove=Supprimer +BookmarksManager.Remove.Tip=Supprimer le favori sélectionné +BookmarksManager.SearchingDuplicates=Recherche des doublons... +BookmarksManager.Title=Favoris +BookmarksManager.CommentsTooltip=Commentaires du favori +BookmarksManager.Update=Mise à jour +BookmarksManager.UpdateTooltip=Mettre à jour les commentaires +BookmarksManager.AlreadyExists=Nom du favori existe déjà \! +BookmarksTreeModel.NoBookmarks=[Aucun favori] +BookmarksTreeModel.RootName=Favoris +CategoryTreeModel.RootName=Catégories +ColumnsManager.Advanced=Avancées +ColumnsManager.All=Toutes +ColumnsManager.Audio=Audio +ColumnsManager.Basic=Basic +ColumnsManager.Common=Commun +ColumnsManager.Communication=Communication +ColumnsManager.HashDB=Base de données des Hashes +ColumnsManager.HTML=HTML +ColumnsManager.Image=Image +ColumnsManager.Language=Langue +ColumnsManager.NamedEntity=Nom des entités +ColumnsManager.Office=Bureau +ColumnsManager.Other=Autres +ColumnsManager.PDF=PDF +ColumnsManager.Regex=Regex +ColumnsManager.ShowCols=Afficher les Colonnes : +ColumnsManager.Title=Colonnes visibles +ColumnsManager.Video=Vidéo +ColumnsManager.PeerToPeer=PeerToPeer +ColumnsManager.UFED=UFED +ColumnsManager.AutoManageCols=Gérer les colonnes automatiquement (Plus lent) +ColumnsManager.LoadingCols=Chargement des colonnes utilisées... +ColumnsManager.Filter=[Type de filtre] +ColumnsManager.WindowsEvt=Évènements Windows +CopyProperties.Copying=Copier +CopyProperties.CSVDateFormat=dd/MM/yyyy HH:mm:ss z +CopyProperties.CSVDelimiter=; +CopyProperties.from=\ de +DuplicatesTableModel.Duplicates=\ Doublons +ExportFiles.Copying=Copier +ExportFiles.of=\ de +ExportFilesToZip.Copying=Copier +ExportFilesToZip.from=\ de +ExportFileTree.Copied=Copié +ExportFileTree.ExportError=Erreur d''exportation de fichiers. Vérifier les droits et l''espace disponible.\n +ExportFileTree.from=\ de +ExportIndexedTerms.Exported=Exportés +ExportIndexedTerms.ofWords=\ des mots. +ExportToZIP.DefaultName=FichiersExportés.zip +ExportToZIP.DefaultPath=/home/caine/Données_Exportés +ExportToZIP.FileAlreadyExistsMessageText=Le nom du fichier existe déjà. Voulez-vous le remplacer ? +ExportToZIP.FileAlreadyExistsMessageTitle=Le fichier existe déjà +FileProcessor.OpeningEvidence=Ouvrir le fichier d''analyse... +FilterManager.Del.Tip=Supprimer le filtre sélectionné +FilterManager.Delete=Supprimer +FilterManager.Expresion=Expression : +FilterManager.Expression.Tip=Règles du filtre +FilterManager.Filters=Filtres: +FilterManager.New=Nouveau +FilterManager.New.Tip=Nouveau filtre +FilterManager.NewName=Nom du nouveau filtre +FilterManager.Save=Enregistrer +FilterManager.Save.Tip=Enregistrer les modifications +FilterManager.Title=Filtres +Gallery.DecreaseThumbsSize=Reduire la taille des vignettes +Gallery.IncreaseThumbsSize=Augmenter la taille des vignettes +Gallery.GalleryBlurFilter=Ativer/désactiver : Floutage de la galerie (utiliser Ctrl+Q pour tout sélectionner) +Gallery.GalleryGrayFilter=Ativer/désactiver : Griser la gallerie (utiliser Ctrl+W pour tout sélectionner) +Gallery.ToggleVideoFrames=Ativer/désactiver : la configuration des vignettes vidéo (Complète / Reduite) +GraphAnalysis.GraphvizError=Test d''erreur de graphviz tool {0}. Est-il installé ? +GraphAnalysis.Expand=Développer +GraphAnalysis.ExpandConfiguration=Développer (Filtre) +GraphAnalysis.Expand.Links=Liens +GraphAnalysis.Expand.Entities=Entités +GraphAnalysis.Expand.MaxNodes=Développer les entités les plus liées jusqu''à +GraphAnalysis.FindConnectios=Trouver des connexions +GraphAnalysis.FindPaths=Trouver des chemins +GraphAnalysis.Remove=Supprimer +GraphAnalysis.ShowEvidence=Afficher les résultats +GraphAnalysis.SelectAll=Tout sélectionner +GraphAnalysis.Processing=En cours... +GraphAnalysis.Done=Terminé. +GraphAnalysis.Preparing=En cours de préparation... +GraphAnalysis.Ready=Prêt. +GraphAnalysis.ExportingImage=Création de l''image... +GraphAnalysis.Error=Une erreur s''est produite lors de l''opération. +GraphAnalysis.UndoAction=Annuler l''opération en cours +GraphAnalysis.RedoAction=Recommencer +GraphAnalysis.SaveImage=Enregistrer l''Image +GraphAnalysis.SearchEntities=Recherche les liens entre entités +GraphAnalysis.Search=Rechercher +GraphAnalysis.Add=Ajouter +GraphAnalysis.Cancel=Arrêter +GraphAnalysis.Export=Exporter +GraphAnalysis.Id=Id. +GraphAnalysis.Type=Type +GraphAnalysis.Quantity=Quantité +GraphAnalysis.Property=Propriété +GraphAnalysis.Value=Valeur +GraphAnalysis.FitToScreen=Adapter à l''écran +GraphAnalysis.ExportLinks=Exporter les liens +GraphAnalysis.Origin=Origine +GraphAnalysis.Destiny=Destination +GraphAnalysis.Distance=Distance +GraphAnalysis.FileExistsConfirmation=Le fichier {0} existe déjà. Continuer ? +GraphAnalysis.FileSaved=Le fichiers {0} a été enregistré avec succès. +GraphAnalysis.Results=Trouvés {0} résultats en {1}ms. +GraphAnalysis.AdvancedSearch=Recherche avancée +GraphAnalysis.AddToAnalysis=Ajouter à l''analyse +GraphAnalysis.Execute=Executer +GraphAnalysis.SearchLinks=Liens recherchés +GraphAnalysis.Links=Liens +GraphAnalysis.Datasources=Source des données +GraphAnalysis.LinksSearching=Liens recherchés... Trouvés {0}. +GraphAnalysis.CreateMultiGraph=Graphique non créé pour ce cas multiple. Souhaitez-vous le créer maintenant ? +GraphAnalysis.MultiGraphError=Impossible de créer le graphique du cas multiple, vérifier les logs ! +GraphAnalysis.MultiGraphOk=Graphique de cas multiple créé. +GraphAnalysis.InitialGraphMsg=Graphique prêt. Il présente uniquement les entités ayant le plus de contacts. +KeywordListImporter.BookmarkPrefix=Résultats de recherche pour : +KeywordListImporter.Msg.1=Importé(s) +KeywordListImporter.Msg.2= mots-clés avec des résultats sur\ +KeywordListImporter.SyntaxError=Erreur de syntaxe dans les expressions suivantes : +HashDialog.MD5Title=Valeur Hash MD5 du ZIP exporté +ImageSimilarity.ExternalError=Impossible d''ouvrir le fichier image sélectionné. +ImageSimilarity.ExternalTitle=Image exerne similaire +ImageSimilarity.FilterTipTitle=Filtre des images similaires +ImageSimilarity.FilterTipExternal=Image de référence +ImageSimilarity.FilterTipInternal=Image de référence +ImageSimilarity.Image=Image +ImageSimilarity.RemoveFilter=Suppression du filtre d''images identiques +FaceSimilarity.ExternalTitle=Visage similaire +FaceSimilarity.FilterTipTitle=Filtre de visage similaire +FaceSimilarity.FilterTipExternal=Visage de référence externe +FaceSimilarity.FilterTipInternal=Visage de référence +FaceSimilarity.RemoveFilter=Suppression du filtre de visage similaire +FaceSimilarity.Image=Visage +FaceSimilarity.MinScore=Définir la précision de ressemblance (1-100) +FaceSimilarity.LoadingFace=Chargement du visage... +FaceSimilarity.ExternalFaceNotFound=Pas de visage trouvé dans le fichier externe ! +MenuClass.AddToGraph=Ajouter à l''analyse de liens +MenuClass.ChangeGalleryColCount=Modifier le nombre de colonnes de la galerie +MenuClass.ChangeLayout=Changer la disposition Vertical/Horizontal +MenuClass.CheckHighlighted=Vérifier les éléments en surbrillance +MenuClass.CheckRecursivelyHighlighted=Vérifier les sous-éléments et éléments en surbrillance +MenuClass.ClearSearches=Supprimer l''historique des recherches +MenuClass.ColorTheme=Couleur du Thème +MenuClass.CopyViewerImage=Faire une capture d''écran de la visionneuse +MenuClass.ExportChecked=Exporter les éléments cochés +MenuClass.ExportCheckedToZip=Exporter les résultats cochés au format Zip +MenuClass.ExportHighlighted=Exporter les éléments surlignés +MenuClass.ExportIndexedWords=Exporter la liste des expressions indexées +MenuClass.ExportItens=Exporter les éléments... +MenuClass.ExportProps.Checked=Exporter les propriétés des éléments cochés +MenuClass.ExportProps.Highlighed=Exporter les propriétés des éléments surlignés +MenuClass.ExportTree=Exporter l''arborescence des fichiers +MenuClass.ExportTree.Checked=Exporter l''arborescence des fichiers (éléments sélectionnés) +MenuClass.ExportTreeToZip.Checked=Exporter l''arborescence des fichiers au format ZIP (éléments sélectionnés) +MenuClass.FindSimilarDocs=Recherche des documents similaires +MenuClass.FindSimilarImages=Recherche des images similaires +MenuClass.FindSimilarImages.Current=Elément en surbrillance +MenuClass.FindSimilarImages.External=Image externe... +MenuClass.FindSimilarFaces=Recherche des images similaires +MenuClass.FindSimilarFaces.Current=Elément en surbrillance +MenuClass.FindSimilarFaces.External=Visage externe... +MenuClass.GenerateReport=Créer un rapport indexé +MenuClass.GoToParent=Retour à la racine de l''arborescence de fichier +MenuClass.GoToChat=Retour à la racine du chat +MenuClass.ImportKeywords=Importer une liste de mots-clés +MenuClass.LayoutAppearance=Disposition / Apparence +MenuClass.LoadBookmarks=Chargement des favoris +MenuClass.ManageBookmarks=Gestion des favoris +MenuClass.ManageColumns=Gestion des colonnes +MenuClass.ManageVisibleCols=Gestion des colonnes visibles +MenuClass.PinFirstCols=Epingler les premières colonnes... +MenuClass.LoadLastColLayout=Charger la dernière mise en page enregistrée +MenuClass.SaveColLayout=Sauvegarder la mise en forme des colonnes +MenuClass.ResetColLayout=Réinitialiser la mise en forme des colonnes +MenuClass.ManageFilters=Gestion des Filtres +MenuClass.OpenViewFile = Ouvrir un aperçu/rapport externe +MenuClass.LoadPanelsLayout=Charger la dernière mise en page sauvegardée +MenuClass.SavePanelsLayout=Sauvegarder la mise en forme +MenuClass.ResetLayout=Restaurer la mise en forme par défaut +MenuClass.SaveBookmarks=Sauvegarder les favoris +MenuClass.UiZoom=Réglage du zoom +MenuClass.IconSize=Taille des icones +MenuClass.UnCheckHighlighted=Décocher les éléments en surbrillance +MenuClass.UnCheckRecursivelyHighlighted=Décocher les éléments et sous-éléments en surbrillance +MenuListener.ChatNotFound=Origine du chat non trouvé +MenuListener.Cols=Colonnes : +MenuListener.ExportTree.Warn=Selectionner 01 (un) nœud de l''arborescence comme référence d''export \! +MenuListener.Gallery=Galerie +MenuListener.PinFirstCols=Epingler les premières colonnes +MenuListener.SimilarityLabel=Taux de similitude (0 à 100) +MenuListener.CheckAddKeywordsAsSingleBookmark=Importer tous les resultat des mots-clés dans un favori unique +MenuListener.CheckAddKeywordsAsMultipleBookmarks=Importer les résutlatas de chaque mot-clé dans un favori séparé +MenuListener.TableAndOthers=Tableau et autres +MenuListener.UiScaleDialog=Définir l''échelle de l''interface.\nUtilisez une valeur à virgule flottante (par exemple 1.5) ou ''{}'' pour ajuster automatiquement le zoom.\nVous devez redémarrer l''application pour que cette modification prenne effet. +MetadataPanel.AlphaNumeric=Alphanumérique +MetadataPanel.Clear=Supprimer le filtre de métadonnées +MetadataPanel.Group=Groupe : +MetadataPanel.Hits=Résultats +MetadataPanel.Linear=Linéaire +MetadataPanel.Log=Logarithmique +MetadataPanel.NoRanges=Aucune plage +MetadataPanel.Property=Propriété : +MetadataPanel.RangeSeparator=de +MetadataPanel.Scale=Echelle : +MetadataPanel.Sort=Trier : +MetadataPanel.Update=Mise à jour +MetadataPanel.Filter=Filtre : +MetadataPanel.FilterProps=Propriétés +MetadataPanel.FilterValues=Valeurs +MetadataPanel.CopyClipboard=Copier dans le presse papier +MetadataPanel.UpdateWarn=[Cliquer pour mettre à jour] +NoJavaFX.Error=Cette application a besoin que JavaFX soit installé ! +ProcessingNotFinished.title=Le processus n''est pas terminé +ProcessingNotFinished.message=Le traitement ne s''est pas terminé correctement. De nombreux éléments du dossier peuvent être manquants, y compris ceux alloués.\nEssayez de le reprendre avec l''option --continuer. +ProcessingNotFinished.cases=\ Les cas suivants sont concernés : +ProcessingNotFinished.evidence=Preuve affectée : +ReferencesTab.Title=Référencement +ReferencedByTab.Title=Référencé par +ResultTableModel.bookmark=favori +ResultTableModel.score=score +ReportDialog.AddToReport=Ajouter à un rapport existant +ReportDialog.AppendWarning=Le rapport HTML existant n''est pas encore mis à jour, le cas est seulement indexé ! +ReportDialog.CaseInfo=Compléter les informations du cas (numéro du cas, nom de l''analyste, numéro du rapport...) +ReportDialog.ChooseLabel=Sélectionner les favoris à insérer dans le rapport : +ReportDialog.Create=Création +ReportDialog.ErrorTitle=Erreur +ReportDialog.Evidences=Description des preuves +ReportDialog.Examiner=Analyste +ReportDialog.FillInfo=Informations sur le cas +ReportDialog.Investigation=Numéro du cas +ReportDialog.KeywordsFile=Fichier de mots-clés (optionnel): +ReportDialog.LoadButton=Chargement +ReportDialog.LoadInfo=Charger les informations du cas à partir du fichier .json ou .asap : +ReportDialog.NoAttachments=Ne pas exporter automatiquement les pièces jointes des e-mails +ReportDialog.noLinkedItems=Ne pas exporter automatiquement les pièces jointes du chat +ReportDialog.Output=Dossier d''enregistrement : +ReportDialog.OutputRequired=Dossier d''enregistrement requis \! +ReportDialog.Record=Numéro de dossier +ReportDialog.RecordDate=Date du dossier +ReportDialog.ReportDate=Date du rapport +ReportDialog.ReportError=Erreur de création du rapport, vérifier le log d''erreurs \! +ReportDialog.ReportFinished=Rapport créé \! +ReportDialog.ReportNum=Numéro de rapport +ReportDialog.ReportTitle=Titre du rapport +ReportDialog.Request=Formulaire de demande +ReportDialog.RequestDate=Date de la demande +ReportDialog.Requester=Requérant +ReportDialog.TableHeader1=Favori +ReportDialog.TableHeader2=ThumbsOnly +ReportDialog.Title=Créer un rapport +ParentTableModel.ParentCount=Dossier source +ResultTableModel.DateFormat=dd/MM/yyyy HH:mm:ss z +ResultTableModel.Error=ERREUR +ResultTableModel.FATDateFormat=dd/MM/yyyy +ResultTableRowSorter.Sorting=Tri... +RowComparator.SortCanceled=Tri annulé. +SearchStateFilter.BookmarksFile=Fichier des favoris +SubitemTableModel.Subitens=\ Pièces jointes/sous éléments +TextParserListener.Found=Trouvés +TextParserListener.hits=\ résultats +TreeViewModel.RootName=Analyse +UISearcher.Canceled=Arrêter la recherche \! +UISearcher.Error.Msg=Erreur de syntaxe dans la requête : +UISearcher.Error.Title=Erreur +UnsupportedIcon.Unavailable=Vignette non supportée +ViewerController.OfficeViewerUnSupported=La visionneuse Office n''est plus prise en charge dans Java 32 bits ! Veuillez installer un Java 64 bits. +ViewerController.FixViewer=Correction de la visionneuse +ViewerController.NextHit=Résultat suivant +ViewerController.PrevHit=Résultat précédent +ViewerController.ShowToolBar=Afficher/Masquer la barre d''outils +HexSearcherImpl.hits=résultats +HexSearcherImpl.hit=résultat +HexSearcherImpl.of=de +HexSearcherImpl.timeLeft=Temps restant +HexSearcherImpl.noHits=Aucun résultat trouvé +Theme.Dark=Mode sombre +Theme.Light=Mode clair (default) +TimeLineGraph.highlightEventItensOnPeriod=Mettre en surbrillance les éléments d''évènement dans la période +TimeLineGraph.highlightItensOnPeriod=Mettre en surbrillance les éléments dans la période +TimeLineGraph.checkEventItensOnPeriod=Cocher les éléments de l''évènement dans la période +TimeLineGraph.checkItensOnPeriod=Vérifier les éléments dans la plage +TimeLineGraph.filterBefore=Filtrer avant +TimeLineGraph.filterAfter=Filtrer après +TimeLineGraph.selectBefore=Mettre en surbrillance avant +TimeLineGraph.selectAfter=Mettre en surbrillance après +TimeLineGraph.filterAllDefinedIntervals=Filtrer les intervalles définies +TimeLineGraph.selectItensOnThisInterval=Mettre en surbrillance les éléments de l''intervalle sélectionné +TimeLineGraph.deleteInterval=Supprimer l''intervalle +TimeLineGraph.continueIntervalSelection=Continuer à sélectionner des intervalles... +TimeLineGraph.hideSeriesOnChart=Masquer sur le graphique +TimeLineGraph.filterEventFromResultSet=Supprimer du jeu de résultats +TimeLineGraph.unfilterEventFromResultSet=Réinclure dans le jeu de résultats +TimeLineGraph.Year=Année +TimeLineGraph.Quarter=Trimestre +TimeLineGraph.Month=Mois +TimeLineGraph.Week=Semaine +TimeLineGraph.Day=Jour +TimeLineGraph.Hour=Heure +TimeLineGraph.Minute=Minute +TimeLineGraph.Second=Seconde +TimeLineGraph.Millisecond=Milliseconde +TimeLineGraph.donotBreak=Ne pas diviser le graphique +TimeLineGraph.breakByBookmark=Diviser le graphique par favoris +TimeLineGraph.breakByMetadata=Diviser le graphique par métadonnées +TimeLineGraph.breakByCategory=Diviser le graphique par categories +TimeLineGraph.checkingItemsProgressLabel=Selection des éléments du diagramme temporel... +TimeLineGraph.highlightingItemsProgressLabel=Mise en surbrillance les éléments du diagramme temporel... +TimeLineGraph.PeriodGranularity=Échelle de temps +TimeLineGraph.Timezone=Fuseau horaire +TimeLineGraph.applyDefinedFilters=Appliquer les filtres définis +TimeLineGraph.clearDefinedFilters=Effacer les filtres définis +TimeLineGraph.openIntervalsDialogMenu=Ouvrir la boîte de dialogue de définition de plage horaire... +TimeLineGraph.visibleRangeToGreat=La plage visible est trop grande pour l''échelle actuelle %s.\n Souhaitez-vous continuer et zoomer en centrant sur la date du milieu %s ? +TimeLineGraph.visibleZoominForGranularity=Zoom avant maximum atteint pour l''échelle %s.\n Souhaitez-vous changer l''échelle en %s et continuer à zoomer ? +TimeLineGraph.visibleZoomoutForGranularity=Le zoom arrière maximum atteint pour l''échelle %s.\n Souhaitez-vous changer l''échelle en %s et continuer le zoom arrière ? +TimeLineGraph.syncTableSelectionInChartView=Afficher la table en surbrillance dans le diagramme temporel +TimeLineGraph.resetZoom=Réinitialiser le zoom +TimeLineGraph.selectAllEventTypes=Sélectionner tous les évènements +TimeLineGraph.unselectAllEventTypes=Désélectionner tous les évènements +TimeLineGraph.checkEventItems=Cocher les éléments des évènements sélectionnés +TimeLineGraph.uncheckEventItems=Décocher les éléments des évènements sélectionnés +IntervalDefinitionDialog.Title=Plages définies dans la ligne de temps +IntervalDefinitionDialog.dateFormat=dd/MM/yyyy +IntervalDefinitionDialog.hourFormat=HH:mm:ss +IntervalDefinitionDialog.Exit=Sortie +App.appliedFilters=Filtres +iped.app.graph.FilterSelectedEdges.filtererName=Filtre des Arêtes du Graphe +iped.app.timelinegraph.IpedChartsPanel.filtererName=Filte du Graphe de la Timeline +iped.app.ui.App.DuplicatesFilterer.filtererName=Filtre des Doublons +iped.app.ui.App.SimilarDocumentFilterer.filtererName=Filtre des Documents Similaires +iped.app.ui.App.SimilarFacesSearchFilterer.filtererName=Filtre des Visages Similaires +iped.app.ui.App.SimilarImagesQueryFilterer.filtererName=Filtre des Images Similaires +iped.app.ui.App.SearchFilterer.filtererName=Filtre Mots-Clés +iped.app.ui.BookmarksTreeListener.filtererName=Filtre Favoris +iped.app.ui.CategoryTreeListener.filtererName=Filtre de Catégories +iped.app.ui.ComboFilterer.filtererName=Filtre Prédéfini +iped.app.ui.ComboFilterer.tooltip=Selectionner un filtre Prédéfini +iped.app.ui.MetadataPanel.filtererName=Filtrer Metadata +iped.app.ui.TableHeaderFilterManager.filtererName=Filtre En-tête du Tableau +iped.app.ui.TimelineListener.filtererName=Filtre Timeline +iped.app.ui.TreeListener.filtererName=Filtre de l''arborescence des preuves +iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Filtre Combiné +iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Appliquer le Filtre Combiné +FilterValue.Duplicates=Résultat du Filtre des Doublons +FilterValue.SimilarDocument=Filtre des Doublons +FilterValue.SimilarFace=Visages Similaires +FilterValue.SimilarImage=Images Similaires +FilterValue.TimelineView=Résultat de la Vue en Timeline +Operand.AND=ET +Operand.OR=OU +OperandMenu.invertFilter=Inverser le filtre +OperandMenu.changeOperand=Changer pour +OperandMenu.addAnd=Ajouter le noeud ET +OperandMenu.addOr=Ajouter le noeud OU +OperandMenu.removeNode=Supprimer le noeud +FiltererMenu.clearFilters=Effacer les filtre +FiltererMenu.goToItem=Aller à l''élément référencé +FiltererMenu.ItemNotInRS=L''élément référencé n''existe pas dans les résultats actuels. +FiltersPanel.addQueryFilterError=Cela n''a pas été possible d''ajouter le filtre à cause d''une erreur interne. +FieldValuePopupMenu.NonEmpty=Pas vide +FieldValuePopupMenu.Empty=Vide +FieldValuePopupMenu.Contains=Contient ... +FieldValuePopupMenu.NotContains=Ne contient pas ... +FieldValuePopupMenu.After=Après ... +FieldValuePopupMenu.Before=Avant ... +FieldValuePopupMenu.GreaterThan=Plus que... +FieldValuePopupMenu.LessThan=Moins que... +FieldValuePopupMenu.Equals=Égal à... +FieldValuePopupMenu.StartsWith=Commençant par... +FieldValuePopupMenu.Clear=Efacer +FieldValuePopupMenu.Filter=Filtre diff --git a/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties b/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties index 28561328a3..6de2ea764f 100644 --- a/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties +++ b/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties @@ -277,25 +277,20 @@ MetadataPanel.RangeSeparator=a MetadataPanel.Scale=Escala: MetadataPanel.Sort=Ordenação: MetadataPanel.Update=Atualizar -MetadataPanel.UpdateWarn=[Clique em Atualizar] MetadataPanel.Filter=Filtrar: MetadataPanel.FilterProps=Propriedades MetadataPanel.FilterValues=Valores MetadataPanel.CopyClipboard=Copiar para a área transf. +MetadataPanel.UpdateWarn=[Clique em Atualizar] NoJavaFX.Error=Esta aplicação precisa que o JavaFX esteja instalado! ProcessingNotFinished.title=Processamento não finalizado ProcessingNotFinished.message=Processamento não finalizou com sucesso. Muitos itens podem estar ausentes, incluindo alocados.\nTente retomá-lo com a opção --continue. ProcessingNotFinished.cases=\ Os seguintes casos são afetados: ProcessingNotFinished.evidence=Evidência afetada: -ResultTableModel.bookmark=marcador -ResultTableModel.score=score -ParentTableModel.ParentCount=Item Pai ReferencesTab.Title=Referências ReferencedByTab.Title=Referenciado por -ResultTableModel.DateFormat=dd/MM/yyyy HH:mm:ss z -ResultTableModel.Error=ERRO -ResultTableModel.FATDateFormat=dd/MM/yyyy -ResultTableRowSorter.Sorting=Ordenando... +ResultTableModel.bookmark=marcador +ResultTableModel.score=score ReportDialog.AddToReport=Adicionar ao relatório já existente ReportDialog.AppendWarning=O relatório html existente ainda não é atualizado, apenas o caso indexado! ReportDialog.CaseInfo=Preencher informações do caso (investigação, examinador, laudo...) @@ -326,6 +321,11 @@ ReportDialog.Requester=Requisitante ReportDialog.TableHeader1=Marcador ReportDialog.TableHeader2=ThumbsOnly ReportDialog.Title=Gerar Relatório +ParentTableModel.ParentCount=Item Pai +ResultTableModel.DateFormat=dd/MM/yyyy HH:mm:ss z +ResultTableModel.Error=ERRO +ResultTableModel.FATDateFormat=dd/MM/yyyy +ResultTableRowSorter.Sorting=Ordenando... RowComparator.SortCanceled=Ordenação cancelada. SearchStateFilter.BookmarksFile=Arquivo de Marcadores SubitemTableModel.Subitens=\ Anexos/Subitens diff --git a/iped-app/resources/localization/iped-engine-messages_de_DE.properties b/iped-app/resources/localization/iped-engine-messages_de_DE.properties index 5706690362..6d27eda5a3 100644 --- a/iped-app/resources/localization/iped-engine-messages_de_DE.properties +++ b/iped-app/resources/localization/iped-engine-messages_de_DE.properties @@ -12,7 +12,7 @@ HTMLReportTask.Bookmark=Lesezeichen HTMLReportTask.Bookmarks=Lesezeichen HTMLReportTask.Categories=Kategorien HTMLReportTask.Category=Kategorie -HTMLReportTask.Dateformat=MM/dd/yyyy HH:mm:ss +HTMLReportTask.Dateformat=dd/MM/yyyy HH:mm:ss HTMLReportTask.FileCount=Anzahl Dateien HTMLReportTask.FirstPage=Erste Seite HTMLReportTask.GalleryLink=Bilder-Galerie diff --git a/iped-app/resources/localization/iped-engine-messages_es_AR.properties b/iped-app/resources/localization/iped-engine-messages_es_AR.properties index bfb7d783b9..1b71b6b7f6 100644 --- a/iped-app/resources/localization/iped-engine-messages_es_AR.properties +++ b/iped-app/resources/localization/iped-engine-messages_es_AR.properties @@ -12,7 +12,7 @@ HTMLReportTask.Bookmark=Marcador HTMLReportTask.Bookmarks=Marcadores HTMLReportTask.Categories=Categorías HTMLReportTask.Category=Categoría -HTMLReportTask.Dateformat=MM/dd/aaaa HH:mm:ss +HTMLReportTask.Dateformat=dd/MM/yyyy HH:mm:ss HTMLReportTask.FileCount=Recuento de archivos HTMLReportTask.FirstPage=Primera página HTMLReportTask.GalleryLink=Galería de imágenes diff --git a/iped-app/resources/localization/iped-engine-messages_fr_FR.properties b/iped-app/resources/localization/iped-engine-messages_fr_FR.properties new file mode 100644 index 0000000000..901b91c370 --- /dev/null +++ b/iped-app/resources/localization/iped-engine-messages_fr_FR.properties @@ -0,0 +1,125 @@ +ExportCSVTask.CsvColNames="Nom","Lien","Taille","Extension","Favori","Catégorie","MD5","SHA1","Supprimé","Récupéré","Accès","Modifié","Créé","Emplacement","TrackId"\r\n +ExportCSVTask.CsvSeparator=, +ExportCSVTask.CsvName=Liste de fichiers.csv +ExportCSVTask.LinkFunction=Lien hyper texte +ExportCSVTask.LinkName=Ouvrir +ExportFileTask.DeletingData1=Suppression des données supprimées de FS... +ExportFileTask.DeletingData2=Suppression des données supprimées des supports... +ExportFileTask.DeletedData1=Données supprimées de FS : {} +ExportFileTask.DeletedData2=Données supprimées des supports: {} +ExportFileTask.ExportFolder=Exportés/Fichiers +HTMLReportTask.Bookmark=Favori +HTMLReportTask.Bookmarks=Favoris +HTMLReportTask.Categories=Catégories +HTMLReportTask.Category=Catéorie +HTMLReportTask.Dateformat=dd/MM/yyyy HH:mm:ss +HTMLReportTask.FileCount=Nombre de fichier +HTMLReportTask.FirstPage=Première page +HTMLReportTask.GalleryLink=Galerie d'images +HTMLReportTask.GalleryTitle=Vignette +HTMLReportTask.LastPage=Dernière page +HTMLReportTask.MakingHtmlReport=Création d'un rapport HTML... +HTMLReportTask.NextPage=Page suivante +HTMLReportTask.No=Non +HTMLReportTask.NoBookmarks=[Pas de favori] +HTMLReportTask.of=\ de\ +HTMLReportTask.Page=Page +HTMLReportTask.PreviewReport=Aper¸u du rapport +HTMLReportTask.PrevPage=Aper¸u de la page +HTMLReportTask.ReportFileName=rapport.htm +HTMLReportTask.ReportSubFolder=rapport +HTMLReportTask.VideoThumbs=Vignette vidéo +HTMLReportTask.Yes=Oui +Main.Finished=Terminé +IPEDSource.ImageNotFound=Image Non trouvée :\ +IPEDSource.ImgFragNotFound=Morceau d'image non trouvé :\ +ItemProducer.Adding=Ajouter ' +JavaVersion.Error=Version de java non supportée. Mettre à jour pour la version {}. +JavaVersion.Warn=Version de Java {} non testée, des erreurs inattendues peuvent se produire ! +JavaVersion.Bug=Une version problématique de Java {1} a été detectée ! Installer la dernière version de Java {2} sinon le programme paut se fermer sans prévenir. +JavaVersion.Arch=Vous utilisez une version 32 bits de Java, certaines fonctionnalités peuvent ne pas fonctionner correctement. Merci de mettre à jour vers une version 64 bits ! +Manager.Adding=Ajouter " +Manager.ClosingIndex=Clotûre de l'Index... +Manager.CopyingIndex=Copie de l'Index de... +Manager.OpeningIndex=Ouverture de l'Index... +Manager.DeletingTreeNodes=Supprimer les noeuds vides de l'arborescence +Manager.FilteringKeywords=Filtrer les mots clés... +Manager.Optimizing=Optimisation de l'index... +Manager.CommitStarted=Commencer la validation... +Manager.CommitFinished=Validation terminée. +P2PBookmarker.P2PBookmarkPrefix=Probablement partagé avec\ +ProgressConsole.files=\ fichiers +ProgressConsole.FinishIn=\ Terminé en\ +ProgressConsole.Found=Trouvés\ +ProgressConsole.Processing=En cours de traitement\ +ProgressConsole.Starting=Début... +ProgressFrame.ActiveProcessed=Éléments actifs traités +ProgressFrame.AlreadyOpen=L'application d'analyse est déjà ouverte \! +ProgressFrame.Carved=Eléments récupérés +ProgressFrame.CarvedDiscarded=Eléments récupérés exclus +ProgressFrame.Continue=Continuer +ProgressFrame.CurrentItems=Éléments en cours de traitement +ProgressFrame.CurrentSpeed=Vitesse actuelle +ProgressFrame.Environment=Environnement +ProgressFrame.EstimatedEnd=Temps estimé +ProgressFrame.Exported=Éléments exportés +ProgressFrame.FinishIn=\ - Terminé en\ +ProgressFrame.Found=Trouvée\ +ProgressFrame.FreeMemory=Mémoire libre +ProgressFrame.Ignored=Eléments ignorés +ProgressFrame.IncompleteProcessing=De nombreux éléments du dossier peuvent être indisponible avant la fin du traitement \! +ProgressFrame.items=\ Éléments +ProgressFrame.ItemsFound=Éléments trouvés +ProgressFrame.ItemsProcessed=Éléments traités +ProgressFrame.JavaVersion=Version de Java +ProgressFrame.MaxMemory=Mémoire Maximale +ProgressFrame.MeanSpeed=Vitesse moyenne +ProgressFrame.OpenApp=Prévisualiser le cas +ProgressFrame.OutputFree=Espace libre +ProgressFrame.OutputTempFree=Espace/Temp libre +ProgressFrame.OutputTempVolume=Volume de sortie/Temp +ProgressFrame.OutputVolume=Volume de sortie +ProgressFrame.ParserTimes=Durées d'analyse +ProgressFrame.ParsingErrors=Erreurs d'analyse +ProgressFrame.Pause=Pause +ProgressFrame.Paused=[En pause] +ProgressFrame.Pausing=[Mise en pause...] +ProgressFrame.PhysicalMemory=Mémoire physique +ProgressFrame.Processing=Traitement en cours\ +ProgressFrame.ProcessingTime=Durée du traitement +ProgressFrame.ReadErrors=Erreurs de lecture +ProgressFrame.Starting=Début... +ProgressFrame.Statistics=Statistiques +ProgressFrame.SubitemsProcessed=Sous éléments traités +ProgressFrame.TaskTimes=Durées par traitement +ProgressFrame.TempFree=Espace Temp Libre +ProgressFrame.TempVolume=Volume Temp +ProgressFrame.Timeouts=Temps dépassé +ProgressFrame.TotalMemory=Mémoire totale +ProgressFrame.VolumeFound=Volume trouvé +ProgressFrame.VolumeProcessed=Volume traité +ProgressFrame.WaitingItem=En attente... +RegexTask.SeparatorNotFound.1=Séparateur '=' non trouvé dans\ +RegexTask.SeparatorNotFound.2=\ ligne :\ +ReportInfo.EvidencePrefix=Extraction\ +SleuthkitReader.Creating=Créer\ +SleuthkitReader.WaitDecode=Décodage de l'image en cours\ +Statistics.LowMemory.Msg=Mémoire insuffisante : moins de {}MB par thread de traitement.\n Cela peut entrainer des lenteurs ou des erreurs pour l'analyse de fichiers complexes.\n Utiliser une JVM x64 (de préférence), \n augmenter la mémoire JVM avec l'option java -Xmx\n ou diminuez-le 'numthreads' dans le fichier LocalConfig.txt. +Statistics.LowMemory.Title=Alerte/Mémoire +UfedXmlReader.Attachments=Pièces jointes +UfedXmlReader.Bcc=Bcc +UfedXmlReader.Cc=Cc +UfedXmlReader.Date=Date +UfedXmlReader.From=De +UfedXmlReader.Subject=Sujet +UfedXmlReader.To=À +UfedXmlReader.LowConfidence=\ [confiance faible] +UfedXmlReader.DeviceInfo=Information sur le support +UfedXmlReader.Extraction=Extraction +Worker.Starting=Début\ +GraphAnalysis.LinksCalls=Appels +GraphAnalysis.LinksContacts=Contacts +GraphAnalysis.LinksEmails=E-mails +GraphAnalysis.LinksInstantMessages=Messages instantannés +GraphAnalysis.LinksWireless=Réseaux sans fils +GraphAnalysis.LinksDocuments=Documents diff --git a/iped-app/resources/localization/iped-filters_fr_FR.properties b/iped-app/resources/localization/iped-filters_fr_FR.properties new file mode 100644 index 0000000000..531b26ab1d --- /dev/null +++ b/iped-app/resources/localization/iped-filters_fr_FR.properties @@ -0,0 +1,18 @@ +Filter\ Known\ Hashes=Filtre\ Hashs\ Connus +Hash\ Alert=Alerte\ Hash +Hash\ Alert\ (Child\ Porn)=Détection\ Hash\ (Pédopornographie) +PhotoDNA\ Alert\ (Child\ Porn)=Détection\ PhotoDNA\ (Pédopornographie) +Encrypted\ Files=Fichiers\ Chiffrés +Possibly\ encrypted\ (entropy)=Probablement\ Chiffré\ (entropie) +Parsing\ Error=Erreur\ de\ Parsing +Read\ Error=Erreur\ de\ Lecture +Timeout=Temps\ dépassé +Actual\ Files=Fichiers\ Actifs +Deleted\ Files=Fichiers\ Supprimés +Carved\ Files=Fichiers\ Récupérés +Geo-referenced\ Files=Fichiers\ Géotagués +Container\ Subitems=Sous-éléments\ du\ Conteneur +Containers\ not\ Expanded=Conteneurs\ non\ Développés +Explicit\ Images\ &\ Videos=Images\ &\ Vidéos\ -\ Nudité\ Possible +Images\ &\ Videos\ with\ Thumbs=Images\ &\ Vidéos\ avec\ Vignettes +Files\ with\ Thumbnails=Fichiers \ avec\ Vignettes diff --git a/iped-app/resources/localization/iped-geo-messages_fr_FR.properties b/iped-app/resources/localization/iped-geo-messages_fr_FR.properties new file mode 100644 index 0000000000..62ed00722e --- /dev/null +++ b/iped-app/resources/localization/iped-geo-messages_fr_FR.properties @@ -0,0 +1,29 @@ +App.Map=Carte +KMLResult.LoadingGPSData=Chargement des données GPS +KMLResult.NoGPSItem=Aucun élément trouvé avec les données GPS \! +KMLResult.Results=Résultats +KMLResult.Save=Enregistrement +KMLResult.SearchResults=Recherche des résultats +KMLResult.SearchResultsDescription=Résultats de recherche GPS. +KMLResult.ShowInTree=Consulter dans l'arboresence. +JMapOptionsPane.title=Sélectionner la source de la carte utilisée +JMapOptionsPane.GoogleApiKeyLabel=Saisissez une clé API Google Maps valide +JMapOptionsPane.UseLeaflet=Utiliser Leaflet +JMapOptionsPane.UrlPatternLabel=Saisir l'URL source de la carte : +JMapOptionsPane.AnotherURL=Autre URL +JMapOptionsPane.UseGoogleMaps=Utiliser Google Maps +toolbar.Radius=Rayon +toolbar.ExportKML=Exporter en KML +toolbar.Next=Suivant +toolbar.Previous=Précédent +toolbar.First=Premier +toolbar.Last=Dernier +toolbar.Area=Zone +toolbar.Selection=Sélection +toolbar.Navigation=Navigation +toolbar.Sorting=Tri +toolbar.DisplayAll=Afficher tout +toolbar.MappedItensCount=Eléments cartographiés +toolbar.ChangeTileServer=Changer de serveur +gpxXslt.dateTrailLabel=Sentier dans +gpxXslt.routeLabel=Itinéraire diff --git a/iped-app/resources/localization/iped-parsers-messages.properties b/iped-app/resources/localization/iped-parsers-messages.properties index 6b441d003d..ee4e2615c4 100644 --- a/iped-app/resources/localization/iped-parsers-messages.properties +++ b/iped-app/resources/localization/iped-parsers-messages.properties @@ -345,6 +345,10 @@ BitTorrentResumeDatParser.Time=Date/Time BitTorrentResumeDatParser.LastSeenCompleteDate=Last Seen Complete BitTorrentResumeDatParser.SeedTime=Seed time (s) BitTorrentResumeDatParser.RunTime=Run time (s) +BitTorrentResumeDatParser.InfoHash=InfoHash +BitTorrentResumeDatParser.FilesFoundInCase=Files Found in the Case +BitTorrentResumeDatParser.TorrentFoundInCase=Torrent Found in the Case +BitTorrentResumeDatParser.Yes=Yes TorrentFileDatParser.DateFormat=MM/dd/yyyy HH:mm:ss TorrentFileDatParser.FullPath=Full Path TorrentFileDatParser.FileSize=File Size (Bytes) @@ -362,6 +366,13 @@ TorrentFileDatParser.NumberOfPieces=Number of pieces TorrentFileDatParser.Piece=Piece TorrentFileDatParser.PieceLength=Piece length TorrentFileDatParser.IncompleteWarning=Incomplete file. Some of the parse information may be wrong. Please verify. +TorrentFileDatParser.File=File +TorrentFileDatParser.FileFoundInCase=File Found in the Case +TorrentFileDatParser.FilesFoundInCase=Files Found in the Case +TorrentFileDatParser.PathInCase=Path of Item Found in the Case +TorrentFileDatParser.Yes=Yes +TorrentFileDatParser.ConfirmedPieces=Confirmed pieces +TorrentFileDatParser.AtOffset=at offset TelegramContact.ContactID=Contact ID: TelegramContact.FirstName=First Name: TelegramContact.LastName=Last Name: diff --git a/iped-app/resources/localization/iped-parsers-messages_de_DE.properties b/iped-app/resources/localization/iped-parsers-messages_de_DE.properties index d6fb7cfd7d..06d93740bf 100644 --- a/iped-app/resources/localization/iped-parsers-messages_de_DE.properties +++ b/iped-app/resources/localization/iped-parsers-messages_de_DE.properties @@ -5,7 +5,7 @@ AresParser.Artist=Künstler AresParser.Category=Kategorie AresParser.Comments=Kommentare AresParser.Corrupted=Beschädigt -AresParser.DateFormat=MM/dd/yyyy HH:mm:ss +AresParser.DateFormat=dd/MM/yyyy HH:mm:ss AresParser.FileDate=Dateidatum (Lokale Zeit) AresParser.FoundInCase=In Fall gefunden AresParser.FoundInPedoHashDB=in KiPo Hash-Datenbank gefunden @@ -18,7 +18,7 @@ AresParser.Size=Größe AresParser.Title=Titel AresParser.URL=URL AresParser.Yes=Ja -DateFormat=MM/dd/yyyy HH:mm:ss +DateFormat=dd/MM/yyyy HH:mm:ss DiscordParser.Attachments=Anhänge DiscordParser.Start=Start DiscordParser.End=Ende @@ -40,7 +40,7 @@ IncrediMailParser.NoSubject=[kein Betreff] StandardParser.MetadataTitle=METADATEN: KnownMetParser.AcceptedRequests=angenommene Anfragen KnownMetParser.BytesSent=Bytes gesendet -KnownMetParser.DataFormat=MM/dd/yyyy HH:mm:ss +KnownMetParser.DataFormat=dd/MM/yyyy HH:mm:ss KnownMetParser.Hash=Hashwert eDonkey KnownMetParser.FoundInCase=Gefunden im Fall KnownMetParser.FoundInPedoHashDB=Gefunden in KiPo Hash Database @@ -68,7 +68,7 @@ LNKShortcutParser.CommonPathUnicode=Gemeinsamer Pfad - Unicode LNKShortcutParser.Created=Erstelldatum LNKShortcutParser.DataNotDecoded=(Daten nicht dekodiert) LNKShortcutParser.DataStrings=Daten Zeichenfolgen ( -LNKShortcutParser.DateFormat=MM/dd/yyyy HH:mm:ss [z] +LNKShortcutParser.DateFormat=dd/MM/yyyy HH:mm:ss [z] LNKShortcutParser.Description=Beschreibung LNKShortcutParser.Directory=Verzeichnis LNKShortcutParser.DistributedLinkTrackProps=Eigenschaften Distributed Link Tracker @@ -120,7 +120,7 @@ MetadataUtil.NoSubject=[kein Betreff] MSAccessParser.Table=Tabelle:\ OutlookPSTParser.Attachment=Anhang- OutlookPSTParser.Attachments=Anhänge -OutlookPSTParser.DateFormat=MM/dd/yyyy HH:mm:ss +OutlookPSTParser.DateFormat=dd/MM/yyyy HH:mm:ss OutlookPSTParser.From=From OutlookPSTParser.NoSubject=[kein Betreff] OutlookPSTParser.Sent=gesendet @@ -142,7 +142,7 @@ SkypeConversation.SkypeChat=Skype Chat\ SkypeFileTransfer.Download=Download SkypeFileTransfer.FileOffer=Datei angeboten (*) SkypeFileTransfer.FileSend=Datei gesendet -SkypeParser.DateFormat=MM/dd/yyyy HH:mm:ss +SkypeParser.DateFormat=dd/MM/yyyy HH:mm:ss SkypeParser.SkypeTransfer=Skype Transfer SkypeReport.About=Über SkypeReport.AcceptDate=Datum akzeptiert @@ -197,7 +197,7 @@ SkypeReport.TransferCount=Transfer Zähler:\ SkypeReport.TypeDescr=Typ-Beschreibung SkypeReport.UserData=Benutzer-Daten: SkypeReport.Value=Wert -SQLite3TableReader.DateFormat=MM/dd/yyyy_HH:mm:ssz +SQLite3TableReader.DateFormat=dd/MM/yyyy_HH:mm:ssz WhatsAppReport.AccountID=Account ID:\ WhatsAppReport.ChatContinuation=[Chat-Fortsetzung...] WhatsAppReport.ChatContinues=[Chat wird fortgesetzt...] @@ -333,7 +333,7 @@ VCardParser.Telephone=Telefone VCardParser.Organization=Organisation VCardParser.Notes=Notizen VCardParser.Photo=Foto -BitTorrentResumeDatParser.DateFormat=MM/dd/yyyy HH:mm:ss +BitTorrentResumeDatParser.DateFormat=dd/MM/yyyy HH:mm:ss BitTorrentResumeDatParser.TorrentFile=Torrent-Datei BitTorrentResumeDatParser.RootDir=Wurzelverzeichnis BitTorrentResumeDatParser.Path=vollständiger Pfad @@ -345,7 +345,11 @@ BitTorrentResumeDatParser.Time=Datum/Zeit BitTorrentResumeDatParser.LastSeenCompleteDate=zuletzt vollständig gesehen BitTorrentResumeDatParser.SeedTime=Seed time (s) BitTorrentResumeDatParser.RunTime=Laufzeit (s) -TorrentFileDatParser.DateFormat=MM/dd/yyyy HH:mm:ss +BitTorrentResumeDatParser.InfoHash=InfoHash[TBT] +BitTorrentResumeDatParser.FilesFoundInCase=Files Found in the Case[TBT] +BitTorrentResumeDatParser.TorrentFoundInCase=Torrent Found in the Case[TBT] +BitTorrentResumeDatParser.Yes=Yes[TBT] +TorrentFileDatParser.DateFormat=dd/MM/yyyy HH:mm:ss TorrentFileDatParser.FullPath=vollständiger Pfad TorrentFileDatParser.FileSize=Dateigröße (Bytes) TorrentFileDatParser.MD5=MD5 Hashwert @@ -362,6 +366,13 @@ TorrentFileDatParser.NumberOfPieces=Number of pieces[TBT] TorrentFileDatParser.Piece=Piece[TBT] TorrentFileDatParser.PieceLength=Piece length[TBT] TorrentFileDatParser.IncompleteWarning=Incomplete file. Some of the parse information may be wrong. Please verify.[TBT] +TorrentFileDatParser.File=File[TBT] +TorrentFileDatParser.FileFoundInCase=File Found in the Case[TBT] +TorrentFileDatParser.FilesFoundInCase=Files Found in the Case[TBT] +TorrentFileDatParser.PathInCase=Path of Item Found in the Case[TBT] +TorrentFileDatParser.Yes=Yes[TBT] +TorrentFileDatParser.ConfirmedPieces=Confirmed pieces[TBT] +TorrentFileDatParser.AtOffset=at offset[TBT] TelegramContact.ContactID=Kontakt ID: TelegramContact.FirstName=Vorname: TelegramContact.LastName=Nachname: diff --git a/iped-app/resources/localization/iped-parsers-messages_es_AR.properties b/iped-app/resources/localization/iped-parsers-messages_es_AR.properties index ff175fac36..98359140cc 100644 --- a/iped-app/resources/localization/iped-parsers-messages_es_AR.properties +++ b/iped-app/resources/localization/iped-parsers-messages_es_AR.properties @@ -345,6 +345,10 @@ BitTorrentResumeDatParser.Time=Fecha/Hora BitTorrentResumeDatParser.LastSeenCompleteDate=Último visto completo BitTorrentResumeDatParser.SeedTime=Hora de la siembra (s) BitTorrentResumeDatParser.RunTime=Tiempo de ejecución (s) +BitTorrentResumeDatParser.InfoHash=InfoHash[TBT] +BitTorrentResumeDatParser.FilesFoundInCase=Files Found in the Case[TBT] +BitTorrentResumeDatParser.TorrentFoundInCase=Torrent Found in the Case[TBT] +BitTorrentResumeDatParser.Yes=Yes[TBT] TorrentFileDatParser.DateFormat=dd/MM/yyyy HH:mm:ss TorrentFileDatParser.FullPath=Ubicación Full TorrentFileDatParser.FileSize=Tamaño del archivo (Bytes) @@ -362,6 +366,13 @@ TorrentFileDatParser.NumberOfPieces=Number of pieces[TBT] TorrentFileDatParser.Piece=Piece[TBT] TorrentFileDatParser.PieceLength=Piece length[TBT] TorrentFileDatParser.IncompleteWarning=Incomplete file. Some of the parse information may be wrong. Please verify.[TBT] +TorrentFileDatParser.File=File[TBT] +TorrentFileDatParser.FileFoundInCase=File Found in the Case[TBT] +TorrentFileDatParser.FilesFoundInCase=Files Found in the Case[TBT] +TorrentFileDatParser.PathInCase=Path of Item Found in the Case[TBT] +TorrentFileDatParser.Yes=Yes[TBT] +TorrentFileDatParser.ConfirmedPieces=Confirmed pieces[TBT] +TorrentFileDatParser.AtOffset=at offset[TBT] TelegramContact.ContactID=Contact ID: TelegramContact.FirstName=Nombre de la persona: TelegramContact.LastName=Segundo Nombre: diff --git a/iped-app/resources/localization/iped-parsers-messages_fr_FR.properties b/iped-app/resources/localization/iped-parsers-messages_fr_FR.properties new file mode 100644 index 0000000000..a1b81febd7 --- /dev/null +++ b/iped-app/resources/localization/iped-parsers-messages_fr_FR.properties @@ -0,0 +1,518 @@ +AbstractDBParser.ProbableDate=*Date possiblement décodée.\n +AbstractDBParser.Table=Tableau :\ +AresParser.Album=Album +AresParser.Artist=Artiste +AresParser.Category=Catégories +AresParser.Comments=Commentaires +AresParser.Corrupted=Corrompu +AresParser.DateFormat=dd/MM/yyyy HH:mm:ss +AresParser.FileDate=Horodatage du fichier (Heure locale) +AresParser.FoundInCase=Trouvé dans le cas +AresParser.FoundInPedoHashDB=Correspondance dans la base de hash avec de la pédopornographie +AresParser.HashSha1=Hash SHA1 +AresParser.No=Non +AresParser.Path=Chemin complet +AresParser.Seq=Séquence +AresParser.Shared=Partagé +AresParser.Size=Taille +AresParser.Title=Titre +AresParser.URL=Adresse web +AresParser.Yes=Oui +DateFormat=dd/MM/yyyy HH:mm:ss +DiscordParser.Attachments=Pièces jointes +DiscordParser.Start=Début +DiscordParser.End=Fin +DiscordParser.EditTime=Modifier l'heure: +DiscordParser.Participants=Participants +DiscordParser.Reactions=Réactions : +DiscordParser.DateFormat0=(hh:mm:ss dd/MM/yyyy) +DiscordParser.DateFormat2=dd/MM/yy +EmbeddedDocumentParser.UnNamed=[Inconnu]- +FirefoxSessions.TabsHeader=Onglets des sessions sauvegardées de Mozilla Firefox +FirefoxSessions.TabsTitle=Titre +FirefoxSessions.TabsURL=URL +FirefoxSessions.CookiesHeader=Cookies des sessions sauvegardées de Mozilla Firefox +FirefoxSessions.CookiesHost=Hôte +FirefoxSessions.CookiesPath=Chemin +FirefoxSessions.CookiesName=Nom +FirefoxSessions.CookiesCookie=Cookie +IncrediMailParser.NoSubject=[Sans sujet] +StandardParser.MetadataTitle=Métadonnées : +KnownMetParser.AcceptedRequests=Demandes acceptées +KnownMetParser.BytesSent=Bytes envoyés +KnownMetParser.DataFormat=dd/MM/yyyy HH:mm:ss +KnownMetParser.Hash=Hash eDonkey +KnownMetParser.FoundInCase=Trouvé dans le cas +KnownMetParser.FoundInPedoHashDB=Pédopornographie trouvée dans la base de Hash +KnownMetParser.LastModDate=Dernière date de modification (UTC) +KnownMetParser.LastPubDate=Dernière date de publication (UTC) +KnownMetParser.LastShareDate=Dernière date d'échange +KnownMetParser.Name=Nom du fichier +KnownMetParser.Requests=Total des demandes +KnownMetParser.Seq=Séquence +KnownMetParser.Size=Taille du fichier +KnownMetParser.TempFile=Fichier temporaire +KnownMetParser.Totals=TOTAUX +KnownMetParser.Yes=Oui +PreferencesDat.Version=Version +PreferencesDat.UserHash=Hash utilisateur +LibpffPSTParser.AttachedMessage=Message joint +LibpffPSTParser.Attachments=Pièces jointes +LibpffPSTParser.NoSubject=[Sans sujet] +LNKShortcutParser.Accessed=Date du dernier accès +LNKShortcutParser.BirthDroidFileId=Birth Droid File Identifier +LNKShortcutParser.BirthDroidVolId=Birth Droid Volume Identifier +LNKShortcutParser.CmdLineArgs=Arguments ligne de commande +LNKShortcutParser.CommonPath=Chemin commun +LNKShortcutParser.CommonPathUnicode=Chemin commun - Unicode +LNKShortcutParser.Created=Date de création +LNKShortcutParser.DataNotDecoded=(donnée non décodée) +LNKShortcutParser.DataStrings=Chaine de données ( +LNKShortcutParser.DateFormat=dd/MM/yyyy HH:mm:ss [z] +LNKShortcutParser.Description=Description +LNKShortcutParser.Directory=Dossier +LNKShortcutParser.DistributedLinkTrackProps=Propriété du tacker de liens distribués +LNKShortcutParser.DriveSerial=Numéro de série du lecteur +LNKShortcutParser.DriveType=Type de disque dur +LNKShortcutParser.DroidFileId=Identifiant du fichier du Droid +LNKShortcutParser.DroidVolId=Identifiant du volume du Droid +LNKShortcutParser.EntryType=Type d'entrée +LNKShortcutParser.Extensions=Extensions +LNKShortcutParser.File=Fichier +LNKShortcutParser.FileAttr=Attributs du fichier +LNKShortcutParser.FileHeader=En-tête du fichier (LNK) +LNKShortcutParser.HotKey=Touche de raccourci +LNKShortcutParser.IconIndex=Index de l'icône +LNKShortcutParser.IconLocation=Emplacement de l'icône +LNKShortcutParser.LastMod=Dernière modification +LNKShortcutParser.LinkAttr=Attributs des liens (Data Flags) +LNKShortcutParser.LinkLocationInfo=Information sur l'emplacement des liens (HasLinkInfo) +LNKShortcutParser.LinkTargetID=Identification de la cible du lien (HasTargetIDList) +LNKShortcutParser.LocalizedNames=Nom local du Shell +LNKShortcutParser.LocalPath=Chemin local +LNKShortcutParser.LocalPathUnicode=Chemin local - Unicode +LNKShortcutParser.LocationFlags=Indicateur de localisation +LNKShortcutParser.MachineId=Identifiant de la machine +LNKShortcutParser.Modified=Date de dernière modification +LNKShortcutParser.NetComments=Réseau - commentaires +LNKShortcutParser.NetDescription=Descriptif du réseau +LNKShortcutParser.NetDeviceName=Nom du périphérique réseau +LNKShortcutParser.NetDevNameUnicode=Nom du périphérique réseau - Unicode +LNKShortcutParser.NetItemName=Nom de l'élément de réseau +LNKShortcutParser.NetItemType=Type d'élément de réseau +LNKShortcutParser.NetProviderType=Type de fournisseur de réseau +LNKShortcutParser.NetShare=Nom du dossier réseau +LNKShortcutParser.NetShareUnicode=Nom du dossier réseau - Unicode +LNKShortcutParser.NtfsRef=Référence NTFS +LNKShortcutParser.PrimaryName=Nom principal +LNKShortcutParser.RelativePath=Chemin relatif +LNKShortcutParser.SecondaryName=Nom secondaire +LNKShortcutParser.Size=Taille +LNKShortcutParser.TargetAttr=Propriétés de la cible +LNKShortcutParser.TargetSize=Taille de la cible +LNKShortcutParser.UnknownData=Donnée inconnue +LNKShortcutParser.VolumeLabel=Nom du lecteur +LNKShortcutParser.VolumeLabelUnicode=Nom du lecteur - Unicode +LNKShortcutParser.WindowAttr=Propriétés de la fenêtre +LNKShortcutParser.WorkingDir=Dossier de travail +MboxParser.NoSubject=[Sans sujet] +MetadataUtil.NoSubject=[Sans sujet] +MSAccessParser.Table=Tableau :\ +OutlookPSTParser.Attachment=Pièces jointes- +OutlookPSTParser.Attachments=Pièces jointes +OutlookPSTParser.DateFormat=dd/MM/yyyy HH:mm:ss +OutlookPSTParser.From=de +OutlookPSTParser.NoSubject=[Sans sujet] +OutlookPSTParser.Sent=Envoyé +OutlookPSTParser.Subject=Sujet +OutlookPSTParser.To=À : +OutlookPSTParser.ImportanceHigh=Haute +OutlookPSTParser.ImportanceNormal=Normal +OutlookPSTParser.ImportanceLow=Faible +PythonModule.JepNotFound=JEP non trouvé, tous les modules python sont désactivés.\ +PythonModule.ModuleDisabled=\ module désactivé.\ +PythonModule.SeeManual=Consulter https://github.com/sepinf-inc/IPED/wiki/User-Manual#python-modules +ReportGenerator.DownloadedFile=[Fichier téléchargé] +ReportGenerator.TranscriptionTitle=Transcription automatique +ReportGenerator.Unknown=Inconnu +ReportGenerator.UnknownDate=Horodatage inconnu +RFC822Parser.AttachedEmail=Email en pièce jointe.eml +RFC822Parser.UnNamed=[Sans nom] +SkypeConversation.SkypeChat=Chat de l'application Skype\ +SkypeFileTransfer.Download=Téléchargement +SkypeFileTransfer.FileOffer=Proposition de fichier (*) +SkypeFileTransfer.FileSend=Envoi de fichier +SkypeParser.DateFormat=dd/MM/yyyy HH:mm:ss +SkypeParser.SkypeTransfer=Transfert Skype +SkypeReport.About=À propos +SkypeReport.AcceptDate=Date d'acceptation +SkypeReport.Attribute=Propriété +SkypeReport.Author=Auteur +SkypeReport.Avatar=Avatar : +SkypeReport.AvatarDate=Date de l'avatar +SkypeReport.BirthDate=Date de naissance +SkypeReport.Chat=Chat +SkypeReport.ChatID=Identifiant du chat +SkypeReport.ChatName=Nom du chat +SkypeReport.City=Ville +SkypeReport.ContactCount=Nombre de contacts :\ +SkypeReport.Content=Contenu +SkypeReport.Country=Pays +SkypeReport.Date=Date +SkypeReport.DisplayName=Nom d'affichage +SkypeReport.EditedBy=Modifié par +SkypeReport.EditedDate=Date de modification +SkypeReport.Email=E-mail +SkypeReport.Empty=[Vide] +SkypeReport.FileName=Nom du fichier +SkypeReport.FileSize=Taille du fichier +SkypeReport.FinishDate=Date de fin +SkypeReport.From=De +SkypeReport.FullName=Nom complet +SkypeReport.FullPath=Chemin complet +SkypeReport.HomePhone=Téléphone fixe +SkypeReport.ID=Identifiant +SkypeReport.ImageCacheMsg=Image du cache multimédia +SkypeReport.LastContactedDate=Date du dernier contact +SkypeReport.LastOnlineDate=Dernière date de connexion +SkypeReport.LikelyFile=Fichier probable : +SkypeReport.MessageCount=Nombre de messages :\ +SkypeReport.Messages=Messages +SkypeReport.MobilePhone=Téléphone mobile +SkypeReport.Mood=Mood +SkypeReport.MoodDate=Mood Date +SkypeReport.OfficePhone=Téléphone du travail +SkypeReport.Participants=Participants : +SkypeReport.Phone=Téléphone +SkypeReport.ProfileDate=Date du profil +SkypeReport.Province=Province +SkypeReport.PstnNum=Numéro PSTN +SkypeReport.Recipient=Destinataire +SkypeReport.RemoteID=Identifiant d'envoi +SkypeReport.SentBytes=Bytes envoyés +SkypeReport.SkypeID=Identifiant Skype +SkypeReport.StartDate=Date de début +SkypeReport.TotalCount=Nombre Total +SkypeReport.TransferCount=Nombre de transferts :\ +SkypeReport.TypeDescr=Description +SkypeReport.UserData=Donnée utilisateur : +SkypeReport.Value=Valeur +SQLite3TableReader.DateFormat=dd/MM/yyyy_HH:mm:ssz +WhatsAppReport.AccountID=Identifiant du compte :\ +WhatsAppReport.ChatContinuation=[Suite du chat...] +WhatsAppReport.ChatContinues=[le chat continue...] +WhatsAppReport.ContactDeleted=Contacts supprimés récupérés +WhatsAppReport.RecoveredChat=Chat supprimés récupérés +WhatsAppReport.ContactID=Identifiant de contactv:\ +WhatsAppReport.DisplayName=Nomv:\ +WhatsAppReport.GivenName=Prénomv:\ +WhatsAppReport.NickName=Surnom :\ +WhatsAppReport.SortName=Nom du tri :\ +WhatsAppReport.Status=Statut :\ +WhatsAppReport.Video=Vidéo +WhatsAppReport.WAName=Nom WA :\ +WhatsAppReport.UnknownMessage=Message inconnu. +WhatsAppReport.UnknownMediaMessage=Message Média inconnu +WhatsAppReport.Forwarded=Transféré +WhatsAppReport.SecurityChanged=Le code de sécurité a changé. Appuyer pour plus d'informations. +WhatsAppReport.BlockedContact=Vous avez bloqué ce contact. Appuyer pour débloquer. +WhatsAppReport.UnblockedContact=Vous avez débloqué ce contact. +WhatsAppReport.BusinessSecureService=Cette entreprise utilise un service sécurisé de Meta pour gérer ce chat. Cliquer pour plus d'information. +WhatsAppReport.BusinessToStandard=Ce compte professionnel est désormais enregistré en tant que compte standard. Appuyer pour plus d'informations. +WhatsAppReport.ChatBusiness=Ce chat s'effectue avec un compte professionnel. Appuyer pour plus d'informations. +WhatsAppReport.ChatEncrypted=Les messages et les appels sont cryptés de bout en bout. Personne en dehors de ce chat ne peut les lire ou les écouter, pas même WhatsApp. Appuyer pour en savoir plus. +WhatsAppReport.ChatNowEncrypted=Les messages de ce chat et les appels sont désormais sécurisés avec un cryptage de bout en bout. Appuyer pour plus d'informations. +WhatsAppReport.ChatStandard=Ce compte professionnel est désormais enregistré en tant que compte standard. Appuyer pour plus d'informations. +WhatsAppReport.GroupNowEncrypted=Les messages adressés à ce groupe sont désormais sécurisés avec un cryptage de bout en bout. Appuyer pour plus d'informations. +WhatsAppReport.MissedVideoCall=Appel vidéo manqué +WhatsAppReport.MissedVoiceCall=Appel vocal manqué +WhatsAppReport.RefusedVoiceCall=Appel vocal rejeté +WhatsAppReport.RefusedVideoCall=Appel vidéo rejeté +WhatsAppReport.UnavailableVoiceCall=Appel vocal indisponible +WhatsAppReport.UnavailableVideoCall=Appel vidéo indisponible +WhatsAppReport.UnknownVoiceCall=Type d'appel vocal inconnu +WhatsAppReport.UnknownVideoCall=Type d'appel vidéo inconnu +WhatsAppReport.GroupCreated=Groupe créé par +WhatsAppReport.UserAddedToCommunity=Utilisateur ajouté à la communauté +WhatsAppReport.UserAddedToGroup=Utilisateur ajouté au groupe +WhatsAppReport.UserCommunityAdmin=Définir l'utilisateur en tant qu'administrateur +WhatsAppReport.CommunityAdmin=est à présent administrateur +WhatsAppReport.UserLeftGroup=Utilisateur ayant quitté le groupe :\ +WhatsAppReport.UserRemovedGroup=Utilisateur supprimé du groupe :\ +WhatsAppReport.AddedToCommunity=Ajouté à la communauté +WhatsAppReport.AddedToGroup=Ajouté au groupe +WhatsAppReport.RemovedGroup=Supprimé du groupe +WhatsAppReport.GroupIconChanged=l'icône du groupe a changé +WhatsAppReport.GroupIconDeleted=l'icône du groupe a été supprimé +WhatsAppReport.MessageDeleted=Message supprimé +WhatsAppReport.MessageDeletedByAdmin=Message supprimé par l'administrateur +WhatsAppReport.MessageDeletedBySender=Message supprimé par l'expéditeur +WhatsAppReport.MessageDeletedRecovered=Message supprimé récupéré +WhatsAppReport.LocationMessage=Emplacement : +WhatsAppReport.SharedLocationMessage=Emplacement partagé : +WhatsAppReport.Latitude=Latitude +WhatsAppReport.Longitude=Longitude +WhatsAppReport.Attachment=Pièce jointe +WhatsAppReport.VoiceCall=Appel vocal +WhatsAppReport.VideoCall=Appel vidéo +WhatsAppReport.UserJoinedGroupCommunity=a rejoint le groupe par la communauté +WhatsAppReport.UserJoinedGroupInvitation=a rejoint le groupe sur invitation +WhatsAppReport.UserJoinedGroupLink=a rejoint le groupe à partir d'un lien partagé +WhatsAppReport.ResetGroupLink=a réinitialisé le lien d'invitation +WhatsAppReport.GroupDescriptionChanged=Description du groupe modifiée +WhatsAppReport.GroupDescriptionDeleted=Description du groupe supprimée +WhatsAppReport.GroupNameChanged=a changé le nom du groupe +WhatsAppReport.SubjectChanged=Sujet modifié +WhatsAppReport.UserAdmin=est à préseant administrateur du groupe +WhatsAppReport.YouAdmin=Vous êtes à présent administrateur du groupe +WhatsAppReport.YouNotAdmin=Vous n'êtes plus administrateur de ce groupe +WhatsAppReport.WaitingMessage=En attente de message +WhatsAppReport.Duration=Durée +WhatsAppReport.AudioMessageTitle=Fichier de message audio +WhatsAppReport.VideoMessageTitle=Fichier de message vidéo +WhatsAppReport.Contact=Contact +WhatsAppReport.RecoveredFrom=Récupéré de +WhatsAppReport.FoundInPedoHashDB=Contenu pédopornographique détecté via la base de Hashs +WhatsAppReport.Owner=Propriétaire +WhatsAppReport.Recovered=Récupéré +WhatsAppReport.QuoteNotFound=Message cité est introuvable +WhatsAppReport.Document=Document +WhatsAppReport.Photo=Photo +WhatsAppReport.Audio=Audio +WhatsAppReport.ChatFragment=Ce message cité se trouve dans l'extrait de la discussion +WhatsAppReport.ReferenceId=Identifiant du message cité +WhatsAppReport.Close=Fermer +WhatsAppReport.GroupInvite=Invitation au groupe WhatsApp +WhatsAppReport.Poll=Sondage +WhatsAppReport.Vote=vote +WhatsAppReport.Votes=votes +WhatsAppReport.EphemeralDurationChanged=a changé la durée avant effacement des messages pour +WhatsAppReport.EphemeralDefault=utilise une durée de conservation par défaut des messages dans les nouvelles conversations. Tous les messages de ce chat disparaitront après +WhatsAppReport.EphemeralOn=a activé l'effacement des messages. Tous les messages ce chat disparaitront après. +WhatsAppReport.EphemeralOff=a désactivé l'effacement des messages. +WhatsAppReport.EphemeralSave=Il est désormais possible de sauvegarder les messages temporaires du chat. +WhatsAppReport.Days=jours +WhatsAppReport.Hours=heures +WhatsAppReport.GroupChangedOnlyAdminsCanAdd=a modifié les paramètres de ce groupe pour permettre uniquement aux administrateurs d'ajouter d'autres utilisateurs. +WhatsAppReport.GroupChangedAllMembersCanEdit=a modifié les paramètres de ce groupe pour permettre à tous les participants d'en modifier les informations. +WhatsAppReport.GroupChangedOnlyAdminsCanEdit=a modifié les paramètres de ce groupe pour permettre uniquement aux administrateurs d'effectuer des modifications. +WhatsAppReport.GroupChangedAllMembersCanSend=a modifié les paramètres de ce groupe pour permettre à tous les participants d'envoyer des messages. +WhatsAppReport.GroupChangedOnlyAdminsCanSend=a modifié les paramètres de ce groupe pour autoriser uniquement les administrateurs à envoyer des messages. +WhatsAppReport.GroupOnlyAdminsCanSend=Seuls les administrateurs peuvent envoyer des messages à ce groupe. +WhatsAppReport.ChangedDevice=a changer d'appareil. +WhatsAppReport.ChangedNumberTo=changé en +WhatsAppReport.ChangedNumberChattingWithNew=a changé de numéro de téléphone. Vous discutez actuellement avec leur nouveau numéro. +WhatsAppReport.ChangedNumberChattingWithOld=a changé son numéro de téléphone. Appuyez pour envoyer un message au nouveau numéro. +WhatsAppReport.SenderInContacts=est dans vos contacts. +WhatsAppReport.SenderAddedToContacts=a été ajouté à vos contacts. +WhatsAppReport.BusinessChangedName=Ce compte professionnel a changé de nom. +WhatsAppReport.ChatBusinessOfficial=Ce chat est avec un compte professionnel officiel. +WhatsAppReport.GroupAddedToCommunity=Le groupe a été ajouté à la communauté. +WhatsAppReport.GroupRemovedFromCommunity=Le groupe a été supprimé de la communauté. +WhatsAppReport.AnyCommunityMemberCanJoinThisGroup=N'importe qui dans la communauté peut rejoindre ce groupe. +WhatsAppReport.CommunityManagementAction=Gestion de la communauté. +WhatsAppReport.CommunityRenamed=Changer le nom de la communauté +WhatsAppReport.CommunityWelcome=Bienvenue dans la communauté. +WhatsAppReport.NewParticipantsNeedAdminApproval=Les nouveaux participants ont besoin de l'approbation de l'administrateur pour rejoindre ce groupe. +WhatsAppReport.ChatAddedPrivacy=Ce chat assure la confidentialité de votre profil et de votre numéro de téléphone. +WhatsAppReport.ChannelAddedPrivacy=Cette chaîne assure la confidentialité de votre profil et de votre numéro de téléphone. +WhatsAppReport.ChannelCreated=La chaîne a été créée. +WhatsAppReport.ProductTitle=Produit +WhatsAppReport.ProductSeller=Vendeur +WhatsAppReport.ProductAmount=Montant +WhatsAppReport.OrderCount=Quantité +WhatsAppReport.EditedOn=Modifié en +WhatsAppReport.UserJoinedWhatsApp=a rejoint WhatsApp +WhatsAppReport.PinnedMessage=a epinglé un message +WhatsAppReport.AIThirdParty=Cette IA provient d'un développeur tiers. Meta reçoit vos discussions IA pour améliorer la qualité de l'IA. +VCardParser.FormattedName=Nom formaté +VCardParser.Name=Nom +VCardParser.Nickname=Surnom +VCardParser.Email=E-mail +VCardParser.Telephone=Téléphone +VCardParser.Organization=Organisation +VCardParser.Notes=Notes +VCardParser.Photo=Photo +BitTorrentResumeDatParser.DateFormat=dd/MM/yyyy HH:mm:ss +BitTorrentResumeDatParser.TorrentFile=Fichier Torrent +BitTorrentResumeDatParser.RootDir=Dossier racine +BitTorrentResumeDatParser.Path=Chemin complet +BitTorrentResumeDatParser.Downloaded=Téléchargés (bytes) +BitTorrentResumeDatParser.Uploaded=Uploadés (bytes) +BitTorrentResumeDatParser.AddedDate=Date/Heure ajouté +BitTorrentResumeDatParser.CompletedDate=Date/Heure complété +BitTorrentResumeDatParser.Time=Date/Heure +BitTorrentResumeDatParser.LastSeenCompleteDate=Dernière fois vu complet +BitTorrentResumeDatParser.SeedTime=Seed time (s) +BitTorrentResumeDatParser.RunTime=Durée d'execution (s) +BitTorrentResumeDatParser.InfoHash=Information sur le Hash +BitTorrentResumeDatParser.TorrentFoundInCase=Torrent trouvé dans le cas +BitTorrentResumeDatParser.Yes=Oui +BitTorrentResumeDatParser.FilesFoundInCase=Fichiers trouvés dans le cas +TorrentFileDatParser.DateFormat=dd/MM/yyyy HH:mm:ss +TorrentFileDatParser.FullPath=Chemin complet +TorrentFileDatParser.FileSize=Taille du fichier (Bytes) +TorrentFileDatParser.MD5=Hash MD5 +TorrentFileDatParser.SHA1=Hash SHA1 +TorrentFileDatParser.ED2K=Hash ED2K +TorrentFileDatParser.Announce=URL du tracker +TorrentFileDatParser.Comment=Commentaire +TorrentFileDatParser.CreatedBy=Créé par +TorrentFileDatParser.CreationDate=Date de création +TorrentFileDatParser.InfoHash=Informations sur le Hash +TorrentFileDatParser.Name=Nom +TorrentFileDatParser.NumberOfFiles=Nombre de fichier +TorrentFileDatParser.NumberOfPieces=Nombre de pièces +TorrentFileDatParser.Piece=Pièce +TorrentFileDatParser.PieceLength=taille de la pièce +TorrentFileDatParser.IncompleteWarning=Fichier incomplet. Certaines informations analysées peuvent être erronées. Veuillez vérifier. +TorrentFileDatParser.File=Fichier +TorrentFileDatParser.FileFoundInCase=Fichier trouvé dans le cas +TorrentFileDatParser.FilesFoundInCase=Fichiers trouvés dans le cas +TorrentFileDatParser.PathInCase=Emplacement de l'élément trouvé dans le cas +TorrentFileDatParser.Yes=Oui +TorrentFileDatParser.ConfirmedPieces=Pièces confirmées +TorrentFileDatParser.AtOffset=à l'offset +TelegramContact.ContactID=Identifiant du contact : +TelegramContact.FirstName=Prénom : +TelegramContact.LastName=Nom : +TelegramContact.Username=Nom d'utilisateur : +TelegramContact.Phone=Téléphone : +TelegramContact.Channel=Chaine de Telegram +TelegramContact.Group=Groupe de Telegram +TelegramReport.GroupCreate=Groupe/chat/canal créé +TelegramReport.AddMember=Ajouter un membre +TelegramReport.RemoveMember=Supprimer un membre +TelegramReport.PhotoUpdated=Mise à jour de la Photo +TelegramReport.TitleUpdated=Mise à jour du titre +TelegramReport.pinnMessage=Message épinglé mis à jour +TelegramReport.UserJoinLink=Utilisateur ayant rejoint via un lien +TelegramReport.ChangeToChannel=Changement de groupe à canal +TelegramReport.HistoryCleared=Historique effacé +TelegramReport.HistoryScreenshot=Capture d'écran de l'historique +TelegramReport.MessageAutoRemove=Définir le délai de suppression automatique des messages +TelegramReport.GameScore=Score du jeu +TelegramReport.PhoneCall=Appel téléphonique +TelegramReport.PaymentSent=Paiement envoyé +TelegramReport.CustomText=Texte personnalisé +TelegramReport.BotAcess=Accès accordé au domaine bot +TelegramReport.BotSent=Valeurs du bot SentSecure +TelegramReport.PeerJoin=Utilisateur a rejoint +TelegramReport.PhoneNumberRequest=Demande de numéro de téléphone +TelegramReport.ContactSignUp=Contact inscription +TelegramReport.ChatDeletePhoto=Supprimer la photo du chat +TelegramReport.UnknownMessage=Type de message inconnu :\ +TelegramReport.FoundInPedoHashDB=Contenu pédopornographique détecté via la base de Hashs +TelegramReport.geoProximityReached=L'alerte de géoproximité a été atteinte\ +TelegramReport.groupPhoneCall=Appel téléphonique de groupe +TelegramReport.inviteToGroupPhoneCall=Invitation à rejoindre le groupe d'appel téléphonique +TelegramReport.ChangeChatTheme=Changement du thème du chat +TelegramReport.joinedByRequest=Utilisateur a joint par requête +TelegramReport.ChannelMigratedFromGroup=Cette chaîne a migré depuis un groupe +TelegramReport.RecoveredChannel=Chaine supprimée récupérée +TelegramReport.RecoveredGroup=Groupe supprimé récupéré +TelegramReport.Link=Lien +TelegramReport.LinkTitle=Titre +TelegramReport.LinkURL=Adresse web +TelegramReport.Pool=Ensemble +ThreemaReport.ChatContinuation=[Suite du chat] +ThreemaReport.ChatContinues=[Le chat continue...] +ThreemaReport.UnknownMessage=Message inconnu +ThreemaReport.GroupRenamed=Groupe renommé +ThreemaReport.GroupNoteStart=*Vous êtes seul ici* Utilisez ce chat comme bloc-notes sécurisé pour le texte, les médias et les documents. +ThreemaReport.GroupNoteEnd=*Vous n'êtes plus seul dans ce chat* Les nouveaux messages seront lisibles par tous les membres du groupe. +ThreemaReport.GroupCreatorLeft=*Ce groupe est orphelin* Le créateur du groupe a quitté le groupe et celui-ci ne peut plus être maintenu. L'un des membres restants doit cloner le groupe (via les détails du groupe) pour devenir le nouvel administrateur. +ThreemaReport.GroupIconChanged=Photo du groupe modifiée +ThreemaReport.GroupCallStarted=Appel de groupe lancé +ThreemaReport.GroupCallEnded=Appel de groupe terminé +ThreemaReport.UserLeftGroup=L'utilisateur a quitté ce groupe +ThreemaReport.UserJoinedGroup=L'utilisateur a rejoint ce groupe +ThreemaReport.UserRemovedFromGroup=Utilisateur supprimé du groupe +ThreemaReport.SelfAddedToGroup=Vous avez été ajouté à ce groupe +ThreemaReport.SelfRemovedToGroup=Vous avez été supprimé de ce groupe +ThreemaReport.SelfLeftGroup=Vous avez quitté le groupe +ThreemaReport.MissedCall=Appel manqué +ThreemaReport.RejectedCall=Appel rejeté +ThreemaReport.RejectedCallBusy=Appel rejeté (occupé) +ThreemaReport.RejectedCallTimeout=Le destinataire de l'appel n'est pas disponible +ThreemaReport.RejectedCallDisabled=Appels Threema désactivés par le destinataire +ThreemaReport.RejectedCallUnknown=Appel rejeté (Inconnu) +ThreemaReport.RejectedCallOffHours=Appel rejeté (heures creuses) +ThreemaReport.WorkConsumerInfo=Ce contact utilise une version différente (Travail/Privé) depuis l'application Threema +ThreemaReport.ThreemaCall=Appel Threema +ThreemaReport.Duration=Durée +ThreemaReport.UnknownMediaMessage=Message multimédia inconnu +ThreemaReport.LocationMessage=Emplacement : +ThreemaReport.AudioMessageTitle=Fichier de messages audio +ThreemaReport.VideoMessageTitle=Fichier de messages vidéo +ThreemaReport.Video=Vidéo +ThreemaReport.FoundInPedoHashDB=Trouvé dans la base de hash de pédopornographie. +P2P.FoundInPedoHashDB=* Les lignes rouges signifient que les hachages ont été trouvés dans les bases de données de hachage d'alertes en matière de pédopornographie. +Win10Mail.NotFound=Non trouvé +APKParser.Permissions=Autorisations requises +APKParser.Manifest=Manifest XML +APKParser.Package=Package +APKParser.Version=Version +APKParser.SDKVersion=Version du SDK +APKParser.Features=Fonstionnalités +APKParser.Signers=Signataires +APKParser.SignersV2=Signataires(V2) +APKParser.Path=Chemin +APKParser.Certificate=Certificat +APKParser.Algorithm=Algorithme +APKParser.MD5=MD5 +APKParser.OID=OID +APKParser.StartDate=Date de début +APKParser.EndDate=Date de fin +OFXParser.AccessKey=Clé d'accès +OFXParser.AccountKey=Clé de compte +OFXParser.AccountLastUpdate=Dernière mise à jour du compte +OFXParser.AccountNumber=Numéro de compte +OFXParser.AccountType=Type de compte +OFXParser.Amount=Montant +OFXParser.AvailableBalanceAmount=Montant du solde disponible +OFXParser.AvailableBalanceDate=Date du solde disponible +OFXParser.Bank=Banque +OFXParser.BankId=Identifiant bancaire +OFXParser.BranchId=identifiant de succursale +OFXParser.CheckNumber=Numéro du chèque +OFXParser.CorrectionId=Numéro de correction +OFXParser.CreditCard=Carte de crédit +OFXParser.CurrencyCode=Code de devise +OFXParser.CurrencyExchangeRate=Taux de change +OFXParser.DateAvailable=Date de disponibilité +OFXParser.DateInitiated=Date de lancement +OFXParser.DatePosted=Date d'envoi +OFXParser.ExpirationUserKey=Clé utilisateur expirée +OFXParser.FinancialInstitutionId=Identifiant de l'institution financière +OFXParser.FinancialInstitutionOrganization=Organisation de l’institution financière +OFXParser.Id=Identifiant +OFXParser.Language=Langue +OFXParser.LedgerBalanceAmount=Montant du solde du grand livre +OFXParser.LedgerBalanceDate=Date du solde du grand livre +OFXParser.Memo=Mémo +OFXParser.Name=Nom +OFXParser.OriginalCurrencyCode=Code de devise d'origine +OFXParser.OriginalCurrencyExchangeRate=Taux de change d'origine +OFXParser.Payee=Bénéficiaire +OFXParser.PayeeId=Identifiant du Bénéficiaire +OFXParser.ProfileLastUpdate=Dernière mise à jour du profil +OFXParser.ReferenceNumber=Référence +OFXParser.ServerAssignedTemporaryId=Identifiant temporaire attribué par le serveur +OFXParser.SessionId=Identifiant de la session +OFXParser.Signon=Se connecter +OFXParser.StandardIndustrialCode=Code industriel standard +OFXParser.StatusCode=Code d'état +OFXParser.StatusSeverity=Statut de serveur +OFXParser.TimestampResponse=Horodatage de la réponse +OFXParser.Transactions=Transactions +OFXParser.TransactionStartDate=Date de début de la transaction +OFXParser.TransactionEndDate=Date de fin de transaction +OFXParser.Type=Type +OFXParser.UserKey=Clé utilisateur +OFXParser.DateOfStatement=Date du relevé +OFXParser.BrokerId=Identifiant du courtier +OFXParser.Investment=Investissement +OFXParser.BankTransactions=Opérations bancaires +OFXParser.SubAccountFund=Fonds de sous-compte +OFXParser.Investments=Investissements diff --git a/iped-app/resources/localization/iped-parsers-messages_it_IT.properties b/iped-app/resources/localization/iped-parsers-messages_it_IT.properties index 881167492d..abfee09355 100644 --- a/iped-app/resources/localization/iped-parsers-messages_it_IT.properties +++ b/iped-app/resources/localization/iped-parsers-messages_it_IT.properties @@ -345,6 +345,10 @@ BitTorrentResumeDatParser.Time=Data/Ora BitTorrentResumeDatParser.LastSeenCompleteDate=Ultimo visto completo BitTorrentResumeDatParser.SeedTime=Tempo di condivisione (s) BitTorrentResumeDatParser.RunTime=Tempo di esecuzione (s) +BitTorrentResumeDatParser.InfoHash=InfoHash[TBT] +BitTorrentResumeDatParser.FilesFoundInCase=Files Found in the Case[TBT] +BitTorrentResumeDatParser.TorrentFoundInCase=Torrent Found in the Case[TBT] +BitTorrentResumeDatParser.Yes=Yes[TBT] TorrentFileDatParser.DateFormat=dd/MM/yyyy HH:mm:ss TorrentFileDatParser.FullPath=Percorso completo TorrentFileDatParser.FileSize=Dimensione file (Byte) @@ -362,6 +366,13 @@ TorrentFileDatParser.NumberOfPieces=Number of pieces[TBT] TorrentFileDatParser.Piece=Piece[TBT] TorrentFileDatParser.PieceLength=Piece length[TBT] TorrentFileDatParser.IncompleteWarning=Incomplete file. Some of the parse information may be wrong. Please verify.[TBT] +TorrentFileDatParser.File=File[TBT] +TorrentFileDatParser.FileFoundInCase=File Found in the Case[TBT] +TorrentFileDatParser.FilesFoundInCase=Files Found in the Case[TBT] +TorrentFileDatParser.PathInCase=Path of Item Found in the Case[TBT] +TorrentFileDatParser.Yes=Yes[TBT] +TorrentFileDatParser.ConfirmedPieces=Confirmed pieces[TBT] +TorrentFileDatParser.AtOffset=at offset[TBT] TelegramContact.ContactID=ID Contatto: TelegramContact.FirstName=Nome: TelegramContact.LastName=Cognome: diff --git a/iped-app/resources/localization/iped-parsers-messages_pt_BR.properties b/iped-app/resources/localization/iped-parsers-messages_pt_BR.properties index 05b80e9e62..81c372bb6e 100644 --- a/iped-app/resources/localization/iped-parsers-messages_pt_BR.properties +++ b/iped-app/resources/localization/iped-parsers-messages_pt_BR.properties @@ -345,6 +345,10 @@ BitTorrentResumeDatParser.Time=Data/Hora BitTorrentResumeDatParser.LastSeenCompleteDate=Última vez visto completo BitTorrentResumeDatParser.SeedTime=Tempo semeando (s) BitTorrentResumeDatParser.RunTime=Tempo executando (s) +BitTorrentResumeDatParser.InfoHash=InfoHash +BitTorrentResumeDatParser.FilesFoundInCase=Arquivos Localizados no Caso +BitTorrentResumeDatParser.TorrentFoundInCase=Torrent Localizado no Caso +BitTorrentResumeDatParser.Yes=Sim TorrentFileDatParser.DateFormat=dd/MM/yyyy HH:mm:ss TorrentFileDatParser.FullPath=Caminho completo TorrentFileDatParser.FileSize=Tamanho do arquivo (Bytes) @@ -362,6 +366,13 @@ TorrentFileDatParser.NumberOfPieces=Número de partes TorrentFileDatParser.Piece=Parte TorrentFileDatParser.PieceLength=Tamanho da partes TorrentFileDatParser.IncompleteWarning=Arquivo incompleto. Algumas das informações podem estar incorretas. Por favor, verifique. +TorrentFileDatParser.File=Arquivo +TorrentFileDatParser.FileFoundInCase=Arquivo Localizado no Caso +TorrentFileDatParser.FilesFoundInCase=Arquivos Localizados no Caso +TorrentFileDatParser.PathInCase=Caminho do Item Localizado no Caso +TorrentFileDatParser.Yes=Sim +TorrentFileDatParser.ConfirmedPieces=Partes confirmadas +TorrentFileDatParser.AtOffset=a partir do offset TelegramContact.ContactID=ID do Contato: TelegramContact.FirstName=Nome: TelegramContact.LastName=Sobrenome: diff --git a/iped-app/resources/localization/iped-properties_fr_FR.properties b/iped-app/resources/localization/iped-properties_fr_FR.properties new file mode 100644 index 0000000000..3456975abf --- /dev/null +++ b/iped-app/resources/localization/iped-properties_fr_FR.properties @@ -0,0 +1,13 @@ +accessed=consulté +category=catégorie +content=contenu +created=créé +deleted=supprimé +modified=modifié +changed=méta changé +name=nom +path=emplacement +size=taille +type=type +nudityScore=taux de nudité +nudityClass=classement de nudité \ No newline at end of file diff --git a/iped-app/resources/localization/iped-utils-messages_fr_FR.properties b/iped-app/resources/localization/iped-utils-messages_fr_FR.properties new file mode 100644 index 0000000000..f5676eee44 --- /dev/null +++ b/iped-app/resources/localization/iped-utils-messages_fr_FR.properties @@ -0,0 +1,4 @@ +IOUtil.ConfirmOpening=Êtes-vous sur de vouloir ouvrir ou exécuter +IOUtil.ConfirmOpening.Unknown=inconnu +SelectImage.ImageNotFound=Preuve introuvable :\ +SelectImage.NewImgPath=Sélectionner un nouveau chemin pour diff --git a/iped-app/resources/localization/iped-viewer-messages.properties b/iped-app/resources/localization/iped-viewer-messages.properties index 6e78c4aa65..290292322e 100644 --- a/iped-app/resources/localization/iped-viewer-messages.properties +++ b/iped-app/resources/localization/iped-viewer-messages.properties @@ -26,6 +26,7 @@ MetadataViewer.AdvancedProps=Advanced Properties MetadataViewer.BasicProps=Basic Properties MetadataViewer.Metadata=Metadata MetadataViewer.TabTitle=Metadata +MetadataViewer.DateFormat=MM/dd/yyyy HH:mm:ss z NoJavaFXViewer.Warn=Viewing not supported. Update Java to 7u06 or newer. TiffViewer.InvalidPage=is not a valid page number.\nPlease enter a number between 1 and\ TiffViewer.Page=\ Page\ diff --git a/iped-app/resources/localization/iped-viewer-messages_de_DE.properties b/iped-app/resources/localization/iped-viewer-messages_de_DE.properties index e22054c09b..a4972dd7a6 100644 --- a/iped-app/resources/localization/iped-viewer-messages_de_DE.properties +++ b/iped-app/resources/localization/iped-viewer-messages_de_DE.properties @@ -5,7 +5,7 @@ EmailViewer.Attachments=Anhänge EmailViewer.Bcc=Bcc EmailViewer.Cc=Cc EmailViewer.Date=Datum -EmailViewer.DateFormat=MM/dd/yyyy HH:mm:ss +EmailViewer.DateFormat=dd/MM/yyyy HH:mm:ss EmailViewer.EmbeddedMessage=eingebundene Nachricht EmailViewer.From=From EmailViewer.NotFound=(Nicht gefunden) @@ -26,6 +26,7 @@ MetadataViewer.AdvancedProps=Erweitert MetadataViewer.BasicProps=Allgemein MetadataViewer.Metadata=Metadaten MetadataViewer.TabTitle=Metadaten +MetadataViewer.DateFormat=dd/MM/yyyy HH:mm:ss z NoJavaFXViewer.Warn=Vorschau nicht unterstützt. Java auf Version 7u06 oder neuer aktualisieren. TiffViewer.InvalidPage=ist keine gültige Seitennummer.\nBitte eine Zahl eingeben zwischen 1 und\ TiffViewer.Page=\ Seite\ diff --git a/iped-app/resources/localization/iped-viewer-messages_es_AR.properties b/iped-app/resources/localization/iped-viewer-messages_es_AR.properties index 3d3e68519f..215b3fe405 100644 --- a/iped-app/resources/localization/iped-viewer-messages_es_AR.properties +++ b/iped-app/resources/localization/iped-viewer-messages_es_AR.properties @@ -5,7 +5,7 @@ EmailViewer.Attachments=Archivos adjuntos EmailViewer.Bcc=Bcc EmailViewer.Cc=Cc EmailViewer.Date=Fecha -EmailViewer.DateFormat=MM/dd/aaaa HH:mm:ss +EmailViewer.DateFormat=dd/MM/yyyy HH:mm:ss EmailViewer.EmbeddedMessage=Mensaje incrustado EmailViewer.From=Desde EmailViewer.NotFound=(No encontrado) @@ -26,6 +26,7 @@ MetadataViewer.AdvancedProps=Propiedades avanzadas MetadataViewer.BasicProps=Propiedades básicas MetadataViewer.Metadata=Metadatos MetadataViewer.TabTitle=Metadatos +MetadataViewer.DateFormat=dd/MM/yyyy HH:mm:ss z NoJavaFXViewer.Warn=Visualización no compatible. Actualice Java a 7u06 o posterior. TiffViewer.InvalidPage=no es un número de página válido.\nPor favor ingrese un número entre 1 y\ TiffViewer.Page=\ Página\ diff --git a/iped-app/resources/localization/iped-viewer-messages_fr_FR.properties b/iped-app/resources/localization/iped-viewer-messages_fr_FR.properties new file mode 100644 index 0000000000..3dadcc84e3 --- /dev/null +++ b/iped-app/resources/localization/iped-viewer-messages_fr_FR.properties @@ -0,0 +1,123 @@ +ATextViewer.TabName=Texte +MultiViewer.TabName=Prévisualisation +EmailViewer.AttachedEmail=E-mail en pièce jointe.eml +EmailViewer.Attachments=Pièces jointes +EmailViewer.Bcc=Bcc +EmailViewer.Cc=Cc +EmailViewer.Date=Date +EmailViewer.DateFormat=dd/MM/yyyy HH:mm:ss +EmailViewer.EmbeddedMessage=Message intégré +EmailViewer.From=De +EmailViewer.NotFound=(Non trouvé) +EmailViewer.Subject=Sujet +EmailViewer.To=À +EmailViewer.UnNamed=[Anonyme] +ExternalViewer.Open=Cliquer ici pour visualiser le fichier en surbrillance +HitsTableModel.ContentHits=Résultats dans le contenu +HtmlLinkViewer.AttachNotFound=Pièce jointe non trouvée \! +HtmlViewer.OpenExternally=Ouvert à l'extérieur +HtmlViewer.TooBigToOpen=Fichier trop volumineux pour être ouvert en interne \! +ImageViewer.Blur=Activer/Dasactiver le filtre "Flou" dans la visionneuse (utiliser Ctrl+Q pour tout flouter) +ImageViewer.Copy=Copier l'image de la visionneuse +ImageViewer.GrayScale=Activer/Dasactiver le filtre "Grisé" dans la visionneuse (utiliser Ctrl+W for pour tout griser) +LibreOfficeViewer.RestartingViewer=Redémarrez la visionneuse... +LOExtractor.DecompressingLO=Décompresser LibreOffice... +MetadataViewer.AdvancedProps=Propriétés avancées +MetadataViewer.BasicProps=Propriétés de base +MetadataViewer.Metadata=Métadonnées +MetadataViewer.TabTitle=Métadonnées +MetadataViewer.DateFormat=dd/MM/yyyy HH:mm:ss z +NoJavaFXViewer.Warn=Affichage non pris en charge. Mettre à jour Java en version 7u06 ou supérieure. +TiffViewer.InvalidPage=Numéro de page non valide.\nMerci de saisir un nombre entre 1 et\ +TiffViewer.Page=\ Page\ +PDFViewer.OpenError=ERREUR : Impossible d'ouvrir le fichier PDF ! +MsgViewer.OpenError=ERREUR : Impossible d'ouvrir le message ! +HexViewerPlus.TabName=Hex +HexViewerPlus.appName=Hex Viewer Plus +HexViewerPlus.HvpFileSettings=Paramètres de Hex Viewer Plus +HexViewerPlus.position=Position +HexViewerPlus.relative=Relative +HexViewerPlus.charset=Jeu de caractères +HexViewerPlus.selection=Selection +HexViewerPlus.to=à +HexViewerPlus.settings=Paramètres +HexViewerPlus.hit=Élément trouvé +HexViewerPlus.hits=Eléments trouvés +HexViewerPlus.of=de +HexViewerPlus.search=ÉRechercher +HexViewerPlus.nextHit=Élément trouvé suivant +HexViewerPlus.preHit=Élément trouvé précédent +HexViewerPlus.goToHit=Aller à l'élément trouvé +HexViewerPlus.goToPosition=Aller à la position +HexViewerPlus.selectBlock=Selectionner le Bloc +HexViewerPlus.selectAll=Tout sélectionner +HexViewerPlus.copyHex=Copier l'Hexadecimal +HexViewerPlus.copyText=Copier le Texte +HexViewerPlus.options=Options +HexViewerPlus.selectColor=Choisir une couleur +HexViewerPlus.codeArea=Code de la zone +HexViewerPlus.header=Entête +HexViewerPlus.layout=Mise en page +HexViewerPlus.cursor=Curseur +HexViewerPlus.mode=Mode +HexViewerPlus.font=Police de caractères +HexViewerPlus.size=Taille +HexViewerPlus.blink=Clignoter +HexViewerPlus.bytesPerLine=Octets par ligne +HexViewerPlus.cursorColor=Couleur du curseur +HexViewerPlus.fontColor=Couleur de la police de caractères +HexViewerPlus.backGroundColor=Couleur du fond +HexViewerPlus.selectionCharactersMirror=Selection de caractères - Miroir +HexViewerPlus.selectionCharactersMain=Selection de caractères - Principal +HexViewerPlus.searchHitsFoundMatch=Recherche dans les éléments trouvés - Correspondance trouvée +HexViewerPlus.searchHitsCurrentMatch=Recherche dans les éléments trouvés - En cours +HexViewerPlus.loadDefault=Charger les paramètres par défaut +HexViewerPlus.saveDefault=Enregistrer les paramètres par défaut +HexViewerPlus.close=Cloturer +HexViewerPlus.ok=OK +HexViewerPlus.cancel=Annuler +HexViewerPlus.hexLowerCase=Hexadecimal minuscule +HexViewerPlus.showHeader=Afficher les entêtes +HexViewerPlus.showLines=Afficher les Lignes +HexViewerPlus.lineBreak=Fin de Ligne +HexViewerPlus.showAllCharacters=Afficher tous les caractères +HexViewerPlus.loadFile=Charger le fichier +HexViewerPlus.saveFile=Sauvegarder le fichier +HexViewerPlus.failOpenFile=Echec d'ouverture du fichier ! +HexViewerPlus.failSaveFile=Erreur d'enregistrement du fichie r! +HexViewerPlus.yes=Oui +HexViewerPlus.no=Non +HexViewerPlus.overWriteFile=existe déjà. Voulez vous le remplacer ? +HexViewerPlus.select=Selection +HexViewerPlus.type=Type +HexViewerPlus.interval=Intervalle +HexViewerPlus.invalidPosition=IPosition non valide ! +HexViewerPlus.startPosition=Position de départ +HexViewerPlus.endPosition=Position d'arrivée +HexViewerPlus.format=Format +HexViewerPlus.hexadecimal=Hexadécimal +HexViewerPlus.decimal=Décimal +HexViewerPlus.octal=Octal +HexViewerPlus.invalidStartPosition=Position de départ non valide ! +HexViewerPlus.invalidSize=Taille invalide ! +HexViewerPlus.invalidEndPosition=Position d'arrivée non valide ! +HexViewerPlus.start=Démarrer +HexViewerPlus.invalidHit=Elément trouvé invalide ! +HexViewerPlus.text=Texte +HexViewerPlus.all=Tous +HexViewerPlus.max=Maximum +HexViewerPlus.caseSensitive=Respecter la casse +HexViewerPlus.invalidSearchText=Texte de recherche invalide ! +HexViewerPlus.invalidHexadecimalText=Hexadecimal de recherche invalide ! +HexViewerPlus.invalidMax=Maximum invalide ! +HexViewerPlus.invalidMaxLessThen=Maximum invalide. Inférieur ou égal à\ +HexViewerPlus.invalid=invalide +HexViewerPlus.showPositionBar=Afficher la barre de Position +HexViewerPlus.showSelectionBar=Afficher la barre de Sélection +HexViewerPlus.showLineNumberBackground=Fusionner en-tête et ligne avec la mise en page +HexViewerPlus.headerLineBackground=En-tête et numéros de ligne +ProgressDialog.Cancel=Abandonner +ProgressDialog.Progress=En cours +ProgressDialog.Searching=Recherche... +ReferenceViewer.FileNotFound=Fichier de référence introuvable :\ +ReferenceViewer.NotSupported=Type de fichier non supporté :\ diff --git a/iped-app/resources/localization/iped-viewer-messages_it_IT.properties b/iped-app/resources/localization/iped-viewer-messages_it_IT.properties index 0dc7dceea4..03f411b6c3 100644 --- a/iped-app/resources/localization/iped-viewer-messages_it_IT.properties +++ b/iped-app/resources/localization/iped-viewer-messages_it_IT.properties @@ -26,6 +26,7 @@ MetadataViewer.AdvancedProps=Proprietà avanzate MetadataViewer.BasicProps=Proprietà base MetadataViewer.Metadata=Metadati MetadataViewer.TabTitle=Metadati +MetadataViewer.DateFormat=dd/MM/yyyy HH:mm:ss z NoJavaFXViewer.Warn=Visualizzazione non supportata. Aggiorna Java alla versione 7u06 o successiva. TiffViewer.InvalidPage=non è un numero di pagina valido.\nInserisci un numero tra 1 e\ TiffViewer.Page=\ Pagina\ diff --git a/iped-app/resources/localization/iped-viewer-messages_pt_BR.properties b/iped-app/resources/localization/iped-viewer-messages_pt_BR.properties index eb5dd8201d..489d4d97e8 100644 --- a/iped-app/resources/localization/iped-viewer-messages_pt_BR.properties +++ b/iped-app/resources/localization/iped-viewer-messages_pt_BR.properties @@ -26,6 +26,7 @@ MetadataViewer.AdvancedProps=Propriedades Avançadas MetadataViewer.BasicProps=Propriedades Básicas MetadataViewer.Metadata=Metadados MetadataViewer.TabTitle=Metadados +MetadataViewer.DateFormat=dd/MM/yyyy HH:mm:ss z NoJavaFXViewer.Warn=Visualização não suportada. Atualize o Java para a versão 7u06 ou superior TiffViewer.InvalidPage=não é uma página válida. Insira um valor entre 1 e\ TiffViewer.Page=\ Página\ diff --git a/iped-app/resources/root/help/Help_fr-FR.htm b/iped-app/resources/root/help/Help_fr-FR.htm new file mode 100644 index 0000000000..26a058a2b5 --- /dev/null +++ b/iped-app/resources/root/help/Help_fr-FR.htm @@ -0,0 +1,121 @@ + + + + + IPED Aide + + + + + +

IPED +Aide

+

Syntaxe utilisée pour les recherches:
+

+

Pour +ouvrir l'interface d'analyse, vous avez besoin d'un système +d'exploitation 64 bits. Si votre cas ou votre rapport est stocké +sur un disque optique, l’analyse peut devenir lente. Si tel est +le cas, copiez l'intégralité du cas sur un disque dur +local, à partir duquel l'application d'analyse doit être +ouverte.

+
+La recherche par mot-clé recherche les termes dans le nom de fichier et le contenu des fichiers texte, comme Word, Excel, PDF, les e-mails, les pages Internet, les chats, etc. Si elle est activée, la technologie OCR (Optical Character Recognition) est utilisée pour rechercher du texte dans les fichiers image. Cependant, certains résultats peuvent ne pas être trouvés dans des images de mauvaise qualité ou de faible résolution, ou si les polices sont petites ou peu courantes. +

+La recherche par mot-clé ne différencie pas les majuscules ou les accents des lettres. Mais il est recommandé d'inclure des accents dans les recherches, afin que les mots-clés soient correctement mis en évidence dans l'onglet « Aperçu ». Il n'est pas recommandé de rechercher des mots-clés courants ou très courts, comme OF. Vous trouverez ci-dessous quelques exemples de recherche. 

+ +

+
    +
  • 1. suspect
    +Recherchez + les fichiers contenant le terme exact suspect. + Les dossiers contenant suspects + ne seront pas trouvés.

    +
  • 2. suspect?
    +Recherchez + des fichiers contenant des mots commençant par suspect + suivis d'une lettre à la fin, comme suspects.

    +
  • 3. suspect*
    +Recherchez + des fichiers contenant des mots commençant par suspect + avec ou sans suffixe, comme suspect, + suspects + et suspect.

    +
  • 4. Sicrano~
    +Recherchez + des fichiers contenant des mots égaux ou similaires à + sicrano, + comme siclano, + cicrano + et ciclano. + C’est plus long, + mais son utilisation est recommandée pour rechercher du texte + dans les images (si l'OCR a été activé). +

    +
  • 5. "Thomas + Edson"
    +Recherchez l’expression + exacte Thomas Edson. + Il n'est pas possible d'utiliser * ? ~ entre guillemets.

    +
  • 6. Thomas Edson
    +Recherchez + des fichiers contenant l’un des mots Thomas + ou Edson. + Cela équivaut à rechercher Thomas + OU Edson

    +
  • 7. Thomas AND + Edson
    +Rechercher Thomas et Edson +

    +
  • 8. corruption + -paiement
    +Recherchez des fichiers + contenant corruption + mais sans référence à un paiement. + Cela équivaut à rechercher corruption + ET NON un paiement.

    +
  • 9. (Thomas Edson) && + paiement
    +Recherchez des fichiers + contenant un paiement ET l'un de Thomas OU Edson

    +
  • 10. "Thomas + Edson"~5
    +Recherche de fichiers + contenant Thomas au plus 5 mots de distance d'Edson. +

    +
  • 11. (Thomas Edson + John)@2
    +Recherchez des fichiers + contenant au moins deux termes de l'ensemble. +

    +
  • 12. nom:reçu
    + + Recherchez les fichiers contenant un reçu en son nom propre.
    + Toutes les propriétés affichées dans le gestionnaire de colonnes peuvent être utilisées, à l'exception actuellement de "bookmark" et "score". +

    +
+
    +
  • 13. size:[5000 TO + *]
    +Recherchez des fichiers d'une taille + supérieure ou égale à 5 000 octets inclus. + Utilisez {} au lieu de [] pour exclure la valeur. +

    +
  • 14. modifié:[2015-01-31 + TO 2015-03-31T12\:59\:59Z]
    +Recherche des + fichiers dont la date de modification est comprise entre 0h00 du + 31/01/2015 et 12h59:59 du 31/03/2015. +

    +
  • 15. /<0-17>y(r|o)/
    +Recherchez + une expression régulière, délimitée par + 2 barres obliques. Cela ne fonctionne que pour les lettres indexées + (alphanumériques par défaut). +

    +
+
Pour plus d'informations sur la syntaxe de recherche, consulter: https://lucene.apache.org/core/9_2_0/queryparser/org/apache/lucene/queryparser/flexible/standard/StandardQueryParser.html.
+ + \ No newline at end of file diff --git a/iped-app/resources/root/htmlreport/fr-FR/caseinformation.htm b/iped-app/resources/root/htmlreport/fr-FR/caseinformation.htm new file mode 100644 index 0000000000..968e012a3e --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/caseinformation.htm @@ -0,0 +1,39 @@ + + + + Nom du service + + + + +
+ + + + + + + + + + + + + + + + + + +
%HEADER%
Rapport%REPORT%
Date%REPORT_DATE%
Numéro de dossier%RECORD%
Analyste/Expert(s) + %EXAMINERS% +
Références + Numéro du cas: %INVESTIGATION%
+ Formulaire de demande: %REQUEST_DOC% - date %REQUEST_DATE%
+ Requérant: %REQUESTER%
+
Scellé analysé + %EVIDENCE% +
+
+ + diff --git a/iped-app/resources/root/htmlreport/fr-FR/contents.htm b/iped-app/resources/root/htmlreport/fr-FR/contents.htm new file mode 100644 index 0000000000..c4cf2ac1d4 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/contents.htm @@ -0,0 +1,33 @@ + + + + IPED Rapport + + + + + + + + diff --git a/iped-app/resources/root/htmlreport/fr-FR/report.htm b/iped-app/resources/root/htmlreport/fr-FR/report.htm new file mode 100644 index 0000000000..d2b136b06e --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/report.htm @@ -0,0 +1,16 @@ + + + + IPED Rapport + + + + + + + <body> + </body> + + + + diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/background.jpg b/iped-app/resources/root/htmlreport/fr-FR/res/background.jpg new file mode 100644 index 0000000000..576c5c95a1 Binary files /dev/null and b/iped-app/resources/root/htmlreport/fr-FR/res/background.jpg differ diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/bookmarks.css b/iped-app/resources/root/htmlreport/fr-FR/res/bookmarks.css new file mode 100644 index 0000000000..633ab1c4a4 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/bookmarks.css @@ -0,0 +1,30 @@ +/* CSS Document */ + +/* This css contains definitions that are used excusively by + the Bookmarks and Registry report sections */ + +/* .bkmkSeparator class selector is used in conjuction with + .bkmkValue class selector which defined the border-bottom-style::inset + and border-bottom-width:thin properties for .bkmkSeparator; + .bkmkValue class selector is defined in Common.css */ +.bkmkSeparator +{ + border-top-style:double; + clear:both; +} +.bkmkLblFileSel +{ + font-weight:bold; + text-decoration:underline; + margin-top:12pt; + clear:both; +} +.bkmkColLeft +{ + float:left; + width:185px; +} +.bkmkColRight +{ + float:left; +} \ No newline at end of file diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/common.css b/iped-app/resources/root/htmlreport/fr-FR/res/common.css new file mode 100644 index 0000000000..0463783765 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/common.css @@ -0,0 +1,120 @@ +/* CSS Document */ + +/* This css contains definitions that are used by all + the generated report html pages (except Index.html) + All of the report sections used one or more of the + following definitions */ + +/* The body selector applies to all the pages, thus + if you want to change font, font-size etc, change + the properties here */ +body +{ + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; +} +/* all html table set to no border */ +table +{ + border:none; +} + +/* define color of light gray used within header etc */ +.clrBkgrnd +{ + background-color:#F2F0E6 +} + +/* define a value used within bookmark section */ +.bkmkValue +{ + border-bottom-style:inset; + border-bottom-width:thin; +} + +/* define all the Heading properties */ +.contentHead, .bkmkColHead, .bkmkLblFiles +{ + border-bottom:groove; + border-top:groove; + background-color:#D2C8AE; + text-align:left; + font-size: 20px; + color:#21536A +} + +/* .labelBorderless used in conjuction with .clrBkgrnd + for the background-color property */ +.labelBorderless +{ + font-weight:bold; + text-align:left; +} + +/* all graohic numbers definition */ +.graphicNumbers +{ + font-weight:bold +} + +/* define all link properties */ +a +{ + text-decoration:none; +} +a:hover +{ + text-decoration:underline; +} + +th.columnHead +{ + border-bottom:double; + border-top:ridge; + text-align:left; + background-color:#D2C8AE +} + +td +{ + border-left:none; + border-right:none; + border-top:none +} +/* td.label used in conjuction with .clrBkgrnd + for the background-color property */ +td.label +{ + font-weight:bold; + text-align:left; + border-right:solid; + border-right-width:thin; +} +/* td.graphicNumber used in conjuction with .clrBkgrnd + and graphicNumbers; For the background-color property + and font-weight property*/ +td.graphicNumber +{ + text-align:center; + border:groove; +} +td.graphicPath +{ + border:none; +} +td.graphic +{ + border:solid; + border-width:thin +} + +/*td.screenCaptureDesc used in screen captures section*/ +td.screenCaptureDesc +{ + text-align:center; +} + + +div.row, p { + clear:both; +} diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/contents.css b/iped-app/resources/root/htmlreport/fr-FR/res/contents.css new file mode 100644 index 0000000000..41c6908db8 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/contents.css @@ -0,0 +1,66 @@ +body { + margin: 0; + color: black; + background-color: rgb(52,102,153); + background-image: url('background.jpg'); + background-repeat: repeat-x; +} + +div#menu { + font-family: Verdana, Arial, Tahoma; + padding-top: 10px; + padding-left: 10px; +} + +div#emblema { + padding-left: 20px; +} + +.MenuText:link, .MenuText:visited, .MenuText:active { + font-family: 'Verdana'; + font-size: 8pt; + color: rgb(255,255,192); + text-decoration: none; +} + +.MenuText:hover { + text-decoration: underline; +} + +.SmallText { + font-size: 10pt; + font-weight: bold; + color: white; + text-decoration: none; +} + +.SmallText1 { + font-size: 9pt; + font-weight: bold; + color: white; + text-decoration: none; +} + +.SmallText2 { + font-size: 9pt; + font-weight: bold; + color: white; + text-decoration: none; +} + +.SmallText2:link, .SmallText2:visited, .SmallText2:active { + color: white; + text-decoration: none; +} + +.SmallText2:hover { + color: rgb(255,255,192); + text-decoration: underline; +} + +.SmallText3 { + font-size: 8pt; + font-weight: bold; + color: white; + text-decoration: none; +} \ No newline at end of file diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/estilo.css b/iped-app/resources/root/htmlreport/fr-FR/res/estilo.css new file mode 100644 index 0000000000..7c61ab39bd --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/estilo.css @@ -0,0 +1,29 @@ +* { + font-family: Verdana, Arial, Tahoma; + font-size: 10pt; +} + +body { + margin: 0; + color: black; + background-color: white; +} + +img { + border: 0; +} + +a { + color: rgb(0, 102, 204); + background-color: inherit; + text-decoration: none; +} +a:hover { + color: rgb(153, 153, 153); + background-color: inherit; + text-decoration: underline; +} + +table * { + vertical-align: top; +} \ No newline at end of file diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/header.gif b/iped-app/resources/root/htmlreport/fr-FR/res/header.gif new file mode 100644 index 0000000000..a9b6bd8fca Binary files /dev/null and b/iped-app/resources/root/htmlreport/fr-FR/res/header.gif differ diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/info.css b/iped-app/resources/root/htmlreport/fr-FR/res/info.css new file mode 100644 index 0000000000..c17e24262d --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/info.css @@ -0,0 +1,9 @@ +table.info { + width: 90%; + +} + +table.info td { + border: 1px solid rgb(200,200,200); + padding: 5px; +} \ No newline at end of file diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/lupa.png b/iped-app/resources/root/htmlreport/fr-FR/res/lupa.png new file mode 100644 index 0000000000..bc18b4226d Binary files /dev/null and b/iped-app/resources/root/htmlreport/fr-FR/res/lupa.png differ diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/main.css b/iped-app/resources/root/htmlreport/fr-FR/res/main.css new file mode 100644 index 0000000000..0d055c3836 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/main.css @@ -0,0 +1,21 @@ +div#conteudo { + margin-left: 20px; + margin-right: 10px; + margin-top: 10px; + width: 90%; + text-align: left; +} + +hr { + margin-top: 15px; + margin-bottom: 0px; +} + +.HeaderText { + font-size: 25px; + color: #034D86; + font-family: 'Arial Black'; + text-decoration: none; + border-bottom: 4px solid rgb(200,200,200); + width: 80%; +} diff --git a/iped-app/resources/root/htmlreport/fr-FR/res/navigation.css b/iped-app/resources/root/htmlreport/fr-FR/res/navigation.css new file mode 100644 index 0000000000..4ddcc3ea51 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/res/navigation.css @@ -0,0 +1,25 @@ +/* CSS Document */ + +/* This css contains definitions used excusively by + Table_of_Contents.html; These definitions provided the + behavior for the button style links as seen on the left + panel of the html report */ + +a.sectionLinks:link, a.sectionLinks:visited +{ + display: block; + border-top: 1px solid #ffffff; + border-bottom: 1px solid #cccccc; + background-image: url(bg_nav.jpg); + font-weight: bold; + padding: 3px 0px 3px 10px; + color: #21536A; +} +a.sectionLinks:hover +{ + border-top: 1px solid #cccccc; + background-color: #e2e4e1; + background-image: none; + font-weight: bold; + text-decoration: none; +} \ No newline at end of file diff --git a/iped-app/resources/root/htmlreport/fr-FR/templates/arq.html b/iped-app/resources/root/htmlreport/fr-FR/templates/arq.html new file mode 100644 index 0000000000..4fc814a4c9 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/templates/arq.html @@ -0,0 +1,18 @@ + + + + +Favoris + +
+%PAGS% + +
%CATEGORY%
Commentaires: %COMMENTS%
+Nombre de fichiers: %TOTALCOUNT% +
Fichiers
+%ITEMS% +%PAGS% +

+ diff --git a/iped-app/resources/root/htmlreport/fr-FR/templates/item.html b/iped-app/resources/root/htmlreport/fr-FR/templates/item.html new file mode 100644 index 0000000000..8347f9d0f1 --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/templates/item.html @@ -0,0 +1,12 @@ + +
Nom%NAME%
+
Emplacement%PATH%
+
Type de fichier%TYPE%
+
Taille%SIZE% Bytes
+
Date de Crétion%CREATED%
+
Date de Modification%MODIFIED%
+
Date de Consultation%ACCESSED%
+
Supprimé%DELETED%
+
Récupéré%CARVED%
+
Hash%HASH%
+
Exporté comme%EXPORTED%
diff --git a/iped-app/resources/root/htmlreport/fr-FR/templates/perito.html b/iped-app/resources/root/htmlreport/fr-FR/templates/perito.html new file mode 100644 index 0000000000..c4e446178a --- /dev/null +++ b/iped-app/resources/root/htmlreport/fr-FR/templates/perito.html @@ -0,0 +1 @@ +%EXAMINER%
ANALYSTE \ No newline at end of file diff --git a/iped-app/resources/scripts/tasks/RefineCategoryTask.js b/iped-app/resources/scripts/tasks/RefineCategoryTask.js index 98512fb122..35d07da9fb 100644 --- a/iped-app/resources/scripts/tasks/RefineCategoryTask.js +++ b/iped-app/resources/scripts/tasks/RefineCategoryTask.js @@ -148,6 +148,32 @@ function process(e){ } } + // Calls sub-categories + if (mime.equals("application/x-ufed-call")) { + source = e.getMetadata().get("ufed:Source"); + if (source == null) { + e.setCategory("Phone Calls"); + } else { + source = source.toLowerCase(); + if (source.contains("whatsapp")) { + e.setCategory("WhatsApp Calls"); + } else if (source.contains("facebook")) { + e.setCategory("Facebook Calls"); + } else if (source.contains("discord")) { + e.setCategory("Discord Calls"); + } else if (source.contains("threema")) { + e.setCategory("Threema Calls"); + } else if (source.contains("telegram")) { + e.setCategory("Telegram Calls"); + } else if (source.contains("signal")) { + e.setCategory("Signal Calls"); + } else { + // New sub-categories may be created from other phone call apps handled by UFED + e.setCategory("Other Calls"); + } + } + } + // Usually, conditions that overwrite the category (using setCategory()) // should go before the ones that add other categories (using addCategory()). diff --git a/iped-app/resources/scripts/tasks/WhisperProcess.py b/iped-app/resources/scripts/tasks/WhisperProcess.py new file mode 100644 index 0000000000..a53203bc47 --- /dev/null +++ b/iped-app/resources/scripts/tasks/WhisperProcess.py @@ -0,0 +1,113 @@ +import sys +import numpy +stdout = sys.stdout +sys.stdout = sys.stderr + +terminate = 'terminate_process' +model_loaded = 'model_loaded' +library_loaded = 'library_loaded' +finished = 'transcription_finished' +ping = 'ping' + +def main(): + + modelName = sys.argv[1] + deviceNum = int(sys.argv[2]) + threads = int(sys.argv[3]) + language = sys.argv[4] + compute_type = sys.argv[5] + batch_size = int(sys.argv[6]) + + if language == 'detect': + language = None + + try: + import whisperx + whisperx_found = True + except: + import faster_whisper + whisperx_found = False + + print(library_loaded, file=stdout, flush=True) + print('whisperx' if whisperx_found else 'faster_whisper', file=stdout, flush=True) + + import GPUtil + cudaCount = len(GPUtil.getGPUs()) + + print(str(cudaCount), file=stdout, flush=True) + + if cudaCount > 0: + deviceId = 'cuda' + else: + deviceId = 'cpu' + deviceNum = 0 + + try: + if whisperx_found: + model = whisperx.load_model(modelName, device=deviceId, device_index=deviceNum, threads=threads, compute_type=compute_type, language=language) + else: + model = faster_whisper.WhisperModel(modelName, device=deviceId, device_index=deviceNum, cpu_threads=threads, compute_type=compute_type) + + except Exception as e: + if deviceId != 'cpu': + # loading on GPU failed (OOM?), try on CPU + print('FAILED to load model on GPU, OOM? Fallbacking to CPU...', file=sys.stderr) + deviceId = 'cpu' + if compute_type == 'float16': # not supported on CPU + compute_type = 'int8' + if whisperx_found: + model = whisperx.load_model(modelName, device=deviceId, device_index=deviceNum, threads=threads, compute_type=compute_type, language=language) + else: + model = faster_whisper.WhisperModel(modelName, device=deviceId, cpu_threads=threads, compute_type=compute_type) + else: + raise e + + print(model_loaded, file=stdout, flush=True) + print(deviceId, file=stdout, flush=True) + + while True: + + line = input() + + if line == terminate: + break + if line == ping: + print(ping, file=stdout, flush=True) + continue + + transcription = '' + logprobs = [] + try: + if whisperx_found: + audio = whisperx.load_audio(line) + result = model.transcribe(audio, batch_size=batch_size, language=language) + for segment in result['segments']: + transcription += segment['text'] + if 'avg_logprob' in segment: + logprobs.append(segment['avg_logprob']) + else: + segments, info = model.transcribe(audio=line, language=language, beam_size=5, vad_filter=True) + for segment in segments: + transcription += segment.text + logprobs.append(segment.avg_logprob) + + except Exception as e: + msg = repr(e).replace('\n', ' ').replace('\r', ' ') + print(msg, file=stdout, flush=True) + continue + + text = transcription.replace('\n', ' ').replace('\r', ' ') + + if len(logprobs) == 0: + finalScore = 0 + else: + finalScore = numpy.mean(numpy.exp(logprobs)) + + print(finished, file=stdout, flush=True) + print(str(finalScore), file=stdout, flush=True) + print(text, file=stdout, flush=True) + + return + +if __name__ == "__main__": + main() diff --git a/iped-app/src/main/java/iped/app/bootstrap/Bootstrap.java b/iped-app/src/main/java/iped/app/bootstrap/Bootstrap.java index 9669b7efd1..8644f3ae0d 100644 --- a/iped-app/src/main/java/iped/app/bootstrap/Bootstrap.java +++ b/iped-app/src/main/java/iped/app/bootstrap/Bootstrap.java @@ -145,10 +145,7 @@ protected void run(String args[]) { classpath += separator + pluginConfig.getPluginFolder().getAbsolutePath() + "/*"; } - // user can't open analysis UI w/ --nogui, so no need to load libreoffice jars - if (!iped.getCmdLineArgs().isNogui()) { - classpath = fillClassPathWithLibreOfficeJars(iped, classpath); - } + classpath = fillClassPathWithLibreOfficeJars(iped, classpath, iped.getCmdLineArgs().isNogui()); String javaBin = "java"; if (SystemUtils.IS_OS_WINDOWS) { @@ -278,14 +275,14 @@ private static List getSystemProperties() { return props; } - private static String fillClassPathWithLibreOfficeJars(Main iped, String classpath) + private static String fillClassPathWithLibreOfficeJars(Main iped, String classpath, boolean isNogui) throws URISyntaxException, IOException { System.setProperty(IOfficeApplication.NOA_NATIVE_LIB_PATH, new File(iped.getRootPath(), "lib/nativeview").getAbsolutePath()); LibreOfficeFinder loFinder = new LibreOfficeFinder(new File(iped.getRootPath())); - if (loFinder.getLOPath() != null) { + if (loFinder.getLOPath(isNogui) != null) { List jars = new ArrayList<>(); - UNOLibFinder.addUNOJars(loFinder.getLOPath(), jars); + UNOLibFinder.addUNOJars(loFinder.getLOPath(isNogui), jars); for (File jar : jars) { classpath += separator + jar.getCanonicalPath(); } diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index d554d2161f..2e93746f9a 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -562,7 +562,6 @@ public void createGUI() { resultsTable.setDefaultRenderer(String.class, new TableCellRenderer()); resultsTable.setShowGrid(false); resultsTable.setAutoscrolls(false); - ((JComponent) resultsTable.getDefaultRenderer(Boolean.class)).setOpaque(true); FilterTableHeaderController.init(resultsTable.getTableHeader()); InputMap inputMap = resultsTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); @@ -1486,8 +1485,9 @@ public void updateIconContainersUI(int size, boolean updateUI) { } private void updateIconContainerUI(JComponent comp, int size, boolean updateUI) { + JTable table = null; if (comp instanceof JTable && comp != gallery) { - JTable table = (JTable) comp; + table = (JTable) comp; table.setRowHeight(size); // Set bookmark icons column width based on current icon size @@ -1500,6 +1500,10 @@ private void updateIconContainerUI(JComponent comp, int size, boolean updateUI) if (updateUI) { comp.updateUI(); } + if (table != null) { + // Fix the background of boolean columns (with a CheckBox) + ((JComponent) table.getDefaultRenderer(Boolean.class)).setOpaque(true); + } } @Override diff --git a/iped-app/src/main/java/iped/app/ui/IconManager.java b/iped-app/src/main/java/iped/app/ui/IconManager.java index 7db730872c..7a24107fa5 100644 --- a/iped-app/src/main/java/iped/app/ui/IconManager.java +++ b/iped-app/src/main/java/iped/app/ui/IconManager.java @@ -40,7 +40,7 @@ */ public class IconManager { - public static final int defaultSize = 16; + public static final int defaultSize = 18; public static final int defaultGallerySize = 24; public static final int defaultCategorySize = 20; @@ -194,6 +194,7 @@ private static Map initMimeToIconMap(int size) { icon = availableIconsMap.get("torrent"); if (icon != null) { mimeIconMap.put("application/x-bittorrent-resume-dat", icon); + mimeIconMap.put("application/x-bittorrent-settings-dat", icon); mimeIconMap.put("application/x-bittorrent", icon); } diff --git a/iped-app/src/main/java/iped/app/ui/ReportDialog.java b/iped-app/src/main/java/iped/app/ui/ReportDialog.java index 5a286609b0..f325003531 100644 --- a/iped-app/src/main/java/iped/app/ui/ReportDialog.java +++ b/iped-app/src/main/java/iped/app/ui/ReportDialog.java @@ -148,6 +148,8 @@ public void updateList() { table = new JTable(tableModel); table.getColumnModel().getColumn(0).setMaxWidth(20); table.getColumnModel().getColumn(2).setMaxWidth(150); + table.setRowHeight(IconManager.getIconSize()); + tableModel.addTableModelListener(this); scrollPane = new JScrollPane(table); diff --git a/iped-app/src/main/java/iped/app/ui/ViewerController.java b/iped-app/src/main/java/iped/app/ui/ViewerController.java index d056ad6e34..852eeb77d7 100644 --- a/iped-app/src/main/java/iped/app/ui/ViewerController.java +++ b/iped-app/src/main/java/iped/app/ui/ViewerController.java @@ -116,7 +116,7 @@ public void run() { URI jarUri = URLUtil.getURL(LibreOfficeViewer.class).toURI(); File moduledir = new File(jarUri).getParentFile().getParentFile(); LibreOfficeFinder loFinder = new LibreOfficeFinder(moduledir); - final String pathLO = loFinder.getLOPath(); + final String pathLO = loFinder.getLOPath(false); if (pathLO != null) { SwingUtilities.invokeAndWait(new Runnable() { @Override diff --git a/iped-app/src/main/java/iped/app/ui/utils/UiIconSize.java b/iped-app/src/main/java/iped/app/ui/utils/UiIconSize.java index bf345544a5..d041bad475 100644 --- a/iped-app/src/main/java/iped/app/ui/utils/UiIconSize.java +++ b/iped-app/src/main/java/iped/app/ui/utils/UiIconSize.java @@ -4,6 +4,7 @@ import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.Date; import java.util.List; import iped.app.ui.IconManager; @@ -14,6 +15,7 @@ public class UiIconSize { private static final String[] keys = new String[] { "CatIconSize", "GalleryIconSize", "TableIconSize" }; private static final String[] comments = new String[] { "for categories", "in the gallery", "in tables and other UI elements" }; + private static final String lastSavedKey = "LastSaved"; private static final int[] defaultSizes = new int[] { IconManager.defaultCategorySize, IconManager.defaultGallerySize, IconManager.defaultSize }; @@ -26,7 +28,7 @@ public static int[] loadUserSetting() { UTF8Properties prop = new UTF8Properties(); prop.load(file); - boolean missing = false; + boolean missing = prop.getProperty(lastSavedKey) == null; for (int i = 0; i < keys.length; i++) { String value = prop.getProperty(keys[i]); if (value != null) { @@ -37,6 +39,11 @@ public static int[] loadUserSetting() { } if (missing) { + for (int i = 0; i < keys.length; i++) { + if (sizes[i] < defaultSizes[i]) { + sizes[i] = defaultSizes[i]; + } + } saveUserSetting(sizes); } } @@ -57,6 +64,7 @@ public static void saveUserSetting(int[] sizes) { l.add(keys[i] + " = " + sizes[i]); l.add(""); } + l.add(lastSavedKey + " = " + new Date()); Files.write(file.toPath(), l, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); } catch (Exception e) { e.printStackTrace(); diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Discord Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Discord Calls.png new file mode 100644 index 0000000000..2c72a48658 Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Discord Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Facebook Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Facebook Calls.png new file mode 100644 index 0000000000..72513b635e Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Facebook Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Other Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Other Calls.png new file mode 100644 index 0000000000..ca2d8419fc Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Other Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Phone Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Phone Calls.png new file mode 100644 index 0000000000..62ddabd2d5 Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Phone Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Signal Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Signal Calls.png new file mode 100644 index 0000000000..6f46a7705a Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Signal Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Telegram Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Telegram Calls.png new file mode 100644 index 0000000000..ee6ab9fb2c Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Telegram Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/Threema Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/Threema Calls.png new file mode 100644 index 0000000000..90a16721b3 Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/Threema Calls.png differ diff --git a/iped-app/src/main/resources/iped/app/ui/cat/WhatsApp Calls.png b/iped-app/src/main/resources/iped/app/ui/cat/WhatsApp Calls.png new file mode 100644 index 0000000000..d329d59877 Binary files /dev/null and b/iped-app/src/main/resources/iped/app/ui/cat/WhatsApp Calls.png differ diff --git a/iped-engine/src/main/java/iped/engine/config/AudioTranscriptConfig.java b/iped-engine/src/main/java/iped/engine/config/AudioTranscriptConfig.java index 198d73e62b..7e118e70d4 100644 --- a/iped-engine/src/main/java/iped/engine/config/AudioTranscriptConfig.java +++ b/iped-engine/src/main/java/iped/engine/config/AudioTranscriptConfig.java @@ -27,10 +27,14 @@ public class AudioTranscriptConfig extends AbstractTaskPropertiesConfig { private static final String MAX_REQUESTS_KEY = "maxConcurrentRequests"; private static final String MIN_WORD_SCORE = "minWordScore"; public static final String HUGGING_FACE_MODEL = "huggingFaceModel"; + public static final String WHISPER_MODEL = "whisperModel"; public static final String WAV2VEC2_SERVICE = "wav2vec2Service"; + public static final String REMOTE_SERVICE = "remoteServiceAddress"; private static final String GOOGLE_MODEL = "googleModel"; private static final String LANG_AUTO_VAL = "auto"; private static final String SKIP_KNOWN_FILES = "skipKnownFiles"; + private static final String PRECISION = "precision"; + private static final String BATCH_SIZE = "batchSize"; private List languages = new ArrayList<>(); private List mimesToProcess = new ArrayList<>(); @@ -43,9 +47,20 @@ public class AudioTranscriptConfig extends AbstractTaskPropertiesConfig { private int maxConcurrentRequests; private float minWordScore = 0.7f; private String huggingFaceModel; - private String wav2vec2Service; + private String whisperModel; + private String remoteService; private String googleModel; private boolean skipKnownFiles = true; + private String precision = "int8"; + private int batchSize = 1; + + public String getPrecision() { + return precision; + } + + public int getBatchSize() { + return batchSize; + } public boolean getSkipKnownFiles() { return this.skipKnownFiles; @@ -109,8 +124,12 @@ public String getHuggingFaceModel() { return huggingFaceModel; } - public String getWav2vec2Service() { - return wav2vec2Service; + public String getWhisperModel() { + return whisperModel; + } + + public String getRemoteService() { + return remoteService; } public String getGoogleModel() { @@ -144,9 +163,17 @@ public void processProperties(UTF8Properties properties) { if (huggingFaceModel != null) { huggingFaceModel = huggingFaceModel.trim(); } - wav2vec2Service = properties.getProperty(WAV2VEC2_SERVICE); - if (wav2vec2Service != null) { - wav2vec2Service = wav2vec2Service.trim(); + whisperModel = properties.getProperty(WHISPER_MODEL); + if (whisperModel != null) { + whisperModel = whisperModel.strip(); + } + + remoteService = properties.getProperty(REMOTE_SERVICE); + if (remoteService == null) { + remoteService = properties.getProperty(WAV2VEC2_SERVICE); + } + if (remoteService != null) { + remoteService = remoteService.trim(); } googleModel = properties.getProperty(GOOGLE_MODEL); if (googleModel != null) { @@ -165,6 +192,14 @@ public void processProperties(UTF8Properties properties) { if (value != null) { timeoutPerSec = Integer.valueOf(value.trim()); } + value = properties.getProperty(PRECISION); + if (value != null) { + precision = value.trim(); + } + value = properties.getProperty(BATCH_SIZE); + if (value != null) { + batchSize = Integer.parseInt(value.trim()); + } } /** diff --git a/iped-engine/src/main/java/iped/engine/config/ParsersConfig.java b/iped-engine/src/main/java/iped/engine/config/ParsersConfig.java index b3f14e8ebf..7c5b34b333 100644 --- a/iped-engine/src/main/java/iped/engine/config/ParsersConfig.java +++ b/iped-engine/src/main/java/iped/engine/config/ParsersConfig.java @@ -2,11 +2,34 @@ import java.io.File; import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream.Filter; import java.nio.file.Files; import java.nio.file.Path; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + import iped.configuration.Configurable; public class ParsersConfig implements Configurable { @@ -18,6 +41,8 @@ public class ParsersConfig implements Configurable { private static final String PARSER_CONFIG = "ParserConfig.xml"; //$NON-NLS-1$ + public static final String PARSER_DISABLED_ATTR = "iped:disabled"; + private String parserConfigXml; private transient Path tmp; @@ -33,7 +58,53 @@ public boolean accept(Path entry) throws IOException { @Override public void processConfig(Path resource) throws IOException { - parserConfigXml = new String(Files.readAllBytes(resource), StandardCharsets.UTF_8); + if (parserConfigXml == null) { + parserConfigXml = new String(Files.readAllBytes(resource), StandardCharsets.UTF_8); + parserConfigXml = parserConfigXml.trim().replaceFirst("^([\\W]+)<", "<"); + } else { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); + dbf.setNamespaceAware(false); + DocumentBuilder db; + try { + db = dbf.newDocumentBuilder(); + Document doc = db.parse(new InputSource(new StringReader(parserConfigXml))); + Document changedDoc = db.parse(resource.toFile()); + + Element root = changedDoc.getDocumentElement(); + NodeList rootNl = root.getElementsByTagName("parsers").item(0).getChildNodes(); + for (int i = 0; i < rootNl.getLength(); i++) { + Node child = rootNl.item(i); + if (child instanceof Element) { + Element element = (Element) child; + if (element.getTagName().equals("parser")) { + String className = element.getAttribute("class"); + XPath xPath = XPathFactory.newInstance().newXPath(); + String expression = "/properties/parsers/parser[@class='" + className + "']"; + NodeList nlParser = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET); + + expression = "/properties/parsers"; + NodeList nlParsers = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET); + Node newnode = doc.importNode(element, true); + for (int j = 0; j < nlParsers.getLength(); j++) { + for (int k = 0; k < nlParser.getLength(); k++) { + nlParsers.item(j).removeChild(nlParser.item(k)); + } + nlParsers.item(j).appendChild(newnode); + } + } + } + } + + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + parserConfigXml = writer.getBuffer().toString(); + } catch (ParserConfigurationException | SAXException | XPathExpressionException | TransformerException e) { + throw new RuntimeException(e); + } + } } @Override @@ -46,11 +117,34 @@ public void setConfiguration(String config) { parserConfigXml = config; } + public String removeDisabledParsers(String parserConfigXml) { + String[] slices = parserConfigXml.split(PARSER_DISABLED_ATTR + "=\"true\""); + StringBuffer result = new StringBuffer(); + for (int i = 0; i < slices.length; i++) { + String part = slices[i]; + if (i > 0) { + int disabledParserEndIndex = part.indexOf(">"); + if (disabledParserEndIndex == 0 || part.charAt(disabledParserEndIndex - 1) != '/') { + disabledParserEndIndex = part.indexOf(""); + } + part = part.substring(disabledParserEndIndex + 1); + } + if (i < slices.length - 1) { + int disabledParserIndex = part.lastIndexOf(" installTypesToPostProcess() { mediaTypes.put(MediaType.parse(ShareazaLibraryDatParser.LIBRARY_DAT_MIME_TYPE), 2); mediaTypes.put(MediaType.parse(ShareazaDownloadParser.SHAREAZA_DOWNLOAD_META), 2); + mediaTypes.put(MediaType.parse(TorrentFileParser.TORRENT_FILE_MIME_TYPE), 2); + mediaTypes.put(MediaType.parse(BitTorrentResumeDatParser.RESUME_DAT_MIME_TYPE), 3); + mediaTypes.put(WhatsAppParser.WA_DB, 2); mediaTypes.put(WhatsAppParser.MSG_STORE, 3); mediaTypes.put(WhatsAppParser.MSG_STORE_2, 4); diff --git a/iped-engine/src/main/java/iped/engine/datasource/ad1/AD1Extractor.java b/iped-engine/src/main/java/iped/engine/datasource/ad1/AD1Extractor.java index 7a1d53ddf8..a65a953ccb 100644 --- a/iped-engine/src/main/java/iped/engine/datasource/ad1/AD1Extractor.java +++ b/iped-engine/src/main/java/iped/engine/datasource/ad1/AD1Extractor.java @@ -27,8 +27,6 @@ public class AD1Extractor implements Closeable { private static final long SIGNATURE_SIZE = 512; // 0x200 private static final String charset = "UTF-8"; - private static Object lock = new Object(); - private File file; private Map> fcMap = new HashMap<>(); private List channels = new ArrayList<>(); @@ -322,20 +320,17 @@ private int seekAndRead(int ad1Ord, long seekOff, byte[] buf, int off, int len) try { List bbList; - synchronized (lock) { - bbList = fcMap.get(ad1Ord); - if (bbList == null) { - File newAd1 = new File( - file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".") + 3) + ad1Ord); - FileChannel fc = FileChannel.open(newAd1.toPath(), StandardOpenOption.READ); - channels.add(fc); - bbList = new ArrayList<>(); - for (long pos = 0; pos < fc.size(); pos += Integer.MAX_VALUE) { - int size = (int) Math.min(fc.size() - pos, Integer.MAX_VALUE); - bbList.add(fc.map(MapMode.READ_ONLY, pos, size)); - } - fcMap.put(ad1Ord, bbList); + bbList = fcMap.get(ad1Ord); + if (bbList == null) { + File newAd1 = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".") + 3) + ad1Ord); + FileChannel fc = FileChannel.open(newAd1.toPath(), StandardOpenOption.READ); + channels.add(fc); + bbList = new ArrayList<>(); + for (long pos = 0; pos < fc.size(); pos += Integer.MAX_VALUE) { + int size = (int) Math.min(fc.size() - pos, Integer.MAX_VALUE); + bbList.add(fc.map(MapMode.READ_ONLY, pos, size)); } + fcMap.put(ad1Ord, bbList); } ByteBuffer src = bbList.get((int) (seekOff / Integer.MAX_VALUE)); int seek = (int) (seekOff % Integer.MAX_VALUE); @@ -346,9 +341,7 @@ private int seekAndRead(int ad1Ord, long seekOff, byte[] buf, int off, int len) return size; } catch (ClosedChannelException e) { - synchronized (lock) { - fcMap.put(ad1Ord, null); - } + fcMap.put(ad1Ord, null); throw e; } } diff --git a/iped-engine/src/main/java/iped/engine/task/DocThumbTask.java b/iped-engine/src/main/java/iped/engine/task/DocThumbTask.java index 98753a8d9d..bea7aca9d1 100644 --- a/iped-engine/src/main/java/iped/engine/task/DocThumbTask.java +++ b/iped-engine/src/main/java/iped/engine/task/DocThumbTask.java @@ -94,7 +94,7 @@ public void init(ConfigurationManager configurationManager) throws Exception { URL url = URLUtil.getURL(this.getClass()); File jarDir = new File(url.toURI()).getParentFile(); LibreOfficeFinder loFinder = new LibreOfficeFinder(jarDir); - loPath = loFinder.getLOPath(); + loPath = loFinder.getLOPath(true); logger.info("LibreOffice Path: " + loPath); } diff --git a/iped-engine/src/main/java/iped/engine/task/HTMLReportTask.java b/iped-engine/src/main/java/iped/engine/task/HTMLReportTask.java index ee13cbf024..bb565b8a26 100644 --- a/iped-engine/src/main/java/iped/engine/task/HTMLReportTask.java +++ b/iped-engine/src/main/java/iped/engine/task/HTMLReportTask.java @@ -351,6 +351,13 @@ protected void process(IItem evidence) throws Exception { ReportEntry reg = new ReportEntry(); reg.name = evidence.getName(); reg.export = evidence.getIdInDataSource(); + if (reg.export != null && output != null && output.getParentFile() != null) { + // Check if the exported file exists to avoid broken links (see issue #2203) + File expFile = new File(output.getParentFile(), reg.export); + if (!expFile.exists()) { + reg.export = null; + } + } reg.isImage = ImageThumbTask.isImageType(evidence.getMediaType()); reg.isVideo = VideoThumbTask.isVideoType(evidence.getMediaType()); reg.length = evidence.getLength(); diff --git a/iped-engine/src/main/java/iped/engine/task/P2PBookmarker.java b/iped-engine/src/main/java/iped/engine/task/P2PBookmarker.java index b28b49d558..f9fe18cee8 100644 --- a/iped-engine/src/main/java/iped/engine/task/P2PBookmarker.java +++ b/iped-engine/src/main/java/iped/engine/task/P2PBookmarker.java @@ -18,6 +18,7 @@ import iped.engine.search.IPEDSearcher; import iped.engine.task.index.IndexItem; import iped.parsers.ares.AresParser; +import iped.parsers.bittorrent.BitTorrentResumeDatParser; import iped.parsers.emule.KnownMetParser; import iped.parsers.emule.PartMetParser; import iped.parsers.gdrive.GDriveCloudGraphParser; @@ -79,10 +80,9 @@ public void createBookmarksForSharedFiles(File caseDir) { new P2PProgram(HashTask.HASH.SHA1.toString(), "Ares", new Color(238, 173, 0))); List shareazaHashes = Arrays.asList(HashTask.HASH.MD5.toString(), HashTask.HASH.SHA1.toString(), HashTask.HASH.EDONKEY.toString()); - p2pPrograms.put(ShareazaLibraryDatParser.LIBRARY_DAT_MIME_TYPE, new P2PProgram(shareazaHashes, "Shareaza", new Color(170, 20, 20))); - + p2pPrograms.put(ShareazaDownloadParser.SHAREAZA_DOWNLOAD_META, new P2PProgram(shareazaHashes, "Shareaza SD", new Color(170, 20, 20))); @@ -101,6 +101,11 @@ public void createBookmarksForSharedFiles(File caseDir) { p2pPrograms.put(ThreemaParser.THREEMA_CHAT.toString(), new P2PProgram(IndexItem.HASH, "Threema")); // $NON-NLS-1$ + List torrentHashes = Arrays.asList(IndexItem.HASH, HashTask.HASH.MD5.toString(), + HashTask.HASH.SHA1.toString(), HashTask.HASH.EDONKEY.toString()); + p2pPrograms.put(BitTorrentResumeDatParser.RESUME_DAT_MIME_TYPE, + new P2PProgram(torrentHashes, "Torrent", new Color(0, 160, 60))); + P2PProgram progGDrive = new P2PProgram(HashTask.HASH.MD5.toString(), "GoogleDrive"); p2pPrograms.put(GDriveCloudGraphParser.GDRIVE_CLOUD_GRAPH_REG.toString(), progGDrive); p2pPrograms.put(GDriveSnapshotParser.GDRIVE_SNAPSHOT_REG.toString(), progGDrive); diff --git a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2Discovery.java b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionDiscovery.java similarity index 99% rename from iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2Discovery.java rename to iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionDiscovery.java index 01c69855d6..4e07764b6a 100644 --- a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2Discovery.java +++ b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionDiscovery.java @@ -20,9 +20,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import iped.engine.task.transcript.RemoteWav2Vec2Service.MESSAGES; +import iped.engine.task.transcript.RemoteTranscriptionService.MESSAGES; -public class RemoteWav2Vec2Discovery { +public class RemoteTranscriptionDiscovery { private static final File statsFile = new File(System.getProperty("user.home"), "transcription.stats"); diff --git a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2Service.java b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionService.java similarity index 97% rename from iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2Service.java rename to iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionService.java index 93d436f984..39f974ddf1 100644 --- a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2Service.java +++ b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionService.java @@ -35,7 +35,7 @@ import iped.io.URLUtil; import iped.utils.IOUtil; -public class RemoteWav2Vec2Service { +public class RemoteTranscriptionService { static enum MESSAGES { ACCEPTED, @@ -131,11 +131,11 @@ public static void main(String[] args) throws Exception { printHelpAndExit(); } - File jar = new File(URLUtil.getURL(RemoteWav2Vec2Service.class).toURI()); + File jar = new File(URLUtil.getURL(RemoteTranscriptionService.class).toURI()); File root = jar.getParentFile().getParentFile(); System.setProperty("org.apache.logging.log4j.level", "INFO"); - logger = LoggerFactory.getLogger(RemoteWav2Vec2Service.class); + logger = LoggerFactory.getLogger(RemoteTranscriptionService.class); Configuration.getInstance().loadConfigurables(root.getAbsolutePath()); ConfigurationManager cm = ConfigurationManager.get(); @@ -143,10 +143,10 @@ public static void main(String[] args) throws Exception { LocalConfig localConfig = new LocalConfig(); cm.addObject(audioConfig); cm.addObject(localConfig); - cm.loadConfig(audioConfig); cm.loadConfig(localConfig); + cm.loadConfig(audioConfig); - Wav2Vec2TranscriptTask task = new Wav2Vec2TranscriptTask(); + AbstractTranscriptTask task = (AbstractTranscriptTask) Class.forName(audioConfig.getClassName()).getDeclaredConstructor().newInstance(); audioConfig.setEnabled(true); task.init(cm); @@ -261,7 +261,7 @@ private static void removeFrombeaconQueq(OpenConnectons opc) { } } - private static void waitRequests(ServerSocket server, Wav2Vec2TranscriptTask task, String discoveryIp) { + private static void waitRequests(ServerSocket server, AbstractTranscriptTask task, String discoveryIp) { AtomicInteger jobs = new AtomicInteger(); while (true) { try { diff --git a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionTask.java b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionTask.java new file mode 100644 index 0000000000..8c321db98f --- /dev/null +++ b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteTranscriptionTask.java @@ -0,0 +1,318 @@ +package iped.engine.task.transcript; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.ConnectException; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tika.io.TemporaryResources; + +import iped.configuration.IConfigurationDirectory; +import iped.data.IItem; +import iped.engine.config.AudioTranscriptConfig; +import iped.engine.config.ConfigurationManager; +import iped.engine.core.Manager; +import iped.engine.io.TimeoutException; +import iped.engine.task.transcript.RemoteTranscriptionService.MESSAGES; +import iped.exception.IPEDException; + +public class RemoteTranscriptionTask extends AbstractTranscriptTask { + + private static Logger logger = LogManager.getLogger(Wav2Vec2TranscriptTask.class); + + private static final int MAX_CONNECT_ERRORS = 60; + + private static final int UPDATE_SERVERS_INTERVAL_MILLIS = 60000; + + private static List servers = new ArrayList<>(); + + private static int currentServer = -1; + + private static AtomicInteger numConnectErrors = new AtomicInteger(); + + private static AtomicLong audioSendingTime = new AtomicLong(); + + private static AtomicLong transcriptReceiveTime = new AtomicLong(); + + private static AtomicBoolean statsPrinted = new AtomicBoolean(); + + private static long lastUpdateServersTime = 0; + + private static class Server { + + String ip; + int port; + + public String toString() { + return ip + ":" + port; + } + } + + // See https://github.com/sepinf-inc/IPED/issues/1576 + private int getRetryIntervalMillis() { + // This depends on how much time worker nodes need to consume their queue. + // Of course audios duration, nodes queue size and performance affect this. + // This tries to be fair with clients independent of their number of threads. + return Manager.getInstance().getNumWorkers() * 100; + } + + @Override + public void init(ConfigurationManager configurationManager) throws Exception { + + super.init(configurationManager); + + if (!this.isEnabled()) { + return; + } + + if (!servers.isEmpty()) { + return; + } + + boolean disable = false; + if (transcriptConfig.getRemoteService() == null) { + String ipedRoot = System.getProperty(IConfigurationDirectory.IPED_ROOT); + if (ipedRoot != null) { + Path path = new File(ipedRoot, "conf/" + AudioTranscriptConfig.CONF_FILE).toPath(); + configurationManager.getConfigurationDirectory().addPath(path); + configurationManager.addObject(transcriptConfig); + configurationManager.loadConfig(transcriptConfig); + // maybe user changed installation configs + if (transcriptConfig.getRemoteService() == null) { + disable = true; + } else { + transcriptConfig.setEnabled(true); + transcriptConfig.setClassName(this.getClass().getName()); + } + } else { + disable = true; + } + } + + if (disable) { + transcriptConfig.setEnabled(false); + logger.warn("Remote transcription module disabled, service address not configured."); + return; + } + + requestServers(true); + + } + + private static synchronized void requestServers(RemoteTranscriptionTask task, boolean now) throws IOException { + if (!now && System.currentTimeMillis() - lastUpdateServersTime < UPDATE_SERVERS_INTERVAL_MILLIS) { + return; + } + String[] ipAndPort = task.transcriptConfig.getRemoteService().split(":"); + String ip = ipAndPort[0]; + int port = Integer.parseInt(ipAndPort[1]); + try (Socket client = new Socket(ip, port); + InputStream is = client.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), StandardCharsets.UTF_8), true)) { + + client.setSoTimeout(10000); + writer.println(MESSAGES.DISCOVER); + int numServers = Integer.parseInt(reader.readLine()); + List servers = new ArrayList<>(); + for (int i = 0; i < numServers; i++) { + String[] ipPort = reader.readLine().split(":"); + Server server = new Server(); + server.ip = ipPort[0]; + server.port = Integer.parseInt(ipPort[1]); + servers.add(server); + logger.info("Transcription server discovered: {}:{}", server.ip, server.port); + } + RemoteTranscriptionTask.servers = servers; + lastUpdateServersTime = System.currentTimeMillis(); + } catch (ConnectException e) { + String msg = "Central transcription node refused connection, is it online? " + e.toString(); + if (servers.isEmpty()) { + throw new IPEDException(msg); + } else { + logger.warn(msg); + } + } + } + + private void requestServers(boolean now) throws IOException { + requestServers(this, now); + } + + + @Override + public void finish() throws Exception { + super.finish(); + if (!statsPrinted.getAndSet(true)) { + int numWorkers = this.worker.manager.getNumWorkers(); + DecimalFormat df = new DecimalFormat(); + logger.info("Time spent to send audios: {}s", df.format(audioSendingTime.get() / (1000 * numWorkers))); + logger.info("Time spent to receive transcriptions: {}s", df.format(transcriptReceiveTime.get() / (1000 * numWorkers))); + } + } + + /** + * Returns a transcription server between the discovered ones using a simple + * circular approach. + * + * @return Server instance to use + */ + private static synchronized Server getServer() { + if (servers.isEmpty()) { + throw new IPEDException("No transcription server available!"); + } + currentServer++; + if (currentServer >= servers.size()) { + currentServer = 0; + } + return servers.get(currentServer); + } + + /** + * Don't convert to WAV on client side, return the audio as is. + */ + @Override + protected File getTempFileToTranscript(IItem evidence, TemporaryResources tmp) throws IOException, InterruptedException { + return evidence.getTempFile(); + } + + @Override + protected TextAndScore transcribeAudio(File tmpFile) throws Exception { + + while (true) { + requestServers(false); + Server server = getServer(); + long requestTime = System.currentTimeMillis(); + try (Socket serverSocket = new Socket(server.ip, server.port); + InputStream is = serverSocket.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + BufferedOutputStream bos = new BufferedOutputStream(serverSocket.getOutputStream())) { + + numConnectErrors.set(0); + + int timeoutSecs = (int) (MIN_TIMEOUT + TIMEOUT_PER_MB * tmpFile.length() / (1 << 20)); + serverSocket.setSoTimeout(1000 * timeoutSecs); + + String response = reader.readLine(); + if (response == null || MESSAGES.BUSY.toString().equals(response)) { + logger.debug("Transcription server {} busy, trying another one.", server); + sleepBeforeRetry(requestTime); + continue; + } + if (!MESSAGES.ACCEPTED.toString().equals(response)) { + logger.error("Error 0 in communication with {}. The audio will be retried.", server); + continue; + } + + logger.debug("Transcription server {} accepted connection", server); + + long t0 = System.currentTimeMillis(); + + bos.write(MESSAGES.VERSION_1_2.toString().getBytes()); + // bos.write("\n".getBytes()); + + bos.write(MESSAGES.AUDIO_SIZE.toString().getBytes()); + + DataOutputStream dos = new DataOutputStream(bos); + // Must use long see #1833 + dos.writeLong(tmpFile.length()); + dos.flush(); + + Files.copy(tmpFile.toPath(), bos); + bos.flush(); + + long t1 = System.currentTimeMillis(); + + response = reader.readLine(); + + while (MESSAGES.PING.toString().equals(response)) { + logger.debug("ping {}", response); + response = reader.readLine(); + } + + if (MESSAGES.WARN.toString().equals(response)) { + String warn = reader.readLine(); + boolean tryAgain = false; + if (warn.contains(TimeoutException.class.getName())) { + // Timeout converting audio to wav, possibly it's corrupted + evidence.setTimeOut(true); + stats.incTimeouts(); + } else if (warn.contains(SocketTimeoutException.class.getName()) || warn.contains(SocketException.class.getName())) { + tryAgain = true; + } + logger.warn("Fail to transcribe on server: {} audio: {} error: {}.{}", server, evidence.getPath(), warn, (tryAgain ? " The audio will be retried." : "")); + if (tryAgain) { + continue; + } + return null; + } + if (MESSAGES.ERROR.toString().equals(response) || response == null) { + String error = response != null ? reader.readLine() : "Remote server process crashed or node was turned off!"; + logger.error("Error 1 in communication with {}: {}. The audio will be retried.", server, error); + throw new SocketException(error); + } + + TextAndScore textAndScore = new TextAndScore(); + textAndScore.score = Double.parseDouble(response); + textAndScore.text = reader.readLine(); + + long t2 = System.currentTimeMillis(); + + if (!MESSAGES.DONE.toString().equals(reader.readLine())) { + logger.error("Error 2 in communication with {}. The audio will be retried.", server); + throw new SocketException("Error receiving transcription."); + } + + audioSendingTime.addAndGet(t1 - t0); + transcriptReceiveTime.addAndGet(t2 - t1); + + return textAndScore; + + } catch (SocketTimeoutException | SocketException e) { + if (e instanceof ConnectException) { + numConnectErrors.incrementAndGet(); + if (numConnectErrors.get() / this.worker.manager.getNumWorkers() >= MAX_CONNECT_ERRORS) { + throw new TooManyConnectException(); + } + sleepBeforeRetry(requestTime); + requestServers(true); + } else { + logger.warn("Network error communicating to server: " + server + ", retrying audio: " + evidence.getPath(), e); + } + } + } + + } + + private void sleepBeforeRetry(long lastRequestTime) { + long sleep = getRetryIntervalMillis() - (System.currentTimeMillis() - lastRequestTime); + if (sleep > 0) { + try { + Thread.sleep(sleep); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2TranscriptTask.java b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2TranscriptTask.java index d7e1627af0..eda8b715de 100644 --- a/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2TranscriptTask.java +++ b/iped-engine/src/main/java/iped/engine/task/transcript/RemoteWav2Vec2TranscriptTask.java @@ -1,318 +1,11 @@ package iped.engine.task.transcript; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.net.ConnectException; -import java.net.Socket; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.tika.io.TemporaryResources; - -import iped.configuration.IConfigurationDirectory; -import iped.data.IItem; -import iped.engine.config.AudioTranscriptConfig; -import iped.engine.config.ConfigurationManager; -import iped.engine.core.Manager; -import iped.engine.io.TimeoutException; -import iped.engine.task.transcript.RemoteWav2Vec2Service.MESSAGES; -import iped.exception.IPEDException; - -public class RemoteWav2Vec2TranscriptTask extends AbstractTranscriptTask { - - private static Logger logger = LogManager.getLogger(Wav2Vec2TranscriptTask.class); - - private static final int MAX_CONNECT_ERRORS = 60; - - private static final int UPDATE_SERVERS_INTERVAL_MILLIS = 60000; - - private static List servers = new ArrayList<>(); - - private static int currentServer = -1; - - private static AtomicInteger numConnectErrors = new AtomicInteger(); - - private static AtomicLong audioSendingTime = new AtomicLong(); - - private static AtomicLong transcriptReceiveTime = new AtomicLong(); - - private static AtomicBoolean statsPrinted = new AtomicBoolean(); - - private static long lastUpdateServersTime = 0; - - private static class Server { - - String ip; - int port; - - public String toString() { - return ip + ":" + port; - } - } - - // See https://github.com/sepinf-inc/IPED/issues/1576 - private int getRetryIntervalMillis() { - // This depends on how much time worker nodes need to consume their queue. - // Of course audios duration, nodes queue size and performance affect this. - // This tries to be fair with clients independent of their number of threads. - return Manager.getInstance().getNumWorkers() * 100; - } - - @Override - public void init(ConfigurationManager configurationManager) throws Exception { - - super.init(configurationManager); - - if (!this.isEnabled()) { - return; - } - - if (!servers.isEmpty()) { - return; - } - - boolean disable = false; - if (transcriptConfig.getWav2vec2Service() == null) { - String ipedRoot = System.getProperty(IConfigurationDirectory.IPED_ROOT); - if (ipedRoot != null) { - Path path = new File(ipedRoot, "conf/" + AudioTranscriptConfig.CONF_FILE).toPath(); - configurationManager.getConfigurationDirectory().addPath(path); - configurationManager.addObject(transcriptConfig); - configurationManager.loadConfig(transcriptConfig); - // maybe user changed installation configs - if (transcriptConfig.getWav2vec2Service() == null) { - disable = true; - } else { - transcriptConfig.setEnabled(true); - transcriptConfig.setClassName(this.getClass().getName()); - } - } else { - disable = true; - } - } - - if (disable) { - transcriptConfig.setEnabled(false); - logger.warn("Remote transcription module disabled, service address not configured."); - return; - } - - requestServers(true); - - } - - private static synchronized void requestServers(RemoteWav2Vec2TranscriptTask task, boolean now) throws IOException { - if (!now && System.currentTimeMillis() - lastUpdateServersTime < UPDATE_SERVERS_INTERVAL_MILLIS) { - return; - } - String[] ipAndPort = task.transcriptConfig.getWav2vec2Service().split(":"); - String ip = ipAndPort[0]; - int port = Integer.parseInt(ipAndPort[1]); - try (Socket client = new Socket(ip, port); - InputStream is = client.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), StandardCharsets.UTF_8), true)) { - - client.setSoTimeout(10000); - writer.println(MESSAGES.DISCOVER); - int numServers = Integer.parseInt(reader.readLine()); - List servers = new ArrayList<>(); - for (int i = 0; i < numServers; i++) { - String[] ipPort = reader.readLine().split(":"); - Server server = new Server(); - server.ip = ipPort[0]; - server.port = Integer.parseInt(ipPort[1]); - servers.add(server); - logger.info("Transcription server discovered: {}:{}", server.ip, server.port); - } - RemoteWav2Vec2TranscriptTask.servers = servers; - lastUpdateServersTime = System.currentTimeMillis(); - } catch (ConnectException e) { - String msg = "Central transcription node refused connection, is it online? " + e.toString(); - if (servers.isEmpty()) { - throw new IPEDException(msg); - } else { - logger.warn(msg); - } - } - } - - private void requestServers(boolean now) throws IOException { - requestServers(this, now); - } - - - @Override - public void finish() throws Exception { - super.finish(); - if (!statsPrinted.getAndSet(true)) { - int numWorkers = this.worker.manager.getNumWorkers(); - DecimalFormat df = new DecimalFormat(); - logger.info("Time spent to send audios: {}s", df.format(audioSendingTime.get() / (1000 * numWorkers))); - logger.info("Time spent to receive transcriptions: {}s", df.format(transcriptReceiveTime.get() / (1000 * numWorkers))); - } - } - - /** - * Returns a transcription server between the discovered ones using a simple - * circular approach. - * - * @return Server instance to use - */ - private static synchronized Server getServer() { - if (servers.isEmpty()) { - throw new IPEDException("No transcription server available!"); - } - currentServer++; - if (currentServer >= servers.size()) { - currentServer = 0; - } - return servers.get(currentServer); - } - - /** - * Don't convert to WAV on client side, return the audio as is. - */ - @Override - protected File getTempFileToTranscript(IItem evidence, TemporaryResources tmp) throws IOException, InterruptedException { - return evidence.getTempFile(); - } - - @Override - protected TextAndScore transcribeAudio(File tmpFile) throws Exception { - - while (true) { - requestServers(false); - Server server = getServer(); - long requestTime = System.currentTimeMillis(); - try (Socket serverSocket = new Socket(server.ip, server.port); - InputStream is = serverSocket.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); - BufferedOutputStream bos = new BufferedOutputStream(serverSocket.getOutputStream())) { - - numConnectErrors.set(0); - - int timeoutSecs = (int) (MIN_TIMEOUT + TIMEOUT_PER_MB * tmpFile.length() / (1 << 20)); - serverSocket.setSoTimeout(1000 * timeoutSecs); - - String response = reader.readLine(); - if (response == null || MESSAGES.BUSY.toString().equals(response)) { - logger.debug("Transcription server {} busy, trying another one.", server); - sleepBeforeRetry(requestTime); - continue; - } - if (!MESSAGES.ACCEPTED.toString().equals(response)) { - logger.error("Error 0 in communication with {}. The audio will be retried.", server); - continue; - } - - logger.debug("Transcription server {} accepted connection", server); - - long t0 = System.currentTimeMillis(); - - bos.write(MESSAGES.VERSION_1_2.toString().getBytes()); - // bos.write("\n".getBytes()); - - bos.write(MESSAGES.AUDIO_SIZE.toString().getBytes()); - - DataOutputStream dos = new DataOutputStream(bos); - // Must use long see #1833 - dos.writeLong(tmpFile.length()); - dos.flush(); - - Files.copy(tmpFile.toPath(), bos); - bos.flush(); - - long t1 = System.currentTimeMillis(); - - response = reader.readLine(); - - while (MESSAGES.PING.toString().equals(response)) { - logger.debug("ping {}", response); - response = reader.readLine(); - } - - if (MESSAGES.WARN.toString().equals(response)) { - String warn = reader.readLine(); - boolean tryAgain = false; - if (warn.contains(TimeoutException.class.getName())) { - // Timeout converting audio to wav, possibly it's corrupted - evidence.setTimeOut(true); - stats.incTimeouts(); - } else if (warn.contains(SocketTimeoutException.class.getName()) || warn.contains(SocketException.class.getName())) { - tryAgain = true; - } - logger.warn("Fail to transcribe on server: {} audio: {} error: {}.{}", server, evidence.getPath(), warn, (tryAgain ? " The audio will be retried." : "")); - if (tryAgain) { - continue; - } - return null; - } - if (MESSAGES.ERROR.toString().equals(response) || response == null) { - String error = response != null ? reader.readLine() : "Remote server process crashed or node was turned off!"; - logger.error("Error 1 in communication with {}: {}. The audio will be retried.", server, error); - throw new SocketException(error); - } - - TextAndScore textAndScore = new TextAndScore(); - textAndScore.score = Double.parseDouble(response); - textAndScore.text = reader.readLine(); - - long t2 = System.currentTimeMillis(); - - if (!MESSAGES.DONE.toString().equals(reader.readLine())) { - logger.error("Error 2 in communication with {}. The audio will be retried.", server); - throw new SocketException("Error receiving transcription."); - } - - audioSendingTime.addAndGet(t1 - t0); - transcriptReceiveTime.addAndGet(t2 - t1); - - return textAndScore; - - } catch (SocketTimeoutException | SocketException e) { - if (e instanceof ConnectException) { - numConnectErrors.incrementAndGet(); - if (numConnectErrors.get() / this.worker.manager.getNumWorkers() >= MAX_CONNECT_ERRORS) { - throw new TooManyConnectException(); - } - sleepBeforeRetry(requestTime); - requestServers(true); - } else { - logger.warn("Network error communicating to server: " + server + ", retrying audio: " + evidence.getPath(), e); - } - } - } - - } - - private void sleepBeforeRetry(long lastRequestTime) { - long sleep = getRetryIntervalMillis() - (System.currentTimeMillis() - lastRequestTime); - if (sleep > 0) { - try { - Thread.sleep(sleep); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } +/** + * Used just for backwards compatibility with old config files. + * + * @author Nassif + * + */ +public class RemoteWav2Vec2TranscriptTask extends RemoteTranscriptionTask { } diff --git a/iped-engine/src/main/java/iped/engine/task/transcript/Wav2Vec2TranscriptTask.java b/iped-engine/src/main/java/iped/engine/task/transcript/Wav2Vec2TranscriptTask.java index ea4f50bc4c..84a92dca8a 100644 --- a/iped-engine/src/main/java/iped/engine/task/transcript/Wav2Vec2TranscriptTask.java +++ b/iped-engine/src/main/java/iped/engine/task/transcript/Wav2Vec2TranscriptTask.java @@ -36,20 +36,20 @@ public class Wav2Vec2TranscriptTask extends AbstractTranscriptTask { private static final int MAX_TRANSCRIPTIONS = 100000; private static final byte[] NEW_LINE = "\n".getBytes(); - private static volatile Integer numProcesses; + protected static volatile Integer numProcesses; private static LinkedBlockingDeque deque = new LinkedBlockingDeque<>(); - private static volatile Level logLevel = Level.forName("MSG", 250); + protected static volatile Level logLevel = Level.forName("MSG", 250); - private static class Server { + static class Server { Process process; BufferedReader reader; int transcriptionsDone = 0; int device = 0; } - private static int getNumProcessors() { + protected static int getNumProcessors() { SystemInfo si = new SystemInfo(); HardwareAbstractionLayer hal = si.getHardware(); CentralProcessor cpu = hal.getProcessor(); @@ -96,7 +96,7 @@ public void init(ConfigurationManager configurationManager) throws Exception { } - private Server startServer(int device) throws StartupException { + protected Server startServer(int device) throws StartupException { try { return startServer0(device); } catch (Exception e) { @@ -109,7 +109,7 @@ private Server startServer(int device) throws StartupException { } } - private Server startServer0(int device) throws IOException { + protected Server startServer0(int device) throws IOException { if (numProcesses != null && device == numProcesses) { return null; } @@ -172,7 +172,7 @@ private Server startServer0(int device) throws IOException { return server; } - private void logInputStream(InputStream is) { + protected void logInputStream(InputStream is) { Thread t = new Thread() { public void run() { byte[] buf = new byte[1024]; diff --git a/iped-engine/src/main/java/iped/engine/task/transcript/WhisperTranscriptTask.java b/iped-engine/src/main/java/iped/engine/task/transcript/WhisperTranscriptTask.java new file mode 100644 index 0000000000..697273efb2 --- /dev/null +++ b/iped-engine/src/main/java/iped/engine/task/transcript/WhisperTranscriptTask.java @@ -0,0 +1,168 @@ +package iped.engine.task.transcript; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang3.SystemUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import iped.configuration.IConfigurationDirectory; +import iped.engine.config.AudioTranscriptConfig; +import iped.engine.config.Configuration; +import iped.engine.config.ConfigurationManager; +import iped.exception.IPEDException; + +public class WhisperTranscriptTask extends Wav2Vec2TranscriptTask { + + private static Logger logger = LogManager.getLogger(Wav2Vec2TranscriptTask.class); + + private static final String SCRIPT_PATH = "/scripts/tasks/WhisperProcess.py"; + private static final String LIBRARY_LOADED = "library_loaded"; + private static final String MODEL_LOADED = "model_loaded"; + + private static final AtomicBoolean ffmpegTested = new AtomicBoolean(); + private static volatile boolean ffmpegFound; + + @Override + public void init(ConfigurationManager configurationManager) throws Exception { + if (!ffmpegTested.getAndSet(true)) { + try { + Runtime.getRuntime().exec("ffmpeg"); + ffmpegFound = true; + } catch (IOException e) { + ffmpegFound = false; + } + } + super.init(configurationManager); + } + + @Override + protected Server startServer0(int device) throws IOException { + if (numProcesses != null && device == numProcesses) { + return null; + } + ProcessBuilder pb = new ProcessBuilder(); + String ipedRoot = System.getProperty(IConfigurationDirectory.IPED_ROOT); + if (ipedRoot == null) { + ipedRoot = Configuration.getInstance().appRoot; + } + String python = SystemUtils.IS_OS_WINDOWS ? ipedRoot + "/python/python.exe" : "python3"; + String script = ipedRoot + SCRIPT_PATH; + String model = super.transcriptConfig.getWhisperModel(); + if (model == null) { + throw new StartupException("You must configure '" + AudioTranscriptConfig.WHISPER_MODEL + "' in audio transcription config file."); + } + + int cpus = getNumProcessors(); + int threads = Runtime.getRuntime().availableProcessors() / cpus; + + String lang = transcriptConfig.getLanguages().get(0); + if (lang.contains("-")) { + lang = lang.substring(0, lang.indexOf("-")); + } + + String precision = transcriptConfig.getPrecision(); + String batchSize = Integer.toString(transcriptConfig.getBatchSize()); + + pb.command(python, script, model, Integer.toString(device), Integer.toString(threads), lang, precision, batchSize); + + Process process = pb.start(); + + logInputStream(process.getErrorStream()); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line = reader.readLine(); + + if (!LIBRARY_LOADED.equals(line)) { + throw new StartupException("Neither 'faster_whisper' nor 'whisperx' python libraries were loaded correctly. You need to install one of them!"); + } + + line = reader.readLine(); + logger.info("Transcription library loaded: {}", line); + + if ("whisperx".equals(line) && !ffmpegFound) { + throw new IPEDException("FFmpeg not found on PATH, it is needed by WhisperX python library."); + } + + int cudaCount = Integer.valueOf(reader.readLine()); + if (numProcesses == null) { + logger.info("Number of CUDA devices detected: {}", cudaCount); + logger.info("Number of CPU devices detected: {}", cpus); + if (cudaCount > 0) { + numProcesses = cudaCount; + } else { + numProcesses = cpus; + } + } + + String msgToIgnore = "Ignored unknown"; + while ((line = reader.readLine()) != null && line.startsWith(msgToIgnore)) + ; + + if (!MODEL_LOADED.equals(line)) { + throw new StartupException("Error loading '" + model + "' transcription model."); + } + + line = reader.readLine(); + + logger.info("Model loaded on device={}", line); + + Server server = new Server(); + server.process = process; + server.reader = reader; + server.device = device; + + return server; + } + + @Override + protected TextAndScore transcribeAudio(File tmpFile) throws Exception { + return transcribeWavPart(tmpFile); + } + + @Override + protected void logInputStream(InputStream is) { + List ignoreMsgs = Arrays.asList( + "With dispatcher enabled, this function is no-op. You can remove the function call.", + "torchvision is not available - cannot save figures", + "Lightning automatically upgraded your loaded checkpoint from", + "Model was trained with pyannote.audio 0.0.1, yours is", + "Model was trained with torch 1.10.0+cu102, yours is"); + Thread t = new Thread() { + public void run() { + byte[] buf = new byte[1024]; + int read = 0; + try { + while ((read = is.read(buf)) != -1) { + String msg = new String(buf, 0, read).trim(); + boolean ignore = false; + for (String i : ignoreMsgs) { + if (msg.contains(i)) { + ignore = true; + break; + } + } + if (ignore) { + logger.warn(msg); + } else { + logger.log(logLevel, msg); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + t.setDaemon(true); + t.start(); + } + +} diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/ares/AresParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/ares/AresParser.java index d801fb35c9..05b436595a 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/ares/AresParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/ares/AresParser.java @@ -44,10 +44,10 @@ import org.xml.sax.helpers.AttributesImpl; import iped.data.IItemReader; -import iped.parsers.emule.KnownMetParser; import iped.parsers.util.BeanMetadataExtraction; import iped.parsers.util.ChildPornHashLookup; import iped.parsers.util.Messages; +import iped.parsers.util.P2PUtil; import iped.properties.ExtraProperties; import iped.search.IItemSearcher; import iped.utils.LocalizedFormat; @@ -249,9 +249,9 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, if (j != 1 || e == null) xhtml.characters(s); else { - IItemReader item = KnownMetParser.searchItemInCase(searcher, "sha-1", e.getHash()); + IItemReader item = P2PUtil.searchItemInCase(searcher, "sha-1", e.getHash()); if (item != null) { - KnownMetParser.printNameWithLink(xhtml, item, s); + P2PUtil.printNameWithLink(xhtml, item, s); cells.set(cells.size() - 1, strYes); } else { xhtml.characters(s); diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BencodedDict.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BencodedDict.java index b0051673ef..2902942120 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BencodedDict.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BencodedDict.java @@ -100,6 +100,10 @@ public String getString(String key) { return getUnknownCharsetString(buffer.array()); } + public Map getDict() { + return dict; + } + public BencodedDict getDict(String key) { Object obj = getObject(key); if (obj == null || !(obj instanceof Map)) { @@ -199,7 +203,7 @@ public byte[] getBytes(String key) { } private String getUnknownCharsetString(byte[] data) { - return Util.decodeUnknowCharset(data); + return Util.decodeUnknownCharset(data); } @Override diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentGenericDatParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentGenericDatParser.java new file mode 100644 index 0000000000..4107f5d9b0 --- /dev/null +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentGenericDatParser.java @@ -0,0 +1,171 @@ +package iped.parsers.bittorrent; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.HttpHeaders; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.TikaCoreProperties; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.AbstractParser; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.sax.XHTMLContentHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import iped.parsers.util.IgnoreCorruptedCarved; +import iped.parsers.util.Messages; +import iped.parsers.util.Util; +import iped.utils.TimeConverter; + +public class BitTorrentGenericDatParser extends AbstractParser { + private static final long serialVersionUID = -5053923300569187504L; + private static final String SETTINGS_DAT_MIME_TYPE = "application/x-bittorrent-settings-dat"; + private static final Set SUPPORTED_TYPES = Collections + .singleton(MediaType.parse(SETTINGS_DAT_MIME_TYPE)); + + private static final Set secondsKeys = new HashSet(); + private static final Set filetimeKeys = new HashSet(); + static { + secondsKeys.add("isp.peer_policy_expy"); + secondsKeys.add("lit"); + secondsKeys.add("next_market_share_report"); + secondsKeys.add("offers.cookiepage_last_showtime"); + secondsKeys.add("offers.graphicscard_check_timestamp"); + secondsKeys.add("settings_saved_systime"); + + filetimeKeys.add("bin_change"); + filetimeKeys.add("born_on"); + } + + @Override + public Set getSupportedTypes(ParseContext context) { + return SUPPORTED_TYPES; + } + + @Override + public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) + throws IOException, SAXException, TikaException { + + metadata.set(HttpHeaders.CONTENT_TYPE, SETTINGS_DAT_MIME_TYPE); + metadata.remove(TikaCoreProperties.RESOURCE_NAME_KEY); + + DateFormat df = new SimpleDateFormat(Messages.getString("BitTorrentResumeDatParser.DateFormat")); + df.setTimeZone(TimeZone.getTimeZone("GMT+0")); + + BencodedDict dict = new BencodedDict(stream, df, (context.get(IgnoreCorruptedCarved.class) == null)); + + XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata); + xhtml.startDocument(); + xhtml.newline(); + try { + xhtml.startElement("pre"); + xhtml.characters(toFormattedString(dict.getDict(), df)); + xhtml.endElement("pre"); + } finally { + xhtml.endDocument(); + } + } + + private static String toFormattedString(Map dict, DateFormat df) { + StringBuilder sb = new StringBuilder(); + format(sb, dict, df, 0); + return sb.toString(); + } + + private static void format(StringBuilder sb, Map dict, DateFormat df, int level) { + if (dict.isEmpty()) { + sb.append("{}"); + return; + } + char[] aux = new char[level * 4]; + Arrays.fill(aux, ' '); + String start = new String(aux); + if (level > 0) { + sb.append("{\n"); + } + for (String key : dict.keySet()) { + if (key.equals(".fileguard")) { + continue; + } + sb.append(start).append(key).append(" = "); + Object val = dict.get(key); + format(sb, key, val, df, level); + sb.append("\n"); + } + if (level > 0) { + sb.append(start.substring(4)).append("}"); + } + } + + @SuppressWarnings("unchecked") + private static void format(StringBuilder sb, String key, Object val, DateFormat df, int level) { + if (val == null) { + sb.append(""); + } else { + if (val instanceof Long) { + long v = (Long) val; + if (secondsKeys.contains(key)) { + sb.append(df.format(v * 1000)); + } else if (filetimeKeys.contains(key)) { + sb.append(df.format(TimeConverter.filetimeToMillis(v * 10000000))); + } else { + sb.append(v); + } + } else if (val instanceof Map) { + format(sb, (Map) val, df, level + 1); + } else if (val instanceof ByteBuffer) { + byte[] bytes = ((ByteBuffer) val).array(); + int cnt0 = 0; + int cnt1 = 0; + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[i]; + if (b < 32 || b > 127) { + if ((i & 1) == 0) { + cnt0++; + } else { + cnt1++; + } + } + } + if (cnt0 > bytes.length / 4 || cnt1 > bytes.length / 4) { + for (int i = 0; i < bytes.length; i++) { + if (i > 0) { + sb.append(' '); + } + sb.append(String.format("%02X", bytes[i] & 0xFF)); + } + } else { + try { + String s = Util.decodeUnknownCharset(bytes); + sb.append(s); + } catch (Exception e) { + } + } + } else if (val instanceof List) { + List l = (List) val; + sb.append('['); + for (int i = 0; i < l.size(); i++) { + if (i > 0) { + sb.append(", "); + } + format(sb, key, l.get(i), df, level); + } + sb.append(']'); + } else { + sb.append(val.getClass() + " : " + val.toString()); + } + } + } +} diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentResumeDatParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentResumeDatParser.java index 4e5b241478..1e986e2a8c 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentResumeDatParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/BitTorrentResumeDatParser.java @@ -8,6 +8,7 @@ import java.util.Set; import java.util.TimeZone; +import org.apache.commons.codec.binary.Hex; import org.apache.tika.exception.TikaException; import org.apache.tika.metadata.HttpHeaders; import org.apache.tika.metadata.Metadata; @@ -19,8 +20,13 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; +import iped.data.IItemReader; import iped.parsers.util.IgnoreCorruptedCarved; import iped.parsers.util.Messages; +import iped.parsers.util.P2PUtil; +import iped.properties.BasicProps; +import iped.properties.ExtraProperties; +import iped.search.IItemSearcher; import iped.utils.LocalizedFormat; /** @@ -34,9 +40,11 @@ public class BitTorrentResumeDatParser extends AbstractParser { private static final Set SUPPORTED_TYPES = Collections .singleton(MediaType.application("x-bittorrent-resume-dat")); //$NON-NLS-1$ public static final String RESUME_DAT_MIME_TYPE = "application/x-bittorrent-resume-dat"; //$NON-NLS-1$ - private static final String[] header = new String[] { Messages.getString("BitTorrentResumeDatParser.TorrentFile"), //$NON-NLS-1$ + private static final String[] header = new String[] { "#", + Messages.getString("BitTorrentResumeDatParser.TorrentFile"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.RootDir"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.Path"), //$NON-NLS-1$ + Messages.getString("BitTorrentResumeDatParser.InfoHash"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.Downloaded"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.Uploaded"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.AddedDate"), //$NON-NLS-1$ @@ -44,9 +52,12 @@ public class BitTorrentResumeDatParser extends AbstractParser { Messages.getString("BitTorrentResumeDatParser.Time"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.LastSeenCompleteDate"), //$NON-NLS-1$ Messages.getString("BitTorrentResumeDatParser.SeedTime"), //$NON-NLS-1$ - Messages.getString("BitTorrentResumeDatParser.RunTime") //$NON-NLS-1$ + Messages.getString("BitTorrentResumeDatParser.RunTime"), //$NON-NLS-1$ + Messages.getString("BitTorrentResumeDatParser.TorrentFoundInCase"), //$NON-NLS-1$ + Messages.getString("BitTorrentResumeDatParser.FilesFoundInCase") //$NON-NLS-1$ }; - private static final char[] colAlign = new char[] { 'a', 'a', 'a', 'c', 'c', 'b', 'b', 'b', 'b', 'c', 'c' }; + private static final char[] colAlign = new char[] { 'b', 'a', 'a', 'a', 'h', 'c', 'c', 'b', 'b', 'b', 'b', 'c', 'c', 'b', 'b' }; + private static final String strYes = Messages.getString("BitTorrentResumeDatParser.Yes"); @Override public Set getSupportedTypes(ParseContext context) { @@ -72,9 +83,10 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, + ".rh { font-weight: bold; text-align: center; background-color:#AAAAEE; } " //$NON-NLS-1$ + ".ra { vertical-align: middle; } " //$NON-NLS-1$ + ".rb { background-color:#E7E7F0; vertical-align: middle; } " //$NON-NLS-1$ - + ".a { border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; word-wrap: break-word; } " //$NON-NLS-1$ + + ".a { max-width: 400px; border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; word-wrap: break-word; } " //$NON-NLS-1$ + ".b { border: solid; border-width: thin; padding: 3px; text-align: center; vertical-align: middle; word-wrap: break-word; } " //$NON-NLS-1$ - + ".c { border: solid; border-width: thin; padding: 3px; text-align: right; vertical-align: middle; word-wrap: break-word; } "); //$NON-NLS-1$ + + ".c { border: solid; border-width: thin; padding: 3px; text-align: right; vertical-align: middle; word-wrap: break-word; } " //$NON-NLS-1$ + + ".h { font-weight: bold; border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; white-space: nowrap; font-family: monospace; }"); xhtml.endElement("style"); //$NON-NLS-1$ xhtml.newline(); try { @@ -91,6 +103,8 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, } xhtml.endElement("tr"); //$NON-NLS-1$ + int numEntries = 0; + IItemSearcher searcher = context.get(IItemSearcher.class); boolean a = true; for (String torrent : dict.keySet()) { if (torrent.equals(".fileguard") || torrent.equals("rec")) { //$NON-NLS-1$ $NON-NLS-2$ @@ -100,9 +114,43 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, if (torrentDict == null) { continue; } + byte[] infoBytes = torrentDict.getBytes("info"); + String infoHash = ""; + if (infoBytes != null) { + infoHash = Hex.encodeHexString(infoBytes, false); + } + int filesFoundInCase = 0; + IItemReader item = P2PUtil.searchItemInCase(searcher, TorrentFileParser.TORRENT_INFO_HASH, infoHash); + if (item != null) { + metadata.add(ExtraProperties.LINKED_ITEMS, BasicProps.HASH + ":" + item.getHash()); + String[] values = item.getMetadata().getValues(ExtraProperties.LINKED_ITEMS); + if (values != null) { + Long uploaded = torrentDict.getLong("uploaded"); + boolean isShared = uploaded != null && uploaded > 0; + for (String v : values) { + metadata.add(ExtraProperties.LINKED_ITEMS, v); + if (isShared) { + int p = v.lastIndexOf(':'); + if (p >= 0) { + v = v.substring(p + 1).trim(); + } + metadata.add(ExtraProperties.SHARED_HASHES, v); + } + } + } + String v = item.getMetadata().get(TorrentFileParser.TORRENT_FILES_FOUND_IN_CASE); + if (v != null && !v.isBlank()) { + filesFoundInCase = Integer.parseInt(v); + } + } + xhtml.startElement("tr", "class", a ? "ra" : "rb"); //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ $NON-NLS-4$ - String[] rowElements = new String[] { torrent, torrentDict.getString("rootdir"), //$NON-NLS-1$ + String[] rowElements = new String[] { + String.valueOf(++numEntries), + torrent, + torrentDict.getString("rootdir"), //$NON-NLS-1$ torrentDict.getString("path"), //$NON-NLS-1$ + infoHash, Long.toString(torrentDict.getLong("downloaded")), //$NON-NLS-1$ Long.toString(torrentDict.getLong("uploaded")), //$NON-NLS-1$ torrentDict.getDate("added_on"), //$NON-NLS-1$ @@ -110,7 +158,9 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, torrentDict.getDate("time"), //$NON-NLS-1$ torrentDict.getDate("last seen complete"), //$NON-NLS-1$ Long.toString(torrentDict.getLong("seedtime")), //$NON-NLS-1$ - Long.toString(torrentDict.getLong("runtime")) //$NON-NLS-1$ + Long.toString(torrentDict.getLong("runtime")), //$NON-NLS-1$ + item != null ? strYes: "", + filesFoundInCase > 0 ? String.valueOf(filesFoundInCase): "" }; for (int i = 0; i < rowElements.length; i++) { String c = rowElements[i]; @@ -130,11 +180,11 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.endElement("tr"); //$NON-NLS-1$ a = !a; } + metadata.set(ExtraProperties.P2P_REGISTRY_COUNT, String.valueOf(numEntries)); xhtml.endElement("table"); //$NON-NLS-1$ } finally { xhtml.endDocument(); } - } -} \ No newline at end of file +} diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/TorrentFileParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/TorrentFileParser.java index 5a4ec3a177..88cc3d3c4d 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/TorrentFileParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/bittorrent/TorrentFileParser.java @@ -1,5 +1,6 @@ package iped.parsers.bittorrent; +import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -7,8 +8,10 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TimeZone; @@ -25,10 +28,14 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; +import iped.data.IItemReader; import iped.parsers.util.IgnoreCorruptedCarved; import iped.parsers.util.Messages; import iped.parsers.util.MetadataUtil; +import iped.parsers.util.P2PUtil; +import iped.properties.BasicProps; import iped.properties.ExtraProperties; +import iped.search.IItemSearcher; import iped.utils.DateUtil; import iped.utils.LocalizedFormat; @@ -39,16 +46,39 @@ */ public class TorrentFileParser extends AbstractParser { - private static final String TORRENT_CREATION_DATE = "torrentCreationDate"; + private static final String TORRENT_CREATION_DATE = ExtraProperties.P2P_META_PREFIX + "torrentCreationDate"; + public static final String TORRENT_INFO_HASH = ExtraProperties.P2P_META_PREFIX + "torrentInfoHash"; + public static final String TORRENT_FILES_FOUND_IN_CASE = ExtraProperties.P2P_META_PREFIX + + "torrentFilesFoundInCase"; + private static final long serialVersionUID = 3238363426940179831L; private static final Set SUPPORTED_TYPES = Collections.singleton(MediaType.application("x-bittorrent")); //$NON-NLS-1$ public static final String TORRENT_FILE_MIME_TYPE = "application/x-bittorrent"; //$NON-NLS-1$ - private static final String[] header = { Messages.getString("TorrentFileDatParser.FullPath"), //$NON-NLS-1$ + private static final String[] header = { Messages.getString("TorrentFileDatParser.File"), + Messages.getString("TorrentFileDatParser.FullPath"), //$NON-NLS-1$ Messages.getString("TorrentFileDatParser.FileSize"), //$NON-NLS-1$ Messages.getString("TorrentFileDatParser.MD5"), //$NON-NLS-1$ Messages.getString("TorrentFileDatParser.SHA1"), //$NON-NLS-1$ - Messages.getString("TorrentFileDatParser.ED2K") //$NON-NLS-1$ + Messages.getString("TorrentFileDatParser.ED2K"), //$NON-NLS-1$ + Messages.getString("TorrentFileDatParser.FileFoundInCase"), + Messages.getString("TorrentFileDatParser.PathInCase") }; + private static final String strConfirmedPieces = Messages.getString("TorrentFileDatParser.ConfirmedPieces"); + private static final String strAtOffset = Messages.getString("TorrentFileDatParser.AtOffset"); + + private static final String strYes = Messages.getString("TorrentFileDatParser.Yes"); + + private static final String padding = "_____padding_file"; + + private static final int maxPieceLength = 1 << 26; + private static final long minFileLength = 1 << 16; + private static final long maxFileLength = 1L << 34; + private static final int maxHitsCheck = 64; + private static final int minPiecesMultiFile = 8; + + private static final int md5Len = 32; + private static final int sha1Len = 40; + private static final int edonkeyLen = 32; @Override public Set getSupportedTypes(ParseContext context) { @@ -70,17 +100,18 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, throw new TikaException("Error parsing torrent file", e); //$NON-NLS-1$ } - List files = extractFileList(dict, metadata); + IItemSearcher searcher = context.get(IItemSearcher.class); + List files = extractFileList(dict, metadata, searcher); - char[] colClass = { 'a', 'c', 'h', 'h', 'h' }; - boolean[] include = { true, true, false, false, false }; + char[] colClass = { 'c', 'a', 'c', 'h', 'h', 'h', 'b', 'a' }; + boolean[] include = { true, true, true, false, false, false, false, false }; for (FileInTorrent file : files) { if (!file.md5.isEmpty()) - include[2] = true; - if (!file.sha1.isEmpty()) include[3] = true; - if (!file.ed2k.isEmpty()) + if (!file.sha1.isEmpty()) include[4] = true; + if (!file.ed2k.isEmpty()) + include[5] = true; } XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata); @@ -91,11 +122,12 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, + ".rh { font-weight: bold; text-align: center; background-color:#AAAAEE; } " + ".ra { vertical-align: middle; } " + ".rb { background-color:#E7E7F0; vertical-align: middle; } " - + ".a { border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; word-wrap: break-word; } " - + ".b { border: solid; border-width: thin; padding: 3px; text-align: center; vertical-align: middle; word-wrap: break-word; } " - + ".c { border: solid; border-width: thin; padding: 3px; text-align: right; vertical-align: middle; word-wrap: break-word; } " + + ".a { min-width: 200px; border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; word-wrap: break-word; } " + + ".b { min-width: 100px; border: solid; border-width: thin; padding: 3px; text-align: center; vertical-align: middle; word-wrap: break-word; } " + + ".c { min-width: 80px; border: solid; border-width: thin; padding: 3px; text-align: right; vertical-align: middle; word-wrap: break-word; } " + ".d { font-weight: bold; background-color:#AAAAEE; border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; white-space: nowrap; } " - + ".h { font-weight: bold; border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; white-space: nowrap; font-family: monospace; } "); + + ".h { min-width: 200px; font-weight: bold; border: solid; border-width: thin; padding: 3px; text-align: left; vertical-align: middle; white-space: nowrap; font-family: monospace; } " + + ".s { font-size: x-small; } "); xhtml.endElement("style"); //$NON-NLS-1$ xhtml.newline(); @@ -105,31 +137,75 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, metadata.set("incompleteTorrent", "true"); } + TorrentInfo info = extractTorrentInfo(dict); + + // Try to link the items + if (searcher != null && !files.isEmpty() && info.pieces != null && info.pieceLength != null + && info.pieceLength > 0 && info.pieceLength < maxPieceLength) { + long tot = 0; + for (int i = 0; i < files.size(); i++) { + FileInTorrent file = files.get(i); + if (file.item == null) { + ItemPiecesMatchInfo itemPiecesMatchInfo = searchAndMatchFileInCase(searcher, file.length, + info.pieceLength, info.pieces, + (int) (tot / info.pieceLength), (int) (tot % info.pieceLength), i == files.size() - 1); + if (itemPiecesMatchInfo != null) { + file.item = itemPiecesMatchInfo.item; + file.itemPiecesMatchInfo = itemPiecesMatchInfo; + metadata.add(ExtraProperties.LINKED_ITEMS, BasicProps.HASH + ":" + file.item.getHash()); + } + } + tot += file.length; + } + } + + int foundInCase = 0; + int paddingEntries = 0; + for (FileInTorrent file : files) { + if (file.fullPath == null || file.fullPath.toLowerCase().contains(padding)) { + paddingEntries++; + } else if (file.item != null) { + include[6] = true; + include[7] = true; + foundInCase++; + } + } + // Torrent General Info Table xhtml.startElement("table", "class", "dt"); - TorrentInfo info = extractTorrentInfo(dict); outputInfo(xhtml, Messages.getString("TorrentFileDatParser.Name"), info.name); - outputInfo(xhtml, Messages.getString("TorrentFileDatParser.InfoHash"), info.infoHash, true); outputInfo(xhtml, Messages.getString("TorrentFileDatParser.PieceLength"), info.pieceLength); outputInfo(xhtml, Messages.getString("TorrentFileDatParser.NumberOfPieces"), info.numPieces); - outputInfo(xhtml, Messages.getString("TorrentFileDatParser.NumberOfFiles"), files.size()); + outputInfo(xhtml, Messages.getString("TorrentFileDatParser.NumberOfFiles"), files.size() - paddingEntries); + if (foundInCase > 0) { + outputInfo(xhtml, Messages.getString("TorrentFileDatParser.FilesFoundInCase"), foundInCase); + } outputInfo(xhtml, Messages.getString("TorrentFileDatParser.Announce"), info.announce); outputInfo(xhtml, Messages.getString("TorrentFileDatParser.Comment"), info.comment); outputInfo(xhtml, Messages.getString("TorrentFileDatParser.CreatedBy"), info.createdBy); outputInfo(xhtml, Messages.getString("TorrentFileDatParser.CreationDate"), info.creationDate); + xhtml.endElement("table"); + // Set creation date metadata MetadataUtil.setMetadataType(TORRENT_CREATION_DATE, Date.class); if (!info.creationDate.isEmpty()) { try { metadata.set(TORRENT_CREATION_DATE, DateUtil.dateToString(df.parse(info.creationDate))); - } catch (ParseException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); } } + + // Set infoHash metadata + if (info.infoHash != null && !info.infoHash.isBlank()) { + metadata.set(TORRENT_INFO_HASH, info.infoHash); + } - xhtml.endElement("table"); + // Set the number of files found in case metadata + if (foundInCase > 0) { + metadata.set(TORRENT_FILES_FOUND_IN_CASE, String.valueOf(foundInCase)); + } // Files Table xhtml.startElement("table", "class", "dt"); //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ @@ -143,31 +219,42 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, } xhtml.endElement("tr"); //$NON-NLS-1$ - boolean a = true; - for (FileInTorrent file : files) { - xhtml.startElement("tr", "class", a ? "ra" : "rb"); //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ $NON-NLS-4$ - String[] rowElements = new String[] { file.fullPath, Long.toString(file.length), file.md5, file.sha1, - file.ed2k }; - for (int i = 0; i < rowElements.length; i++) { - if (include[i]) { - xhtml.startElement("td", "class", String.valueOf(colClass[i])); //$NON-NLS-1$ $NON-NLS-2$ - if (rowElements[i].equals("")) { //$NON-NLS-1$ - rowElements[i] = " "; //$NON-NLS-1$ - } else if (i == 1) { + int row = 0; + for (int i = 0; i < files.size(); i++) { + FileInTorrent file = files.get(i); + if (file.fullPath == null || file.fullPath.toLowerCase().contains(padding)) { + // Ignore padding entries + continue; + } + xhtml.startElement("tr", "class", row % 2 == 0 ? "ra" : "rb"); + String[] rowElements = new String[] { String.valueOf(++row), file.fullPath, Long.toString(file.length), + file.md5, file.sha1, file.ed2k, "", file.item == null ? "" : file.item.getPath() }; + for (int col = 0; col < rowElements.length; col++) { + if (include[col]) { + String str = rowElements[col]; + xhtml.startElement("td", "class", String.valueOf(colClass[col])); + if (str.length() == 0) { + str = " "; + } else if (col == 2) { // File length column try { - rowElements[i] = LocalizedFormat.format(Long.parseLong(rowElements[i])); + str = LocalizedFormat.format(Long.parseLong(str)); } catch (Exception e) { } } - xhtml.characters(rowElements[i]); - xhtml.endElement("td"); //$NON-NLS-1$ + if (col == 1 && file.item != null) { + P2PUtil.printNameWithLink(xhtml, file.item, str); + } else if (col == 6) { + outputMatchInfo(xhtml, file.itemPiecesMatchInfo); + } else { + xhtml.characters(str); + } + xhtml.endElement("td"); } } - xhtml.endElement("tr"); //$NON-NLS-1$ - a = !a; + xhtml.endElement("tr"); } - xhtml.endElement("table"); //$NON-NLS-1$ + xhtml.endElement("table"); // Pieces Hashes Table if (info.pieces != null) { @@ -181,9 +268,8 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.endElement("td"); xhtml.endElement("tr"); - a = true; for (int i = 0; i < info.pieces.length; i++) { - xhtml.startElement("tr", "class", a ? "ra" : "rb"); + xhtml.startElement("tr", "class", i % 2 == 0 ? "ra" : "rb"); xhtml.startElement("td", "class", "c"); xhtml.characters(LocalizedFormat.format(i + 1)); xhtml.endElement("td"); @@ -191,7 +277,6 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.characters(info.pieces[i]); xhtml.endElement("td"); xhtml.endElement("tr"); - a = !a; } xhtml.endElement("table"); } @@ -199,6 +284,25 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.endDocument(); } + private static void outputMatchInfo(XHTMLContentHandler xhtml, ItemPiecesMatchInfo itemPiecesMatchInfo) + throws SAXException { + if (itemPiecesMatchInfo != null) { + xhtml.characters(strYes); + xhtml.startElement("br"); + xhtml.startElement("span", "class", "s"); + xhtml.characters("(" + strConfirmedPieces + " "); + xhtml.characters(LocalizedFormat.format(itemPiecesMatchInfo.startPiece + 1)); + xhtml.characters("-"); + xhtml.characters(LocalizedFormat.format(itemPiecesMatchInfo.finalPiece + 1)); + if (itemPiecesMatchInfo.startOffset != 0) { + xhtml.characters(" " + strAtOffset + " "); + xhtml.characters(LocalizedFormat.format(itemPiecesMatchInfo.startOffset)); + } + xhtml.characters(")"); + xhtml.endElement("span"); + } + } + private static void outputInfo(XHTMLContentHandler xhtml, String key, Object value) throws SAXException { outputInfo(xhtml, key, value, false); } @@ -218,18 +322,19 @@ private static void outputInfo(XHTMLContentHandler xhtml, String key, Object val } } - private static List extractFileList(BencodedDict dict, Metadata metadata) throws TikaException { - BencodedDict info = dict.getDict("info"); //$NON-NLS-1$ + private static List extractFileList(BencodedDict dict, Metadata metadata, IItemSearcher searcher) + throws TikaException { + BencodedDict info = dict.getDict("info"); List files; if (info != null) { - if (info.containsKey("files")) { //$NON-NLS-1$ - // Multi file torrent - List filesList = info.getList("files"); //$NON-NLS-1$ + if (info.containsKey("files")) { + // Multi-file torrent + List filesList = info.getList("files"); if (filesList == null) { - throw new TikaException("Error parsing torrent file"); //$NON-NLS-1$ + throw new TikaException("Error parsing torrent file"); } - String name = info.getString("name"); //$NON-NLS-1$ + String name = info.getString("name"); files = new ArrayList<>(filesList.size()); for (Object fileDictObj : filesList) { BencodedDict fileDict = (BencodedDict) fileDictObj; @@ -238,62 +343,72 @@ private static List extractFileList(BencodedDict dict, Metadata m if (name != null && 0 != name.length()) { fullPathBuilder.append(name).append(File.separator); } - for (String elem : fileDict.getListOfStrings("path")) { //$NON-NLS-1$ + for (String elem : fileDict.getListOfStrings("path")) { fullPathBuilder.append(elem).append(File.separator); } fullPathBuilder.deleteCharAt(fullPathBuilder.length() - 1); file.fullPath = fullPathBuilder.toString(); - file.length = fileDict.getLong("length"); //$NON-NLS-1$ - file.md5 = fileDict.getString("md5sum"); //$NON-NLS-1$ - if (file.md5.length() > 0) { - metadata.add(ExtraProperties.LINKED_ITEMS, "md5:" + file.md5); - } - file.sha1 = fileDict.getString("sha1").trim(); //$NON-NLS-1$ - if (file.sha1.length() > 0) { - if (file.sha1.length() != 40) { - file.sha1 = fileDict.getHexEncodedBytes("sha1"); //$NON-NLS-1$ - } - metadata.add(ExtraProperties.LINKED_ITEMS, "sha-1:" + file.sha1); - } - file.ed2k = fileDict.getHexEncodedBytes("ed2k"); //$NON-NLS-1$ + file.length = fileDict.getLong("length"); + file.md5 = getStringOrBytes(fileDict, "md5sum", md5Len); + file.sha1 = getStringOrBytes(fileDict, "sha1", sha1Len); + file.ed2k = getStringOrBytes(fileDict, "ed2k", edonkeyLen); files.add(file); } } else { // Single file torrent FileInTorrent file = new FileInTorrent(); - file.fullPath = info.getString("name"); //$NON-NLS-1$ - file.length = info.getLong("length"); //$NON-NLS-1$ - file.md5 = info.getString("md5sum"); //$NON-NLS-1$ - if (file.md5.length() > 0) { - metadata.add(ExtraProperties.LINKED_ITEMS, "md5:" + file.md5); - } - file.sha1 = info.getString("sha1").trim(); //$NON-NLS-1$ - if (file.sha1.length() > 0) { - if (file.sha1.length() != 40) { - file.sha1 = info.getHexEncodedBytes("sha1"); //$NON-NLS-1$ - } - metadata.add(ExtraProperties.LINKED_ITEMS, "sha-1:" + file.sha1); - } - file.ed2k = info.getHexEncodedBytes("ed2k"); //$NON-NLS-1$ + file.fullPath = info.getString("name"); + file.length = info.getLong("length"); + file.md5 = getStringOrBytes(info, "md5sum", md5Len); + file.sha1 = getStringOrBytes(info, "sha1", sha1Len); + file.ed2k = getStringOrBytes(info, "ed2k", edonkeyLen); files = Collections.singletonList(file); } if (files.isEmpty()) { - throw new TikaException("Error parsing torrent file"); //$NON-NLS-1$ + throw new TikaException("Error parsing torrent file"); } + + // Try to link files to case items by hash + for (FileInTorrent file : files) { + linkTorrentToItem(searcher, metadata, file, "md5", file.md5, md5Len); + linkTorrentToItem(searcher, metadata, file, "sha-1", file.sha1, sha1Len); + linkTorrentToItem(searcher, metadata, file, "edonkey", file.ed2k, edonkeyLen); + } + } else { - throw new TikaException("Error parsing torrent file"); //$NON-NLS-1$ + throw new TikaException("Error parsing torrent file"); } return files; } + private static String getStringOrBytes(BencodedDict dict, String key, int len) { + String s = dict.getString(key).trim(); + if (s.length() > 0 && s.length() != len) { + s = dict.getHexEncodedBytes(key); + } + return s; + } + + private static void linkTorrentToItem(IItemSearcher searcher, Metadata metadata, FileInTorrent file, String key, + String val, int len) { + if (val.length() == len) { + metadata.add(ExtraProperties.LINKED_ITEMS, key + ":" + val); + if (file.item == null) { + file.item = P2PUtil.searchItemInCase(searcher, key, val); + } + } + } + private static class FileInTorrent { + ItemPiecesMatchInfo itemPiecesMatchInfo; String fullPath; long length; String md5; String sha1; String ed2k; + IItemReader item; } private static TorrentInfo extractTorrentInfo(BencodedDict dict) throws TikaException { @@ -341,4 +456,85 @@ private static class TorrentInfo { Long numPieces; String[] pieces; } + + private static class ItemPiecesMatchInfo { + IItemReader item; + int startPiece; + int finalPiece; + int startOffset; + } + + private static ItemPiecesMatchInfo searchAndMatchFileInCase(IItemSearcher searcher, long fileLength, + long pieceLength, + String[] pieces, final int firstPiece, final int offset, final boolean isLast) { + if (fileLength < minFileLength || fileLength > maxFileLength) { + return null; + } + int totPieces = (int) ((fileLength + pieceLength - 1 + offset) / pieceLength); + if (firstPiece + totPieces > pieces.length || ((!isLast || offset != 0) && totPieces < minPiecesMultiFile)) { + return null; + } + List items = searcher.search(BasicProps.LENGTH + ":" + fileLength); + if (items == null || items.isEmpty()) { + return null; + } + byte[] bytes = new byte[(int) pieceLength]; + int check = maxHitsCheck; + Set seen = new HashSet(); + for (int step = 0; step <= 1; step++) { + NEXT: for (int i = 0; i < items.size(); i++) { + IItemReader item = items.get(i); + if (step == 0 ^ (item.isCarved() || item.isDeleted())) { + // In the first step check only "active" items + // Carved and deleted items are checked later + continue; + } + if (item.getHash() == null || !seen.add(item.getHash())) { + continue; + } + // Check if the all pieces hashes match + try (BufferedInputStream is = item.getBufferedInputStream()) { + ItemPiecesMatchInfo itemPiecesMatchInfo = new ItemPiecesMatchInfo(); + itemPiecesMatchInfo.startOffset = offset; + if (offset > 0) { + int read = is.readNBytes(bytes, 0, bytes.length - offset); + if (read < bytes.length - offset) { + continue NEXT; + } + } + int n = offset == 0 ? 0 : 1; + itemPiecesMatchInfo.startPiece = n + firstPiece; + for (; n < totPieces; n++) { + int read = is.readNBytes(bytes, 0, bytes.length); + if (read < 0 || (read < bytes.length && n < totPieces - 1)) { + continue NEXT; + } + if (read == bytes.length || isLast) { + byte[] in = bytes; + if (read < bytes.length) { + in = Arrays.copyOf(bytes, read); + } + String calc = DigestUtils.sha1Hex(in); + if (calc == null || !calc.equalsIgnoreCase(pieces[n + firstPiece])) { + continue NEXT; + } + } + } + itemPiecesMatchInfo.finalPiece = n + firstPiece - 1; + itemPiecesMatchInfo.item = item; + + // Found an item that matches all pieces hashes + return itemPiecesMatchInfo; + + } catch (Exception e) { + e.printStackTrace(); + } + + if (--check == 0) { + break; + } + } + } + return null; + } } diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/browsers/ie/IndexDatParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/browsers/ie/IndexDatParser.java index 1d9d389983..b6209ec6ca 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/browsers/ie/IndexDatParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/browsers/ie/IndexDatParser.java @@ -129,7 +129,7 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, read.value = null; read.notify(); } - String str = Util.decodeUnknowCharset(out); + String str = Util.decodeUnknownCharset(out); xhtml.characters(str); if (Thread.currentThread().isInterrupted()) diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/KnownMetParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/KnownMetParser.java index ebd261d792..6b3cade317 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/KnownMetParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/KnownMetParser.java @@ -18,7 +18,6 @@ */ package iped.parsers.emule; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; @@ -48,9 +47,8 @@ import iped.data.IItemReader; import iped.parsers.util.BeanMetadataExtraction; import iped.parsers.util.ChildPornHashLookup; -import iped.parsers.util.ExportFolder; import iped.parsers.util.Messages; -import iped.properties.BasicProps; +import iped.parsers.util.P2PUtil; import iped.properties.ExtraProperties; import iped.search.IItemSearcher; import iped.utils.LocalizedFormat; @@ -199,7 +197,7 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, String hash = e.getHash(); metadata.add(ExtraProperties.SHARED_HASHES, hash); List hashSets = ChildPornHashLookup.lookupHash(EDONKEY, hash); - item = searchItemInCase(searcher, EDONKEY, e.getHash()); + item = P2PUtil.searchItemInCase(searcher, EDONKEY, e.getHash()); if(item != null) { hashSets = ChildPornHashLookup.lookupHashAndMerge(EDONKEY, hash, hashSets); } @@ -241,7 +239,7 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.characters(cells.get(j)); else { if (item != null) { - printNameWithLink(xhtml, item, e.getName()); + P2PUtil.printNameWithLink(xhtml, item, e.getName()); cells.set(cells.size() - 1, strYes); } else { xhtml.characters(e.getName()); @@ -262,42 +260,6 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.endDocument(); } - public static IItemReader searchItemInCase(IItemSearcher searcher, String hashAlgo, String hash) { - if (searcher == null) { - return null; - } - List items = searcher.search(hashAlgo + ":" + hash); //$NON-NLS-1$ - if (items == null || items.isEmpty()) { - return null; - } - return items.get(0); - } - - public static void printNameWithLink(XHTMLContentHandler xhtml, IItemReader item, String name) throws SAXException { - String hashPath = getPathFromHash(new File("../../../../", ExportFolder.getExportPath()), //$NON-NLS-1$ - item.getHash(), item.getExt()); - - AttributesImpl attributes = new AttributesImpl(); - attributes.addAttribute("", "onclick", "onclick", "CDATA", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - "app.open(\"" + BasicProps.HASH + ":" + item.getHash() + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - attributes.addAttribute("", "href", "href", "CDATA", hashPath); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - xhtml.startElement("a", attributes); //$NON-NLS-1$ - xhtml.characters(name); - xhtml.endElement("a"); //$NON-NLS-1$ - } - - private static String getPathFromHash(File baseDir, String hash, String ext) { - if (hash == null || hash.length() < 2) - return ""; //$NON-NLS-1$ - StringBuilder path = new StringBuilder(); - hash = hash.toUpperCase(); - path.append(hash.charAt(0)).append('/'); - path.append(hash.charAt(1)).append('/'); - path.append(hash).append('.').append(ext); - File result = new File(baseDir, path.toString()); - return result.getPath(); - } - private long toSum(long v) { return v == -1 ? 0 : v; } diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/PartMetParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/PartMetParser.java index 94b5ed9888..755d746a48 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/PartMetParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/emule/PartMetParser.java @@ -30,6 +30,7 @@ import iped.parsers.util.BeanMetadataExtraction; import iped.parsers.util.ChildPornHashLookup; import iped.parsers.util.Messages; +import iped.parsers.util.P2PUtil; import iped.properties.ExtraProperties; import iped.search.IItemSearcher; import iped.utils.LocalizedFormat; @@ -116,7 +117,7 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, int hashDBHits = 0; List hashSets = ChildPornHashLookup.lookupHash(KnownMetParser.EDONKEY, e.getHash()); - IItemReader item = KnownMetParser.searchItemInCase(searcher, KnownMetParser.EDONKEY, e.getHash()); + IItemReader item = P2PUtil.searchItemInCase(searcher, KnownMetParser.EDONKEY, e.getHash()); if (item != null) hashSets = ChildPornHashLookup.lookupHashAndMerge(item.getHash(), hashSets); if (hashSets != null && !hashSets.isEmpty()) @@ -131,7 +132,7 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, xhtml.endElement("td"); xhtml.startElement("td", "class", "b"); if (item != null) - KnownMetParser.printNameWithLink(xhtml, item, e.getName()); + P2PUtil.printNameWithLink(xhtml, item, e.getName()); else xhtml.characters(e.getName()); xhtml.endElement("td"); diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/LibraryFile.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/LibraryFile.java index 7bbbb16277..ab4e446756 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/LibraryFile.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/LibraryFile.java @@ -29,8 +29,8 @@ import org.xml.sax.helpers.AttributesImpl; import iped.data.IItemReader; -import iped.parsers.emule.KnownMetParser; import iped.parsers.util.ChildPornHashLookup; +import iped.parsers.util.P2PUtil; import iped.search.IItemSearcher; /** @@ -233,9 +233,9 @@ private void printTd(XHTMLContentHandler html, IItemSearcher searcher, Object... html.startElement("td"); //$NON-NLS-1$ if (o != null) { if (col == 1) { - IItemReader item = KnownMetParser.searchItemInCase(searcher, "md5", md5); + IItemReader item = P2PUtil.searchItemInCase(searcher, "md5", md5); if (item != null) { - KnownMetParser.printNameWithLink(html, item, name); + P2PUtil.printNameWithLink(html, item, name); foundInCase = true; } else { html.characters(name); diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/ShareazaDownloadParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/ShareazaDownloadParser.java index c4788555ec..5d73170ed8 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/ShareazaDownloadParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/shareaza/ShareazaDownloadParser.java @@ -1,7 +1,6 @@ package iped.parsers.shareaza; import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; @@ -15,7 +14,6 @@ import java.util.Collections; import java.util.Date; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.apache.tika.exception.TikaException; @@ -36,9 +34,9 @@ import iped.data.IItemReader; import iped.parsers.util.ChildPornHashLookup; -import iped.parsers.util.ExportFolder; import iped.parsers.util.Messages; import iped.parsers.util.MetadataUtil; +import iped.parsers.util.P2PUtil; import iped.properties.BasicProps; import iped.properties.ExtraProperties; import iped.search.IItemSearcher; @@ -215,7 +213,7 @@ public void processSDFile(InputStream inputStreamFile, ContentHandler handler, X addLine(xhtml, "SHA1: " + sha1); hashSets.addAll(ChildPornHashLookup.lookupHash(HASH_SHA1, sha1)); if (item == null) { - item = searchItemInCase(searcher, HASH_SHA1, sha1); + item = P2PUtil.searchItemInCase(searcher, HASH_SHA1, sha1); } } @@ -237,7 +235,7 @@ public void processSDFile(InputStream inputStreamFile, ContentHandler handler, X addLine(xhtml, "MD5: " + md5); hashSets.addAll(ChildPornHashLookup.lookupHash(HASH_MD5, md5)); if (item == null) { - item = searchItemInCase(searcher, HASH_MD5, md5); + item = P2PUtil.searchItemInCase(searcher, HASH_MD5, md5); } } @@ -253,7 +251,7 @@ public void processSDFile(InputStream inputStreamFile, ContentHandler handler, X addLine(xhtml, "EDONKEY: " + edonkey); hashSets.addAll(ChildPornHashLookup.lookupHash(HASH_EDONKEY, edonkey)); if (item == null) { - item = searchItemInCase(searcher, HASH_EDONKEY, edonkey); + item = P2PUtil.searchItemInCase(searcher, HASH_EDONKEY, edonkey); } } @@ -284,7 +282,7 @@ public void processSDFile(InputStream inputStreamFile, ContentHandler handler, X attributes.addAttribute("", "name", "name", "CDATA", item.getHash().toUpperCase()); xhtml.startElement("span", attributes); - printNameWithLink(xhtml, item, item.getName()); + P2PUtil.printNameWithLink(xhtml, item, item.getName()); xhtml.endElement("span"); xhtml.newline(); xhtml.newline(); @@ -421,12 +419,12 @@ public void processSDFile(InputStream inputStreamFile, ContentHandler handler, X sbFile.append("File: " + "\n"); long nTotal = read8Bytes(buffer); - long nRemaning = read8Bytes(buffer); + long nRemaining = read8Bytes(buffer); int nFragments = read4Bytes(buffer); - totalDownloaded = nTotal - nRemaning; + totalDownloaded = nTotal - nRemaining; sbFile.append(" Total Size: " + nTotal + "\n"); - sbFile.append(" Total Remaning: " + nRemaning + "\n"); + sbFile.append(" Total Remaining: " + nRemaining + "\n"); sbFile.append(" Total Downloaded: " + totalDownloaded + "\n"); sbFile.append(" Number of Fragments: " + nFragments + "\n"); @@ -614,7 +612,7 @@ public void processSDFile(InputStream inputStreamFile, ContentHandler handler, X // TIGER HASH DATABASE int pTreeSize = read4Bytes(buffer); if (pTreeSize > 0) { - sbTigerDB.append("TIGER Hash Database"); + sbTigerDB.append("TIGER Hash Database:"+ "\n"); sbTigerDB.append(" Tree Size: " + pTreeSize + "\n"); int hashTigerDatabaseSize = hashTigerDataBaseSize(pTreeSize); @@ -971,42 +969,6 @@ public String getHash(MessageDigest digest) { return sb.toString(); } - public static void printNameWithLink(XHTMLContentHandler xhtml, IItemReader item, String name) throws SAXException { - String hashPath = getPathFromHash(new File("../../../../", ExportFolder.getExportPath()), //$NON-NLS-1$ - item.getHash(), item.getExt()); - - AttributesImpl attributes = new AttributesImpl(); - attributes.addAttribute("", "onclick", "onclick", "CDATA", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - "app.open(\"" + BasicProps.HASH + ":" + item.getHash() + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - attributes.addAttribute("", "href", "href", "CDATA", hashPath); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - xhtml.startElement("a", attributes); //$NON-NLS-1$ - xhtml.characters(name); - xhtml.endElement("a"); //$NON-NLS-1$ - } - - private static String getPathFromHash(File baseDir, String hash, String ext) { - if (hash == null || hash.length() < 2) - return ""; //$NON-NLS-1$ - StringBuilder path = new StringBuilder(); - hash = hash.toUpperCase(); - path.append(hash.charAt(0)).append('/'); - path.append(hash.charAt(1)).append('/'); - path.append(hash).append('.').append(ext); - File result = new File(baseDir, path.toString()); - return result.getPath(); - } - - public static IItemReader searchItemInCase(IItemSearcher searcher, String hashAlgo, String hash) { - if (searcher == null) { - return null; - } - List items = searcher.search(hashAlgo + ":" + hash); //$NON-NLS-1$ - if (items == null || items.isEmpty()) { - return null; - } - return items.get(0); - } - private void addLine(XHTMLContentHandler xhtml, String value) throws SAXException { xhtml.characters(value); xhtml.newline(); diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/ReportGenerator.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/ReportGenerator.java index ff1b501576..c8bfde02aa 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/ReportGenerator.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/ReportGenerator.java @@ -59,7 +59,7 @@ public void endHTMLDocument(PrintWriter out) { out.println(""); //$NON-NLS-1$ } - public InputStream createHTMLReport(List entries) { + public InputStream createHTMLReport(List entries, Exception entriesReadError) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); PrintWriter out = new PrintWriter(new OutputStreamWriter(bout, StandardCharsets.UTF_8)); // $NON-NLS-1$ @@ -90,6 +90,8 @@ public InputStream createHTMLReport(List entries) { out.print(""); + out.print("Error during additional entries read:" + entriesReadError.getMessage()); + endHTMLDocument(out); out.close(); @@ -97,7 +99,8 @@ public InputStream createHTMLReport(List entries) { } - public InputStream createCSVReport(List entries, TemporaryResources tmp) throws IOException { + public InputStream createCSVReport(List entries, TemporaryResources tmp, Exception entriesReadError) + throws IOException { Path path = tmp.createTempFile(); try (OutputStream os = Files.newOutputStream(path); Writer writer = new OutputStreamWriter(os, StandardCharsets.UTF_8); diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/UsnJrnlParser.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/UsnJrnlParser.java index 16484523c5..86018594e3 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/UsnJrnlParser.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/usnjrnl/UsnJrnlParser.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -25,6 +26,7 @@ import iped.data.IItemReader; import iped.io.SeekableInputStream; import iped.parsers.standard.StandardParser; +import iped.parsers.util.MetadataUtil; import iped.properties.BasicProps; import iped.properties.ExtraProperties; import iped.search.IItemSearcher; @@ -55,6 +57,8 @@ public enum ReportType { public static final MediaType USNJRNL_REPORT_CSV = MediaType.parse("application/x-usnjournal-report-csv"); public static final MediaType USNJRNL_REGISTRY = MediaType.parse("application/x-usnjournal-registry"); + static final String USN_REASON_PREFIX = "usnJrnl:"; + private static Set SUPPORTED_TYPES = MediaType.set(USNJRNL_$J); @Override @@ -136,7 +140,8 @@ public UsnJrnlEntry readEntry(SeekableInputStream in) throws IOException { return null; } - private void createReport(ArrayList entries, int n, ParseContext context, ContentHandler handler) + private void createReport(ArrayList entries, int n, ParseContext context, ContentHandler handler, + Exception entriesReadError) throws SAXException, IOException { ReportGenerator rg = new ReportGenerator(); EmbeddedDocumentExtractor extractor = context.get(EmbeddedDocumentExtractor.class, @@ -149,11 +154,11 @@ private void createReport(ArrayList entries, int n, ParseContext c try (TemporaryResources tmp = new TemporaryResources()) { if (reportType == ReportType.CSV) { cMetadata.set(StandardParser.INDEXER_CONTENT_TYPE, USNJRNL_REPORT_CSV.toString()); - is = rg.createCSVReport(entries, tmp); + is = rg.createCSVReport(entries, tmp, entriesReadError); } else if (reportType == ReportType.HTML) { cMetadata.set(StandardParser.INDEXER_CONTENT_TYPE, USNJRNL_REPORT_HTML.toString()); - is = rg.createHTMLReport(entries); + is = rg.createHTMLReport(entries, entriesReadError); name += " " + n; } @@ -179,12 +184,15 @@ private void createReport(ArrayList entries, int n, ParseContext c String[] props = ReportGenerator.cols; - metadataItem.set(TikaCoreProperties.CREATED, rg.timeFormat.format(entry.getFileTime())); metadataItem.set(ReportGenerator.cols[0], String.format("0x%016X", entry.getOffset())); metadataItem.set(props[1], entry.getFileName()); metadataItem.set(props[2], entry.getFullPath()); metadataItem.set(props[3], Long.toString(entry.getUSN())); + String formatedDate = rg.timeFormat.format(entry.getFileTime()); for (String value : entry.getReasons()) { + value = value.toLowerCase(); + MetadataUtil.setMetadataType(USN_REASON_PREFIX + value, Date.class); + metadataItem.set(USN_REASON_PREFIX + value, formatedDate); metadataItem.add(props[5], value); } metadataItem.set(props[6], "0x" + Util.byteArrayToHex(entry.getMftRef())); @@ -231,28 +239,33 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, int n = 1; IItemSearcher searcher = context.get(IItemSearcher.class); IItemReader item = context.get(IItemReader.class); + Exception entriesReadError = null; try (SeekableInputStream sis = item.getSeekableInputStream()) { jumpZeros(sis, 0, sis.size()); - while (findNextEntry(sis)) { - UsnJrnlEntry u = readEntry(sis); - // do not insert empty registries in the list - if (u == null) { - continue; - } - - entries.add(u); - - if (entries.size() % MAX_ENTRIES == 0) { - int baseIndex = ((entries.size() / MAX_ENTRIES) - 1) * MAX_ENTRIES; - rebuildFullPaths(entries.subList(baseIndex, baseIndex + MAX_ENTRIES), searcher, item); - } - - // limits the html table size - if (entries.size() == MAX_ENTRIES && reportType == ReportType.HTML) { - createReport(entries, n, context, handler); - entries.clear(); - n++; + try { + while (findNextEntry(sis)) { + UsnJrnlEntry u = readEntry(sis); + // do not insert empty registries in the list + if (u == null) { + continue; + } + + entries.add(u); + + if (entries.size() % MAX_ENTRIES == 0) { + int baseIndex = ((entries.size() / MAX_ENTRIES) - 1) * MAX_ENTRIES; + rebuildFullPaths(entries.subList(baseIndex, baseIndex + MAX_ENTRIES), searcher, item); + } + + // limits the html table size + if (entries.size() == MAX_ENTRIES && reportType == ReportType.HTML) { + createReport(entries, n, context, handler, entriesReadError); + entries.clear(); + n++; + } } + } catch (Exception e) { + entriesReadError = e; } } @@ -261,7 +274,18 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, int baseIndex = (entries.size() / MAX_ENTRIES) * MAX_ENTRIES; rebuildFullPaths(entries.subList(baseIndex, entries.size()), searcher, item); } - createReport(entries, n, context, handler); + createReport(entries, n, context, handler, entriesReadError); + } + if (entriesReadError instanceof TikaException) { + throw (TikaException) entriesReadError; + } else if (entriesReadError instanceof IOException) { + throw (IOException) entriesReadError; + } else if (entriesReadError instanceof SAXException) { + throw (SAXException) entriesReadError; + } else if (entriesReadError instanceof RuntimeException) { + throw (RuntimeException) entriesReadError; + } else if (entriesReadError != null) { + throw new RuntimeException(entriesReadError); } } diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/P2PUtil.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/P2PUtil.java new file mode 100644 index 0000000000..7d32998f8a --- /dev/null +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/P2PUtil.java @@ -0,0 +1,50 @@ +package iped.parsers.util; + +import java.io.File; +import java.util.List; + +import org.apache.tika.sax.XHTMLContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import iped.data.IItemReader; +import iped.properties.BasicProps; +import iped.search.IItemSearcher; + +public class P2PUtil { + public static IItemReader searchItemInCase(IItemSearcher searcher, String hashAlgo, String hash) { + if (searcher == null || hash == null || hash.isBlank()) { + return null; + } + List items = searcher.search(searcher.escapeQuery(hashAlgo) + ":" + hash); + if (items == null || items.isEmpty()) { + return null; + } + return items.get(0); + } + + public static void printNameWithLink(XHTMLContentHandler xhtml, IItemReader item, String name) throws SAXException { + String hashPath = getPathFromHash(new File("../../../../", ExportFolder.getExportPath()), item.getHash(), + item.getExt()); + AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute("", "onclick", "onclick", "CDATA", + "app.open(\"" + BasicProps.HASH + ":" + item.getHash() + "\")"); + attributes.addAttribute("", "href", "href", "CDATA", hashPath); + xhtml.startElement("a", attributes); + xhtml.characters(name); + xhtml.endElement("a"); + } + + private static String getPathFromHash(File baseDir, String hash, String ext) { + if (hash == null || hash.length() < 2) { + return ""; + } + StringBuilder path = new StringBuilder(); + hash = hash.toUpperCase(); + path.append(hash.charAt(0)).append('/'); + path.append(hash.charAt(1)).append('/'); + path.append(hash).append('.').append(ext); + File result = new File(baseDir, path.toString()); + return result.getPath(); + } +} diff --git a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/Util.java b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/Util.java index 668c5a65d6..45ba65bae6 100644 --- a/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/Util.java +++ b/iped-parsers/iped-parsers-impl/src/main/java/iped/parsers/util/Util.java @@ -117,7 +117,7 @@ private static String decodeUTF16OrUTF8(byte[] data) throws UnsupportedEncodingE return result; } - public static String decodeUnknowCharset(byte[] data) { + public static String decodeUnknownCharset(byte[] data) { try { return decodeUTF16OrUTF8(data); @@ -161,7 +161,7 @@ private static String decodeUnknownCharsetTika(byte[] data, boolean useFallbackD } catch (IOException | TikaException e) { if (useFallbackDetection) { - return decodeUnknowCharset(data); + return decodeUnknownCharset(data); } else { return decodeWindows1252(data); } diff --git a/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/ocr/OCRParserTest.java b/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/ocr/OCRParserTest.java index efdb621c59..4e1a417629 100644 --- a/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/ocr/OCRParserTest.java +++ b/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/ocr/OCRParserTest.java @@ -43,7 +43,7 @@ public class OCRParserTest { @BeforeClass public static void setUpTool() throws IOException { if (osName.startsWith("windows")) { - String repoPath = "tesseract/tesseract-zip/5.3.2-24-g3922/tesseract-zip-5.3.2-24-g3922.zip"; + String repoPath = "tesseract/tesseract-zip/5.3.2-24-g3922_1/tesseract-zip-5.3.2-24-g3922_1.zip"; RepoToolDownloader.unzipFromUrl(repoPath, testRoot + "/tmp_tools/"); System.setProperty(OCRParser.TOOL_PATH_PROP, testRoot + "/tmp_tools/tesseract/"); } diff --git a/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/AbstractPkgTest.java b/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/AbstractPkgTest.java index d8b29dca33..7919b1827d 100644 --- a/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/AbstractPkgTest.java +++ b/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/AbstractPkgTest.java @@ -38,6 +38,7 @@ protected static class EmbeddedUsnParser extends AbstractParser { protected List contenttype = new ArrayList(); protected List title = new ArrayList(); protected List created = new ArrayList(); + protected List metadata = new ArrayList(); public Set getSupportedTypes(ParseContext context) { return (new AutoDetectParser()).getSupportedTypes(context); @@ -55,6 +56,8 @@ public void parse(InputStream stream, ContentHandler handler, Metadata metadata, if (metadata.get(TikaCoreProperties.CREATED) != null) created.add(metadata.get(TikaCoreProperties.CREATED)); + + this.metadata.add(metadata); } } diff --git a/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/UsnJrnlParserTest.java b/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/UsnJrnlParserTest.java index 919a17d147..5bfa86d603 100644 --- a/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/UsnJrnlParserTest.java +++ b/iped-parsers/iped-parsers-impl/src/test/java/iped/parsers/usnjrnl/UsnJrnlParserTest.java @@ -50,56 +50,44 @@ public void testUsnJrnlParsingHTML() throws IOException, SAXException, TikaExcep assertEquals(3, usntracker.contenttype.size()); assertEquals(3085, usntracker.title.size()); - assertEquals(3084, usntracker.created.size()); + // assertEquals(3084, usntracker.created.size()); assertEquals("application/x-usnjournal-report-csv", usntracker.contenttype.get(0)); assertEquals("application/x-usnjournal-registry", usntracker.contenttype.get(2)); - Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(0)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(1)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(2)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(3)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(3082)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:55:03", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:55:03", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:55:03", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(3083)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:55:03", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:55:03", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:55:03", df.format(date)); + Date date; + Metadata metadata; + String[] reasons; + + for (int i = 1; i <= 4; i++) { + metadata = usntracker.metadata.get(i); + reasons = metadata.getValues("Reasons"); + for (String reason : reasons) { + date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .parse(metadata.get(UsnJrnlParser.USN_REASON_PREFIX + reason)); + if (getVersion() < 9) + assertEquals("20/05/2021 14:52:07", df.format(date)); + if (getVersion() >= 9 && getVersion() < 12) + assertEquals("20 de mai de 2021 14:52:07", df.format(date)); + if (getVersion() >= 12) + assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); + } + } + + for (int i = 3082; i <= 3083; i++) { + metadata = usntracker.metadata.get(i); + reasons = metadata.getValues("Reasons"); + for (String reason : reasons) { + date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .parse(metadata.get(UsnJrnlParser.USN_REASON_PREFIX + reason)); + if (getVersion() < 9) + assertEquals("20/05/2021 14:55:03", df.format(date)); + if (getVersion() >= 9 && getVersion() < 12) + assertEquals("20 de mai de 2021 14:55:03", df.format(date)); + if (getVersion() >= 12) + assertEquals("20 de mai. de 2021 14:55:03", df.format(date)); + } + } assertEquals("USN Journal Report", usntracker.title.get(0)); assertEquals("USN journal Entry 6098518016", usntracker.title.get(1)); @@ -131,58 +119,40 @@ public void testUsnJrnlParsingCSV() throws IOException, SAXException, TikaExcept assertEquals(3, usntracker.contenttype.size()); assertEquals(3085, usntracker.title.size()); - assertEquals(3084, usntracker.created.size()); - assertEquals("application/x-usnjournal-report-csv", usntracker.contenttype.get(0)); - assertEquals("application/x-usnjournal-registry", usntracker.contenttype.get(2)); + Date date; + Metadata metadata; + String[] reasons; + + for (int i = 1; i <= 4; i++) { + metadata = usntracker.metadata.get(i); + reasons = metadata.getValues("Reasons"); + for (String reason : reasons) { + date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .parse(metadata.get(UsnJrnlParser.USN_REASON_PREFIX + reason)); + if (getVersion() < 9) + assertEquals("20/05/2021 14:52:07", df.format(date)); + if (getVersion() >= 9 && getVersion() < 12) + assertEquals("20 de mai de 2021 14:52:07", df.format(date)); + if (getVersion() >= 12) + assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); + } + } - Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(0)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(1)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(2)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(3)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:52:07", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:52:07", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:52:07", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(3082)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:55:03", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:55:03", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:55:03", df.format(date)); - - date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(usntracker.created.get(3083)); - if (getVersion() < 9) - assertEquals("20/05/2021 14:55:03", df.format(date)); - if (getVersion() >= 9 && getVersion() < 12) - assertEquals("20 de mai de 2021 14:55:03", df.format(date)); - if (getVersion() >= 12) - assertEquals("20 de mai. de 2021 14:55:03", df.format(date)); + for (int i = 3082; i <= 3083; i++) { + metadata = usntracker.metadata.get(i); + reasons = metadata.getValues("Reasons"); + for (String reason : reasons) { + date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .parse(metadata.get(UsnJrnlParser.USN_REASON_PREFIX + reason)); + if (getVersion() < 9) + assertEquals("20/05/2021 14:55:03", df.format(date)); + if (getVersion() >= 9 && getVersion() < 12) + assertEquals("20 de mai de 2021 14:55:03", df.format(date)); + if (getVersion() >= 12) + assertEquals("20 de mai. de 2021 14:55:03", df.format(date)); + } + } assertEquals("USN Journal Report", usntracker.title.get(0)); assertEquals("USN journal Entry 6098518016", usntracker.title.get(1)); diff --git a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/MetadataViewer.java b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/MetadataViewer.java index 3fdd964172..6a83ea1fd1 100644 --- a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/MetadataViewer.java +++ b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/MetadataViewer.java @@ -6,13 +6,17 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardOpenOption; +import java.text.DateFormat; import java.text.DecimalFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; +import java.util.Date; import java.util.List; import java.util.Set; +import java.util.TimeZone; import javax.swing.UIManager; @@ -27,6 +31,7 @@ import iped.properties.BasicProps; import iped.properties.ExtraProperties; import iped.properties.MediaTypes; +import iped.utils.DateUtil; import iped.utils.EmojiUtil; import iped.utils.LocalizedFormat; import iped.utils.SimpleHTMLEncoder; @@ -45,7 +50,8 @@ public abstract class MetadataViewer extends AbstractViewer { - private DecimalFormat df = LocalizedFormat.getDecimalInstance("#,###.############"); //$NON-NLS-1$ + private final DecimalFormat df = LocalizedFormat.getDecimalInstance("#,###.############"); //$NON-NLS-1$ + private final DateFormat dateFormat = new SimpleDateFormat(Messages.getString("MetadataViewer.DateFormat")); private TabPane tabPane; private JFXPanel jfxPanel; @@ -68,6 +74,8 @@ public int compare(String a, String b) { public MetadataViewer() { super(new GridLayout()); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + jfxPanel = new JFXPanel(); for (int i = 0; i < 3; i++) htmlViewers.add(new HtmlViewer()); @@ -252,6 +260,12 @@ private void fillMetadata(StringBuilder sb, Metadata metadata) { val = metadata.get(meta); if (isNumeric(meta)) { val = df.format(Double.valueOf(val)); + } else { + try { + Date date = DateUtil.stringToDate(val); + val = dateFormat.format(date); + } catch (Exception e) { + } } } else { String[] vals = metadata.getValues(meta); @@ -259,6 +273,25 @@ private void fillMetadata(StringBuilder sb, Metadata metadata) { for (int i = 0; i < vals.length; i++) { vals[i] = df.format(Double.valueOf(vals[i])); } + } else { + boolean isDate = true; + for (int i = 0; i < vals.length; i++) { + try { + DateUtil.stringToDate(vals[i]); + } catch (Exception e) { + isDate = false; + break; + } + } + if (isDate) { + for (int i = 0; i < vals.length; i++) { + try { + Date date = DateUtil.stringToDate(vals[i]); + vals[i] = dateFormat.format(date); + } catch (Exception e) { + } + } + } } val = Arrays.asList(vals).toString(); } @@ -277,10 +310,10 @@ private void fillBasicProps(StringBuilder sb, IItemReader item) { fillProp(sb, BasicProps.TYPE, item.getType()); fillProp(sb, BasicProps.DELETED, item.isDeleted()); fillProp(sb, BasicProps.CATEGORY, item.getCategorySet()); - fillProp(sb, BasicProps.CREATED, item.getCreationDate()); - fillProp(sb, BasicProps.MODIFIED, item.getModDate()); - fillProp(sb, BasicProps.ACCESSED, item.getAccessDate()); - fillProp(sb, BasicProps.CHANGED, item.getChangeDate()); + fillProp(sb, BasicProps.CREATED, formatDate(item.getCreationDate())); + fillProp(sb, BasicProps.MODIFIED, formatDate(item.getModDate())); + fillProp(sb, BasicProps.ACCESSED, formatDate(item.getAccessDate())); + fillProp(sb, BasicProps.CHANGED, formatDate(item.getChangeDate())); fillProp(sb, BasicProps.HASH, item.getHash()); fillProp(sb, BasicProps.PATH, item.getPath()); sb.append(""); //$NON-NLS-1$ @@ -347,6 +380,10 @@ private void appendCollapsibleString(StringBuilder sb, String str) { } } + private String formatDate(Date date) { + return date == null ? null : dateFormat.format(date); + } + private String format(Object value) { if (value instanceof Number) { return df.format(Double.valueOf(((Number) value).doubleValue())); diff --git a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/components/HitsTable.java b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/components/HitsTable.java index 6f95cdab5c..41a8c10bce 100644 --- a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/components/HitsTable.java +++ b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/components/HitsTable.java @@ -20,7 +20,6 @@ import java.awt.Dimension; -import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.table.AbstractTableModel; @@ -36,7 +35,6 @@ public HitsTable(AbstractTableModel tableModel) { setAutoResizeMode(JTable.AUTO_RESIZE_OFF); getTableHeader().setPreferredSize(new Dimension(0, 0)); setShowGrid(false); - ((JComponent) getDefaultRenderer(Boolean.class)).setOpaque(true); } @Override diff --git a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LOExtractor.java b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LOExtractor.java index 6de5ea345d..e726b1ff6f 100644 --- a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LOExtractor.java +++ b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LOExtractor.java @@ -23,7 +23,7 @@ public class LOExtractor extends CancelableWorker { private File output, input; - private ProgressDialog progressMonitor; + private volatile ProgressDialog progressMonitor; private int progress = 0, numSubitens = 2876;// TODO obter número de itens automaticamente private boolean completed = false; @@ -32,7 +32,7 @@ public LOExtractor(File input, File output) { this.input = input; } - public boolean decompressLO() { + public boolean decompressLO(boolean isNogui) { try { if (output.exists()) { @@ -44,14 +44,16 @@ public boolean decompressLO() { } if (input.exists()) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - progressMonitor = new ProgressDialog(null, LOExtractor.this); - progressMonitor.setMaximum(numSubitens); - progressMonitor.setNote(Messages.getString("LOExtractor.DecompressingLO")); //$NON-NLS-1$ - } - }); + if (!isNogui) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + progressMonitor = new ProgressDialog(null, LOExtractor.this); + progressMonitor.setMaximum(numSubitens); + progressMonitor.setNote(Messages.getString("LOExtractor.DecompressingLO")); //$NON-NLS-1$ + } + }); + } try (ZipFile zip = new ZipFile(input)) { Enumeration e = zip.getEntries(); @@ -69,15 +71,17 @@ public void run() { if (++progress == numSubitens) completed = true; - progressMonitor.setProgress(progress); - - if (progressMonitor.isCanceled()) - break; + if (progressMonitor != null) { + progressMonitor.setProgress(progress); + + if (progressMonitor.isCanceled()) + break; + } } } } - if (!progressMonitor.isCanceled()) { + if (progressMonitor != null && !progressMonitor.isCanceled()) { progressMonitor.close(); } diff --git a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LibreOfficeFinder.java b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LibreOfficeFinder.java index 51170b7a23..c23283bb80 100644 --- a/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LibreOfficeFinder.java +++ b/iped-viewers/iped-viewers-impl/src/main/java/iped/viewers/util/LibreOfficeFinder.java @@ -36,7 +36,7 @@ public LibreOfficeFinder(File baseFolder) { baseDir = baseFolder; } - public String getLOPath() { + public String getLOPath(boolean isNogui) { if (detectedPath == null) { detectedPath = System.getProperty("libreOfficePath"); if (detectedPath != null) @@ -62,7 +62,7 @@ public String getLOPath() { if (winPathLO.exists() || compressedLO.exists()) { // $NON-NLS-1$ //$NON-NLS-2$ LOExtractor extractor = new LOExtractor(compressedLO, winPathLO); - if (extractor.decompressLO()) + if (extractor.decompressLO(isNogui)) detectedPath = winPathLO.getAbsolutePath(); } }