Categories
Llibres Programació C# Javascript Hardware Fotografia Pelis Anglès Android Series Excursions Cites SQLServer Software HTML/CSS Politikon Estilogràfiques Tintes
Contacte: Àlex
|
OnKeyup vs. Onchange vs. OnInput |
Tenia un bug curiós. En un control input normal d'introducció de text es calculava una funció cada cop que es modificava el valor. Clar, en un principi el vaig posar en el onchange però això no era suficient, perque aquest event només es dispara quan l'usuari abandona el control. Aleshores vaig posar la funció en l'event OnKeyup i llestos, cada cop que l'usuari tecleja, doncs es calcula la funció. Segur? L'usuari es queixa que el tema no acaba de funcionar... vinga a fer proves i en local funciona perfectament, doncs cal anar a veure com treballa l'usuari. Resulta que és l'autocomplete que no dispara el keyup, vist el tema també he fet: botó dret sobre el control i escollir "pegar" i es posa el valor al control sense disparar l'event. Hi ha l'opció de posar al control input l'atribut autocomplete="off", però hi ha una manera millor, és el OnInput que es dispara cada cop que el control rep valors diferents, indepedenment de l'origen, ja sigui "pegar" o "autocomplete". A partir d'ara OnInput .
<input tabindex="9" accesskey="9" id="nom_del_control" name="nom_del_control" size="12" maxlength="12" type="text" oninput="javascript: Calculo();" value="el_valor_aqui" />
| #26/11/2024 10:38 Programació HTML/CSS Autor: Alex Canalda
|
Funció per comptar l'enessima aparició d'un caracter en SQL Server |
Fent coses he necessitat comptar paraules en una frase. Aquesta frase és un camp en una BBDD d'SQL Server. Allò que et diuen: "talla la frase a partir de la 6 paraula". Doncs cal fer primer una funció d'usuari a SQL Server que compti quants espais ha saltat i et doni la posició de n-essim espai.
USE [LaTevaBBDD]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[CHARINDEX2]
(
@TargetStr varchar(8000),
@SearchedStr varchar(8000),
@Occurrence int
)
RETURNS int
as
begin
declare @pos int, @counter int, @ret int
set @pos = CHARINDEX(@TargetStr, @SearchedStr)
set @counter = 1
if @Occurrence = 1 set @ret = @pos
else
begin
while (@counter < @Occurrence)
begin
select @ret = CHARINDEX(@TargetStr, @SearchedStr, @pos + 1)
set @counter = @counter + 1
if @ret <> 0 set @pos = @ret
end
end
RETURN(@ret)
end
La gracia d'aquesta versió vs. la que circula per Internet, es que si tu demanes la 8 posició i només té 6, retorna 0 enlloc d'un número aleatori. Un cop feta la funció cal posar aquesta sentència:
update UnaTaula set UnCamp=LEFT(UnCamp, dbo.CHARINDEX2(' ', UnCamp, 9)-1) WHERE dbo.CHARINDEX2(' ', UnCamp, 9)>0
Ja posats, si fem tractament de strings en SQLServer el REPLACE va força bé, però si es vol fer substitucions que estiguin a l'inici de la cadena de text:
update UnaTaula set UnCamp=SUBSTRING(UnCamp, 4, LEN(UnCamp)-3) where LEFT(UnCamp, 3)='un '
Feia temps que no trobava coses noves d'SQLServer per fer. Yummi! | #07/02/2023 01:02 Programació SQLServer Autor: Alex Canalda
|
L'objectiu d'un programa d'ordinador |
Fa uns dies que penso en això. Per alguns pot ser resoldre un problema, per altres gestionar unes dades... I a més a més molts creuen que ha de ser eficient, de fàcil manteniment, que es pugui entendre el codi, etc... Però en realitat tot això és mentida.
L'objectiu d'un programa és que algú pagui diners per ell (si aquest algú és una persona, una empresa o un govern ja és igual).
I es ben bé igual que el programa estigui ben fet, que funcioni com el cul (o directament no funcioni) o que el programa estigui a mig fer, tot es igual sempre que aquest pagament es produeixi. He viscut tots aquests casos, treballant a diferents llocs.
Sobretot maximitzar la diferència entre la quantitat cobrada i el que es paga (a.k.a benefici). Aleshores es nota que per cobrar més cal donar una impressió de complexitat que no sempre s'ajusta a la realitat, afegint sigles o tecnologies que potser no afavoreixen al programa però és igual, millor posar-les, segons la moda del moment (tot el que és nou fa pujar el preu...). I posar noms "fashion" a les coses, en anglès si és possible, també. Sempre intentant jugar amb la ignorància de les persones i ofendre la seva vanitat de que haurien d'admetre que no tenen ni idea de que és el que els estàs explicant.
Després cal pagar, a desenvolupadors, perque facin "algo" (si aquest algo funciona potser es podrà dir programa), però clar, que aquests desenvolupadors tinguin coneixements per fer-ho, o ganes de fer-ho mmmmm...
I poc a poc es va formant un embolic de gent amb tasques, mmmm... rares, que no són ben bé programar. I el client veient com va el tema, també fuig escaldat, i posa a gent a vigilar i la bola es fa gran. Així gira el mon. Però dins d'aquesta bola no cal perdre de vista l'objectiu.
Aleshores, he decidit considerar-me una mini-empresa que ven un servei. Desprès d'anys de fer-ho bé, al final ni pagat ni agraït, aleshores per que matar-se? Estic veient que fent-ho no tan bé al final no passa res. Si l'aplicació enlloc de milisegons té temps de resposta de varis segons... Ningú ho aprecia i la meva mini-empresa cobra el mateix. He vist codi que pffffff, i penso ja posaran un servidor més potent, amb més RAM, total, al cap d'uns anys, s'ha de fer la típica re-enginyeria, llençar tot el que és antic i tornar-ho a fer segons la moda del moment... per repetir el cicle i complir l'objectiu. | #13/04/2022 17:32 Programació Autor: Alex Canalda
|
Mantenibilitat del codi |
Vaig acumulant anys, i clar, codi antic. Codi que vaig fer jo, codi que van fer altres, però codi al fi i al cap. És com parlar llengües mortes, coses antigues i no tan antigues, inclús coses noves però que canvien les especificacions i s'han de modificar. Aquestes modificacions, ja sigui per millorar o per corregir les ha de fer algú, i últimament aquest algú sóc jo.
I m'adono del que al meu jo futur li molaria trobar per facilitar-me la vida.
- Mai, mai, mai, (potser no m'he expressat bé), mai, fer servir IF immediats, i menys aniuats. Es a dir això totalment prohibit:
var Servicer = filter.Servicer == GlobalConstant.DefaultId.ToString() || filter.Servicer.IsNullOrBlank()
? "" : filter.Servicer == GlobalConstant.ServicerNO
? String.Format(" AND (DEM.SERVICER = '{0}' OR DEM.SERVICER IS NULL)", filter.Servicer) : String.Format(" AND DEM.SERVICER = '{0}'", filter.Servicer);
En realitat, és una sola línia. A l'hora de depurar i veure per on va... mmmm... per on va? No hi ha cap premi a qui escrigui menys línies de codi.
- El tipus "var", a veure si un llenguatge és tipat, doncs fes-ho servir.
- Lambda expressions quilomètriques. Prohibides.
model.DatosVol.Where(x=>x.Value.VOL>0).ToList().ForEach(
x => x.Value.VOL_PCT = ((x.Value.VOL * 100)/
model.DatosVol.Where(y=>y.Value.Tipo_Calculo==x.Value.Tipo_Calculo
&& y.Value.Tipo_Contrato==(int)SLAsCliente_TipoContEnum.Global).Sum(y=>GetDividendo(y.Value.VOL))));
Ves i busca un bug, o corregeix algo de la forma de calcular-se... És la típica lluita entre funcionals vs procedurals, jo sóc procedural.
- Noms de funcions clars. A ser possible en un sol idioma. Res de dir funcions "TRACTAMENT" o "TRACTAMENT2". Si es pot incloure un comentari de que fa la funció ja és una gran millora.
I podria continuar, però això ja donaria per un altra post. I parlar del rendiment... perque veig que per millorar rendiment és més barat tirar de hardware i tancar els ulls. | #28/02/2022 17:39 Programació C# Autor: Alex Canalda
|
C# - com obrir un fitxer de text sense obtenir caracters estranys |
Seguim amb els petits detalls, res gaire complicat, però que molesten. Quan obres un fitxer de text a vegades té caràcters estranys en els accents quan llegeixes les línies. Normalment és la codificació. Per això cal posar-ho en la funció que fa la lectura.
StreamReader reader = new StreamReader(NombreFichero, Encoding.GetEncoding("iso-8859-1"))
| #02/10/2020 15:55 Programació C# Autor: Alex Canalda
|
C# - com ensenyar el format espanyol de la data |
Sempre em despito i mai recordo el format... Ainsss, deu ser l'edat.
DateTime.Now.ToString("dd'/'MM'/'yyyy HH:mm:ss");
| #02/10/2020 15:52 Programació C# Autor: Alex Canalda
|
Javascript: com agafar el valor d'un radiobutton |
A vegades faig programes complicats i sembla que "sàpiga" molt, però no. Avui en dia cal saber unes bases però la resta no cal recordar-ho de memòria, cal saber on trobar-ho i com buscar-ho. Per això hem trobo buscant el mateix de forma repetitiva certs temes. Un d'ells és com recuperar el valor d'un control radiobutton en un formulari des de Javascript (fent servir jQuery). Tenim l'HTML:
<input type="radio" id="Ubicacion" name="ordenarpor" value="Ubicacion" />
<label for="Ubicacion">Ubicacion</label><br />
<input type="radio" id="RefCliente" name="ordenarpor" value="RefCliente" />
<label for="RefCliente">Ref. Cliente</label><br />
<input type="radio" id="FechaEntrada" name="ordenarpor" value="FechaEntrada" />
<label for="FechaEntrada">Fecha entrada</label>
Observar en l'HTML cada radiobutton té un value i un id diferent, el que els lliga i fa que estiguin relacionats és el name. El codi javascript per recollir el valor del radiobutton seleccionat és:
var OrderBy = $('input[name="ordenarpor"]:checked').val();
Job done! | #09/09/2020 18:43 Programació Javascript HTML/CSS Autor: Alex Canalda
|
HTML5 tag button |
Aquests dies de coronavirus i de quedar-se a casa, intentant sobreviure a conviure tots junts en un espai reduït, aprofito per programar coses. Una d'aquestes vaig pensar: ¿I si enlloc de fer servir un tag input type="button", faig servir el tag button directament? I així estava jo molt content d'aquesta idea inspiradora quan de sobte, un cop posat el tag button, li dono i "ups!" la pàgina navega a un altra lloc.
Els formularis que faig en HTML acostumen a funcionar amb AJAX, tant per recuperar dades com per guardar-les i no "naveguen" a cap lloc, la URL no acostuma a canviar, i en el meu codi javascript no hi havia res que modifiqui la URL. Per això em va estranyar que amb el nou tag button sí. Vaig trigar una bona estona fins trobar el que passava. Resulta que la URL on navegava la pàgina era el "action" del formulari (vaig trigar a adonar-me perque els meus formularis tenen el action="/", no tenen). I el que estava fent el botó era un submit del formulari. I com és que el tag button fa un submit si jo no li dic per javascript? Aaaaah...
La resposta està en l'especificació del tag button de HTML5. Curiosament el tag button té l'atribut type i aquest té uns valors curiosos. Observa:
- submit: envia el formulari mitjançant un HTTP Post a l'action del formulari.
- reset: neteja el formulari.
- button: no fa res, només executa el javascript quan es fa l'event click
La punyeteta està en la següent frase de l'especificació:
The missing value default is the Submit Button state.
Es a dir, que si al tag button no li poses un atribut type, aquell botó fa submit. I jo que tinc un munt de buttons en el formulari... no crec que aquest comportament per defecte sigui el millor i que de sobte tots facin submit. Per defecte hauria de ser "button", així ens estalviaríem coses del capità "obvious" al tenir que posar molts tags "button type="button" ...." tu escrius un button no cal dir-li que a més a més és de tipus... mmmmm... deixam pensar... mmmmmm... a sí, tipus button.
| #16/03/2020 16:28 Programació HTML/CSS Autor: Alex Canalda
|
Firma AES CMAC - RFC 4493 |
El 3DES ja va quedant enrera i ara cal una nova firma. Clar, ha d'estar basada en el successor del 3DES, el AES. Per això m'ha tocat implementar la firma AES CMAC - RFC 4493 i ho he fet en C#. I de dues formes diferents. Primer fent els passos individuals segons l'especificació, i de la manera comodona: fent servir la llibreria BouncyCastle. Primer fent-ho a màs, pas a pas. La dificultat està en la generació d'una sub-clau, que per això he posat un comentari amb l'especificació de com fer-ho del RFC:
byte[] AESEncrypt(byte[] key, byte[] iv, byte[] data)
{
using (MemoryStream ms = new MemoryStream())
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
}
byte[] Rol(byte[] b)
{
byte[] r = new byte[b.Length];
byte carry = 0;
for (int i = b.Length - 1; i >= 0; i--)
{
ushort u = (ushort)(b[i] << 1);
r[i] = (byte)((u & 0xff) + carry);
carry = (byte)((u & 0xff00) >> 8);
}
return r;
}
byte[] AESCMAC(byte[] key, byte[] data)
{
byte[] L = AESEncrypt(key, new byte[16], new byte[16]);
byte[] FirstSubkey = Rol(L);
if ((L[0] & 0x80) == 0x80)
FirstSubkey[15] ^= 0x87;
byte[] SecondSubkey = Rol(FirstSubkey);
if ((FirstSubkey[0] & 0x80) == 0x80)
SecondSubkey[15] ^= 0x87;
if (((data.Length != 0) && (data.Length % 16 == 0)) == true)
{
for (int j = 0; j < FirstSubkey.Length; j++)
data[data.Length - 16 + j] ^= FirstSubkey[j];
}
else
{
data = AddPaddingAES(data);
for (int j = 0; j < 16; j++) data[data.Length - 16 + j] ^= SecondSubkey[j];
}
byte[] encResult = AESEncrypt(key, new byte[16], data);
byte[] HashValue = new byte[16];
Array.Copy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);
return HashValue;
}
I tot això que sembla tan complicat... només són unes poques linies fent servir BouncyCastle. Però ja es sap... la veritat està en el codi, i amb la llibreria no els veus. I el curiós és que ambdues versions donen el mateix resultat:
Org.BouncyCastle.Crypto.Engines.AesEngine aes = new Org.BouncyCastle.Crypto.Engines.AesEngine();
Org.BouncyCastle.Crypto.Macs.CMac cMac = new Org.BouncyCastle.Crypto.Macs.CMac(aes, 64);
Org.BouncyCastle.Crypto.Parameters.KeyParameter kp = new Org.BouncyCastle.Crypto.Parameters.KeyParameter(key);
cMac.Init(kp);
int MacLenght = cMac.GetMacSize();
byte[] output = new byte[MacLenght];
cMac.BlockUpdate(data, 0, data.Length);
cMac.DoFinal(output, 0);
txtBase64.Text = ConvertByteArrayToHexString(output);
Hi ha un conjunt de proves disponibles a un RFC.
I ja està, una altra firma feta. | #23/01/2020 17:00 Programació C# Autor: Alex Canalda
|
Xifrant fitxers en AES |
El petit hashejador que va creixer ha crescut un xic més. Ara ja incorpora xifrat.
I clar, el xifrat ha de ser simètric per anar ràpid. El 3DES ja l'estan treient de circulació, encara no està retirat però ja es considera un xifrat dèbil. El que s'està aplicant ara és el AES, encara que l'AES és del 1998 i el 3DES del 1995... gaire moderns no són.
Així que dit i fet ara he afegit les opcions de xifrat:
- "obre" desxifra una carpeta, elimina els fitxers xifrats i deixa els normals.
- "tanca" xifra una carpeta, elimina els fitxers normals i deixa els xifrats.
- "-pxxxx" i a continuació la contrasenya feta servir per xifrar o desxifrar.
- "[-f]" force, salta les precaucions: No xifrar dos cops, verificar la contrasenya.
- "[-r]" Recursiu, per aplicar la mateixa operació a les subcarpetes.
- "-cnom_carpeta" nom de la carpeta a processar. Si no informat es fa servir carpeta executable.
- "neteja" esborra el fitxer locker.xml, amb opcio [-r]
- "crea -cnom_carpeta [-r] [-desde_cero]" crea un fitxer XML amb els Hash dels fitxers. -r indica recursiu. -desde_cero: esborra els fitxers de hashos existents.
- "verifica -cnom_carpeta [-r] [-continua]" verifica que els fitxers tinguin el Hash correcte, -r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT
- "resultats -cnom_carpeta [-r]" no calcula hashos, llegeix els fitxers del hasher buscant fitxers amb modificacions, -r indica recursiu
- "actualitza -cpath [-r]" calcula hashos per fitxers nous, esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu
- "reset -cpath [-r]" reseteja l'estat a PENDENT, -r indica recursiu
- "crea_tanca" realitza dues accions seguides.
- "verifica_tanca" realitza dues accions seguides.
- "obre_verifica" realitza dues accions seguides.
- El fitxer locker.xml conté informació sobre el tancat.
- El fitxer hasher.xml conté informació sobre els hashos, l'estat del fitxer i la data que es va fer.
Com sempre el codi a continuació:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace OpenSesame
{
class Program
{
private static string ExecutablePath = "";
private static string Accio = "";
private static bool Recursiu = false;
private static bool Force = false;
private static string Pwd = "";
private static string CarpetaAProcessar = "";
private static bool Creacio_de_cero = false;
private static bool Continua = false;
static void Main(string[] args)
{
string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
ExecutablePath = Path.GetDirectoryName(AppPath);
clsDadesDesxifratRetorn ResultatsDesxifrar = null;
clsDadesVerificacioRetorn ResultatsVerificacio = null;
clsDadesXifratRetorn ResultatsXifrat = null;
try
{
ParseParams(args);
if (string.IsNullOrWhiteSpace(CarpetaAProcessar)) CarpetaAProcessar = ExecutablePath;
switch (Accio)
{
case "obre":
if (string.IsNullOrWhiteSpace(Pwd))
{
Console.WriteLine("Password no informada");
return;
}
ResultatsDesxifrar = obre(CarpetaAProcessar);
Console.WriteLine(ResultatsDesxifrar.AString());
break;
case "tanca":
if (string.IsNullOrWhiteSpace(Pwd))
{
Console.WriteLine("Password no informada");
return;
}
ResultatsXifrat = tanca(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - xifrat acabat.");
Console.WriteLine(ResultatsXifrat.AString());
break;
case "neteja":
Neteja(CarpetaAProcessar);
break;
case "crea":
crea(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - creació acabada.");
break;
case "verifica":
ResultatsVerificacio = verifica(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - verificació acabada.");
Console.WriteLine(ResultatsVerificacio.AString());
break;
case "resultats":
ResultatsVerificacio = resultats(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - resultats acabat");
Console.WriteLine(ResultatsVerificacio.AString());
break;
case "actualitza":
actualitza(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - actualitza acabat.");
break;
case "reset":
reset(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - reset acabat.");
break;
case "crea_tanca":
crea(CarpetaAProcessar);
ResultatsXifrat = tanca(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - crea_tanca acabat.");
Console.WriteLine(ResultatsXifrat.AString());
break;
case "verifica_tanca":
ResultatsVerificacio = verifica(CarpetaAProcessar);
if (ResultatsVerificacio.FitxersHashDiferent == 0)
{
ResultatsXifrat = tanca(CarpetaAProcessar);
}
else
{
Console.WriteLine(ObtenirData() + " - xifrat no efectuat, hi ha fitxers amb hashs diferents dels esperats.");
Console.WriteLine("Actualitzar els hashos o fer servir l'opció \"tanca\" de forma individual");
ResultatsXifrat = new clsDadesXifratRetorn();
}
Console.WriteLine(ObtenirData() + " - resultats verificació:");
Console.Write(ResultatsVerificacio.AString());
Console.WriteLine(ObtenirData() + " - resultats xifrat:");
Console.Write(ResultatsXifrat.AString());
break;
case "obre_verifica":
ResultatsDesxifrar = obre(CarpetaAProcessar);
ResultatsVerificacio = verifica(CarpetaAProcessar);
Console.WriteLine(ObtenirData() + " - resultats desxifrar:");
Console.Write(ResultatsDesxifrar.AString());
Console.WriteLine(ObtenirData() + " - resultats verificació:");
Console.Write(ResultatsVerificacio.AString());
break;
default:
Console.WriteLine("Possibles accions:");
Console.WriteLine("\"obre\" desxifra una carpeta, elimina els fitxers xifrats i deixa els normals.");
Console.WriteLine("\"tanca\" xifra una carpeta, elimina els fitxers normals i deixa els xifrats.");
Console.WriteLine("\"-pxxxx\" i a continuació la contrasenya feta servir per xifrar o desxifrar.");
Console.WriteLine("[-f] force, salta les precaucions: No xifrar dos cops, verificar la contrasenya.");
Console.WriteLine("[-r] Recursiu, per aplicar la mateixa operació a les subcarpetes.");
Console.WriteLine("\"-cnom_carpeta\" nom de la carpeta a processar. Si no informat es fa servir carpeta executable.");
Console.WriteLine("\"neteja\" esborra el fitxer hasher.xml i locker.xml, amb opcio [-r]");
Console.WriteLine("\"crea -cnom_carpeta [-r] [-desde_cero]\" crea un fitxer XML amb els Hash dels fitxers. -r indica recursiu. -desde_cero: esborra els fitxers de hashos existents.");
Console.WriteLine("\"verifica -cnom_carpeta [-r] [-continua]\" verifica que els fitxers tinguin el Hash correcte, -r indica recursiu, -continua no verifica els fitxers en estat VERIFICAT");
Console.WriteLine("\"resultats -cnom_carpeta [-r]\" no calcula hashos, llegeix els fitxers del hasher buscant fitxers amb modificacions, -r indica recursiu");
Console.WriteLine("\"actualitza -cpath [-r]\" calcula hashos per fitxers nous, esborra del fitxer de hashos els que pertanyen a fitxers esborrats, -r indica recursiu");
Console.WriteLine("\"reset -cpath [-r]\" reseteja l'estat a PENDENT, -r indica recursiu");
Console.WriteLine("\"crea_tanca\" realitza dues accions seguides.");
Console.WriteLine("\"verifica_tanca\" realitza dues accions seguides.");
Console.WriteLine("\"obre_verifica\" realitza dues accions seguides.");
Console.WriteLine("El fitxer locker.xml conté informació sobre el tancat.");
Console.WriteLine("El fitxer hasher.xml conté informació sobre els hashos, l'estat del fitxer i la data que es va fer.");
break;
}
Console.WriteLine("OpenSesame 1.0 - 03-03-2020");
}
catch(Exception Err)
{
Console.WriteLine(Err.Message);
}
}
private static void reset(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
Console.WriteLine(ObtenirData() + " - resetejant: " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
objFitxer.Value.Estat = "PENDENT";
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
reset(Carpeta);
}
}
}
private static void Neteja(string pPath)
{
if (!Directory.Exists(pPath))
{
Console.WriteLine("Carpeta no trobada: " + pPath);
}
else
{
if (File.Exists(pPath + "\\locker.xml"))
{
File.Delete(pPath + "\\locker.xml");
}
if (File.Exists(pPath + "\\hasher.xml"))
{
File.Delete(pPath + "\\hasher.xml");
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
Neteja(Carpeta);
}
}
}
}
private static void ParseParams(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
if (args[i].ToLower() == "obre")
{
Accio = "obre";
}
if (args[i].ToLower() == "tanca")
{
Accio = "tanca";
}
if (args[i].ToLower() == "neteja")
{
Accio = "neteja";
}
if (args[i].ToLower().StartsWith("-p"))
{
Pwd = args[i].Replace("-p", "");
}
if (args[i].ToLower() == "crea")
{
Accio = "crea";
}
if (args[i].ToLower() == "verifica")
{
Accio = "verifica";
}
if (args[i].ToLower() == "resultats")
{
Accio = "resultats";
}
if (args[i].ToLower() == "actualitza")
{
Accio = "actualitza";
}
if (args[i].ToLower() == "reset")
{
Accio = "reset";
}
if (args[i].ToLower() == "crea_tanca")
{
Accio = "crea_tanca";
}
if (args[i].ToLower() == "verifica_tanca")
{
Accio = "verifica_tanca";
}
if (args[i].ToLower() == "obre_verifica")
{
Accio = "obre_verifica";
}
if (args[i].ToLower() == "-r")
{
Recursiu = true;
}
if (args[i].ToLower() == "-desde_cero")
{
Creacio_de_cero = true;
}
if (args[i].ToLower() == "-continua")
{
Continua = true;
}
if (args[i].ToLower() == "-f")
{
Force = true;
}
if (args[i].Contains(":") && args[i].Contains("-c"))
{
CarpetaAProcessar = args[i].Replace("\\\\", "\\").Replace("-c", "").Trim();
}
}
}
private static byte[] PwdBytes(string pPwd)
{
SHA256Managed SHA2 = new SHA256Managed();
UTF8Encoding encoder = new UTF8Encoding();
byte[] bodyStringBytes = encoder.GetBytes(pPwd);
byte[] pwdBytes = SHA2.ComputeHash(bodyStringBytes);
return pwdBytes;
}
private static byte[] IVBytes(string pPwd, string FileName)
{
SHA256Managed SHA2 = new SHA256Managed();
UTF8Encoding encoder = new UTF8Encoding();
byte[] bodyStringBytes = encoder.GetBytes(pPwd + FileName);
byte[] IV = new byte[16];
byte[] Hash = SHA2.ComputeHash(bodyStringBytes);
int i, j;
i = 0;
j = 0;
while (i < 32)
{
IV[j] = Hash[i];
i = i + 2;
j++;
}
return IV;
}
private static clsDadesDesxifratRetorn obre(string pPath)
{
string[] Fitxers = Directory.GetFiles(pPath, "*.xxx");
byte[] passwordBytes = PwdBytes(Pwd);
clsConfig Config = new clsConfig();
string KCVPwd = CalcularKCV();
string KCVFitxer = "";
bool ErrorDesxifrant = false;
clsDadesDesxifratRetorn Retorn = new clsDadesDesxifratRetorn();
if (!Directory.Exists(pPath))
{
Console.WriteLine("Carpeta no trobada: " + pPath);
return Retorn;
}
DirectoryInfo DInfo = new DirectoryInfo(pPath);
if (DInfo.Attributes.HasFlag(FileAttributes.Hidden))
{
Console.WriteLine(ObtenirData() + " - carpeta oculta no processada: " + pPath);
return Retorn;
}
Config.Initialize(pPath);
if (Config.bError && !Force)
{
Console.WriteLine(ObtenirData() + " - Sense config: " + Config.txtError + ". Fer servir opció -f (force).");
Retorn.CarpetesSenseFitxerConfiguracio++;
}
else
{
if (Config.GetVal("Estat") == "tancat" || Force )
{
KCVFitxer = Config.GetVal("ValidadorClau");
if (KCVFitxer == KCVPwd || Force)
{
if (Fitxers.Length != 0)
{
foreach (string Fitxer in Fitxers)
{
if (PotProcessarFitxer(Fitxer))
{
FileInfo FInfo = new FileInfo(Fitxer);
ErrorDesxifrant = false;
try
{
DeCryptFile(Fitxer, passwordBytes, FInfo.Length);
Console.WriteLine(ObtenirData() + " - DeCrypted OK: " + Path.GetFileName(Fitxer));
Retorn.FitxersDesxifratsOK++;
}
catch(Exception Err)
{
Console.WriteLine(ObtenirData() + " - Error desxifrant: " + Fitxer);
Console.WriteLine(Err.Message);
Retorn.FitxersDesxifratsKO++;
ErrorDesxifrant = true;
}
try
{
if (!ErrorDesxifrant)
{
File.Delete(Fitxer);
Retorn.FitxersEsborratsOK++;
}
}
catch (Exception Err)
{
Console.WriteLine(ObtenirData() + " - Error esborrant fitxer: " + Path.GetFileName(Fitxer) + ", " + Err.Message);
Retorn.FitxersEsborratsKO++;
}
}
}
}
else
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxers a obrir: " + pPath);
Retorn.CarpetesSenseFitxers++;
}
Config.SetVal("Estat", "obert");
Config.SetVal("Data", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
Config.Save(pPath);
}
else
{
Console.WriteLine(ObtenirData() + " - Password incorrecte: " + pPath);
Retorn.CarpetesPwdIncorrecte++;
}
}
else
{
Console.WriteLine(ObtenirData() + " - La carpeta ja està oberta: " + pPath);
Retorn.CarpetesJaDesxifrades++;
}
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
clsDadesDesxifratRetorn RetornRecusiu;
foreach (string Carpeta in Carpetes)
{
RetornRecusiu = obre(Carpeta);
Retorn.CarpetesJaDesxifrades = Retorn.CarpetesJaDesxifrades + RetornRecusiu.CarpetesJaDesxifrades;
Retorn.CarpetesPwdIncorrecte = Retorn.CarpetesPwdIncorrecte + RetornRecusiu.CarpetesPwdIncorrecte;
Retorn.CarpetesSenseFitxerConfiguracio = Retorn.CarpetesSenseFitxerConfiguracio + RetornRecusiu.CarpetesSenseFitxerConfiguracio;
Retorn.CarpetesSenseFitxers = Retorn.CarpetesSenseFitxers + RetornRecusiu.CarpetesSenseFitxers;
Retorn.FitxersDesxifratsKO = Retorn.FitxersDesxifratsKO + RetornRecusiu.FitxersDesxifratsKO;
Retorn.FitxersDesxifratsOK = Retorn.FitxersDesxifratsOK + RetornRecusiu.FitxersDesxifratsOK;
Retorn.FitxersEsborratsKO = Retorn.FitxersEsborratsKO + RetornRecusiu.FitxersEsborratsKO;
Retorn.FitxersEsborratsOK = Retorn.FitxersEsborratsOK + RetornRecusiu.FitxersEsborratsOK;
}
}
return Retorn;
}
private static clsDadesXifratRetorn tanca(string pPath)
{
clsDadesXifratRetorn Retorn = new clsDadesXifratRetorn();
string[] Fitxers = Directory.GetFiles(pPath);
byte[] passwordBytes = PwdBytes(Pwd);
bool ErrorXifrant = false;
clsConfig Config = new clsConfig();
long TamanyFitxer = 0;
if (!Directory.Exists(pPath))
{
Console.WriteLine("Carpeta no trobada: " + pPath);
return Retorn;
}
DirectoryInfo DInfo = new DirectoryInfo(pPath);
if (DInfo.Attributes.HasFlag(FileAttributes.Hidden))
{
Console.WriteLine(ObtenirData() + " - carpeta oculta no processada: " + pPath);
return Retorn;
}
if (File.Exists(pPath + "\\locker.xml"))
{
Config.Initialize(pPath);
}
else
{
Retorn.CarpetesSenseFitxerConfiguracio++;
Console.WriteLine(ObtenirData() + " - carpeta sense fitxer de configuració.");
}
if(Config.GetVal("Estat") == "tancat")
{
Retorn.CarpetesJaXifrades++;
Console.WriteLine(ObtenirData() + " - carpeta ja tancada, si vols tancar-la altra cop, esborra el fitxer locker.xml");
return Retorn;
}
Config.SetVal("ValidadorClau", CalcularKCV());
Config.SetVal("Estat", "tancat");
Config.SetVal("Data", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
foreach (string Fitxer in Fitxers)
{
if (PotProcessarFitxer(Fitxer.ToLower()))
{
ErrorXifrant = false;
FileInfo FInfo = new FileInfo(Fitxer);
if (FInfo.IsReadOnly)
{
Retorn.FitxersReadonly++;
Console.WriteLine(ObtenirData() + " - fitxer readonly no xifrat: " + Path.GetFileName(Fitxer));
}
else
{
TamanyFitxer = FInfo.Length;
if (TamanyFitxer == 0)
{
Retorn.FitxersTamany0++;
Console.WriteLine(ObtenirData() + " - fitxer tamany 0 no xifrat: " + Path.GetFileName(Fitxer));
}
else
{
if (FInfo.Attributes.HasFlag(FileAttributes.Hidden))
{
Retorn.FitxersOcults++;
Console.WriteLine(ObtenirData() + " - fitxer ocult no xifrat: " + Path.GetFileName(Fitxer));
}
else
{
try
{
CryptFile(Fitxer, passwordBytes, TamanyFitxer);
Retorn.FitxersXifratsOK++;
}
catch (Exception Err)
{
ErrorXifrant = true;
Console.WriteLine(ObtenirData() + " - error xifrant fitxer: " + Path.GetFileName(Fitxer) + ": " + Err.Message);
Retorn.FitxersXifratsKO++;
}
try
{
if (!ErrorXifrant)
{
File.Delete(Fitxer);
Retorn.FitxersEsborratsOK++;
}
}
catch (Exception Err)
{
Retorn.FitxersEsborratsKO++;
Console.WriteLine(ObtenirData() + " - error esborrant fitxer: " + Path.GetFileName(Fitxer) + ", " + Err.Message);
}
}
}
}
}
}
Config.Save(pPath);
if (Recursiu)
{
clsDadesXifratRetorn RetornRecursiu = null;
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
RetornRecursiu = tanca(Carpeta);
Retorn.CarpetesJaXifrades = Retorn.CarpetesJaXifrades + RetornRecursiu.CarpetesJaXifrades;
Retorn.CarpetesSenseFitxerConfiguracio = Retorn.CarpetesSenseFitxerConfiguracio + RetornRecursiu.CarpetesSenseFitxerConfiguracio;
Retorn.FitxersEsborratsKO = Retorn.FitxersEsborratsKO + RetornRecursiu.FitxersEsborratsKO;
Retorn.FitxersEsborratsOK = Retorn.FitxersEsborratsOK + RetornRecursiu.FitxersEsborratsOK;
Retorn.FitxersOcults = Retorn.FitxersOcults + RetornRecursiu.FitxersOcults;
Retorn.FitxersReadonly = Retorn.FitxersReadonly + RetornRecursiu.FitxersReadonly;
Retorn.FitxersTamany0 = Retorn.FitxersTamany0 + RetornRecursiu.FitxersTamany0;
Retorn.FitxersXifratsKO = Retorn.FitxersXifratsKO + RetornRecursiu.FitxersXifratsKO;
Retorn.FitxersXifratsOK = Retorn.FitxersXifratsOK + RetornRecursiu.FitxersXifratsOK;
}
}
return Retorn;
}
private static bool PotProcessarFitxer(string Fitxer)
{
string NomEnMinuscules = Fitxer.ToLower();
if (!NomEnMinuscules.Contains("opensesame.exe")
&& !NomEnMinuscules.Contains("hasher.xml")
&& !NomEnMinuscules.Contains("hasher.exe")
&& !NomEnMinuscules.Contains("locker.xml"))
{
return true;
}
else
{
return false;
}
}
private static void CryptFile(string inputFile, byte[] passwordBytes, long TamanyFitxer)
{
FileStream fsCrypt = new FileStream(inputFile + ".xxx", FileMode.Create);
string NomFitxerSenseRutaNiUnitat = Path.GetFileName(inputFile);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.PKCS7;
AES.Key = passwordBytes;
NomFitxerSenseRutaNiUnitat = NomFitxerSenseRutaNiUnitat.ToLower();
AES.IV = IVBytes(Pwd, NomFitxerSenseRutaNiUnitat);
AES.FeedbackSize = 128;
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
byte[] buffer = new byte[4194304];
int read;
if (TamanyFitxer < 4194304)
{
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
cs.Write(buffer, 0, read);
}
Console.WriteLine(ObtenirData() + " - crypted OK: " + Path.GetFileName(inputFile));
}
else
{
double Percentatge = 0;
string strPercentatge = "";
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
Percentatge = (double) fsIn.Position / TamanyFitxer;
Percentatge = Percentatge * 100;
Percentatge = Math.Round(Percentatge, 2);
strPercentatge = String.Format("{0:00.00}", Percentatge);
Console.Write("\r" + ObtenirData(DateTime.Now) + " - crypted " + strPercentatge + "% " + Path.GetFileName(inputFile));
cs.Write(buffer, 0, read);
}
Console.WriteLine();
}
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
private static void DeCryptFile(string inputFile, byte[] passwordBytes, long TamanyFitxer)
{
string NomFitxerSenseRutaNiUnitat = Path.GetFileName(inputFile);
NomFitxerSenseRutaNiUnitat = NomFitxerSenseRutaNiUnitat.Replace(".xxx", "");
NomFitxerSenseRutaNiUnitat = NomFitxerSenseRutaNiUnitat.ToLower();
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.FeedbackSize = 128;
AES.Key = passwordBytes;
AES.IV = IVBytes(Pwd, NomFitxerSenseRutaNiUnitat);
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);
FileStream fsOut = new FileStream(inputFile.Replace(".xxx", ""), FileMode.Create);
int read;
byte[] buffer = new byte[4194304];
if (TamanyFitxer < 4194304)
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
fsOut.Write(buffer, 0, read);
}
}
else
{
long Posicio = 0;
double Percentatge = 0;
string strPercentatge = "";
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
Posicio = Posicio + read;
Percentatge = (double) Posicio / TamanyFitxer;
Percentatge = Percentatge * 100;
Percentatge = Math.Round(Percentatge, 2);
strPercentatge = String.Format("{0:00.00}", Percentatge);
Console.Write("\r" + ObtenirData(DateTime.Now) + " - Decrypted " + strPercentatge + "% " + Path.GetFileName(inputFile));
fsOut.Write(buffer, 0, read);
}
Console.WriteLine();
}
cs.Close();
fsOut.Close();
fsCrypt.Close();
}
private static string CalcularKCV()
{
try
{
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
#region definicio de variables
string strIVAES = "00000000000000000000000000000000";
byte[] IV = ConvertHexStringToByteArray(strIVAES);
byte[] OrigenBytes = null;
byte[] Encrypted = null;
byte[] KCV = new byte[3];
ICryptoTransform EncDec = null;
#endregion
AES.KeySize = 256;
AES.Key = PwdBytes(Pwd);
AES.IV = IV;
AES.Mode = CipherMode.ECB;
AES.Padding = PaddingMode.Zeros;
OrigenBytes = ConvertHexStringToByteArray("00000000000000000000000000000000");
Encrypted = new byte[OrigenBytes.Length];
EncDec = AES.CreateEncryptor();
EncDec.TransformBlock(OrigenBytes, 0, 16, Encrypted, 0);
KCV[0] = Encrypted[0];
KCV[1] = Encrypted[1];
KCV[2] = Encrypted[2];
return ConvertByteArrayToHexString(KCV);
}
catch (Exception E)
{
Console.WriteLine(E.Message);
return "ERROR";
}
}
public static string ConvertByteArrayToHexString(byte[] ba)
{
StringBuilder sb = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString().ToUpper();
}
public static byte[] SubArray(byte[] data, int index, int length)
{
byte[] result = new byte[length];
Array.Copy(data, index, result, 0, length);
return result;
}
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Los datos de entrada tiene un número impar de caracteres, no se puede convertir a Hexadecimal: {0}", hexString.Length));
}
byte[] HexAsBytes = new byte[hexString.Length / 2];
for (int index = 0; index < HexAsBytes.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return HexAsBytes;
}
public static string ObtenirData()
{
return DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static string ObtenirData(DateTime data)
{
return data.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
}
public static string SHA256HashFile(string sPath)
{
string sHash = "";
using (var stream = new BufferedStream(File.OpenRead(sPath), 2400000))
{
SHA256CryptoServiceProvider sha256h = new SHA256CryptoServiceProvider();
sHash = BitConverter.ToString(sha256h.ComputeHash(stream));
}
return sHash;
}
private static void actualitza(string pPath)
{
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
clsConfig Config = new clsConfig();
if (File.Exists(pPath + "\\locker.xml"))
{
Config.Initialize(pPath);
if (Config.GetVal("Estat") == "tancat")
{
Console.WriteLine("Carpeta xifrada, no es poden calcular els hashs dels fitxers");
return;
}
}
Dictionary<string, clsFitxer> DicFitxers;
Dictionary<string, clsFitxer> FitxersActualitzats = new Dictionary<string, clsFitxer>();
clsFitxer FitxerActualitzat = null;
DicFitxers = CarregaHashos(pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] Fitxers = dir.GetFiles();
Console.WriteLine(ObtenirData() + " - Processant " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
try
{
if (File.Exists(pPath + "\\" + objFitxer.Value.Nom))
{
FitxerActualitzat = new clsFitxer(objFitxer.Value.Nom, objFitxer.Value.DataCreacio, objFitxer.Value.DataVerificacio, objFitxer.Value.MidaEnBytes, objFitxer.Value.Hash, objFitxer.Value.Estat);
FitxersActualitzats.Add(FitxerActualitzat.Nom, FitxerActualitzat);
}
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
foreach (FileInfo Fitxer in Fitxers)
{
if (!DicFitxers.ContainsKey(Fitxer.Name))
{
if (PotProcessarFitxer(Fitxer.Name))
{
string hashValueStr = SHA256HashFile(Fitxer.FullName);
Console.WriteLine(ObtenirData() + " - hashejat: " + Fitxer.Name);
FitxerActualitzat = new clsFitxer(Fitxer.Name, DateTime.Now, DateTime.Now, Fitxer.Length, hashValueStr, "CREAT");
FitxersActualitzats.Add(Fitxer.Name, FitxerActualitzat);
}
}
}
Save(pPath, FitxersActualitzats);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
actualitza(Carpeta);
}
}
}
public static void crea(string pPath)
{
bool Procesa_carpeta = false;
if (File.Exists(pPath + "\\hasher.xml"))
{
if (Creacio_de_cero)
{
File.Delete(pPath + "\\hasher.xml");
Console.WriteLine(ObtenirData() + " - Carpeta " + pPath + " amb fitxer de hashos, esborrat.");
Procesa_carpeta = true;
}
else
{
Console.WriteLine(ObtenirData() + " - Carpeta " + pPath + " amb fitxer de hashos, no procesada.");
Procesa_carpeta = false;
}
}
else
{
Procesa_carpeta = true;
}
if (Procesa_carpeta)
{
Console.WriteLine(ObtenirData() + " - creant fitxer hashos: " + pPath);
DirectoryInfo dir = new DirectoryInfo(pPath);
FileInfo[] files = dir.GetFiles();
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
foreach (FileInfo Fitxer in files)
{
try
{
if (PotProcessarFitxer(Fitxer.Name))
{
string hashValueStr = SHA256HashFile(Fitxer.FullName);
Console.WriteLine(ObtenirData() + " - hashejat: " + Fitxer.Name);
objFitxer = new clsFitxer(Fitxer.Name, DateTime.Now, DateTime.Now, Fitxer.Length, hashValueStr, "CREAT");
DicFitxers.Add(Fitxer.Name, objFitxer);
}
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
crea(Carpeta);
}
}
}
public static void Save(string pPath, Dictionary<string, clsFitxer> DicFitxers)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNode Fitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
Doc.LoadXml("<?xml version=\"1.0\" standalone=\"yes\"?><fitxers></fitxers>");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Fitxer = Doc.CreateNode(XmlNodeType.Element, "fitxer", "");
Nom = Doc.CreateNode(XmlNodeType.Element, "nom", "");
Hash = Doc.CreateNode(XmlNodeType.Element, "hash", "");
DataCreacio = Doc.CreateNode(XmlNodeType.Element, "datacreacio", "");
DataVerificacio = Doc.CreateNode(XmlNodeType.Element, "dataverificacio", "");
Estat = Doc.CreateNode(XmlNodeType.Element, "estat", "");
MidaEnBytes = Doc.CreateNode(XmlNodeType.Element, "midaenbytes", "");
Nom.InnerText = objFitxer.Value.Nom;
Hash.InnerText = objFitxer.Value.Hash;
DataCreacio.InnerText = ObtenirData(objFitxer.Value.DataCreacio);
DataVerificacio.InnerText = ObtenirData(objFitxer.Value.DataVerificacio);
Estat.InnerText = objFitxer.Value.Estat;
MidaEnBytes.InnerText = objFitxer.Value.MidaEnBytes.ToString();
Fitxer.AppendChild(Nom);
Fitxer.AppendChild(Hash);
Fitxer.AppendChild(DataCreacio);
Fitxer.AppendChild(DataVerificacio);
Fitxer.AppendChild(Estat);
Fitxer.AppendChild(MidaEnBytes);
Fitxers.AppendChild(Fitxer);
}
Doc.Save(pPath + "\\hasher.xml");
}
public static clsDadesVerificacioRetorn verifica(string pPath)
{
clsDadesVerificacioRetorn Retorn = new clsDadesVerificacioRetorn();
long GBHashejats = 0;
Console.WriteLine(ObtenirData() + " - verificant carpeta: " + pPath);
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
clsConfig Config = new clsConfig();
if (File.Exists(pPath + "\\locker.xml"))
{
Config.Initialize(pPath);
if (Config.GetVal("Estat") == "tancat")
{
Console.WriteLine(ObtenirData() + " - Carpeta xifrada, no es poden verificar els hashs dels fitxers");
return Retorn;
}
}
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
if (objFitxer.Value.Estat == "VERIFICAT" && Continua)
{
Console.WriteLine(ObtenirData() + " - fitxer ja verificat anteriorment: " + objFitxer.Value.Nom);
}
else
{
try
{
if (File.Exists(pPath + "\\" + objFitxer.Value.Nom))
{
FileInfo fiFitxer = new FileInfo(pPath + "\\" + objFitxer.Value.Nom);
if (fiFitxer.Length != objFitxer.Value.MidaEnBytes)
{
Retorn.FitxersMidaDiferent++;
Console.WriteLine(ObtenirData() + " - Fitxer amb mida diferent: " + fiFitxer.Name);
objFitxer.Value.Estat = "MIDA DIFERENT, actual: " + fiFitxer.Length;
}
else
{
GBHashejats += fiFitxer.Length;
string hashValueStr = SHA256HashFile(fiFitxer.FullName);
if (hashValueStr == objFitxer.Value.Hash)
{
Retorn.FitxersVerificats++;
Console.WriteLine(ObtenirData() + " - Fitxer verificat OK: " + fiFitxer.Name);
objFitxer.Value.Estat = "VERIFICAT";
}
else
{
Retorn.FitxersHashDiferent++;
Console.WriteLine(ObtenirData() + " - Fitxer amb hash canviat: " + fiFitxer.Name);
objFitxer.Value.Estat = "NO COINCIDEIX";
}
if (GBHashejats > 5368709120)
{
GBHashejats = 0;
Save(pPath, DicFitxers);
}
}
}
else
{
Retorn.FitxersEsborrats++;
Console.WriteLine(ObtenirData() + " - Fitxer esborrat: " + objFitxer.Value.Nom);
objFitxer.Value.Estat = "ESBORRAT";
}
objFitxer.Value.DataVerificacio = DateTime.Now;
}
catch (IOException e)
{
Console.WriteLine("I/O Exception: " + e.Message);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Access Exception: " + e.Message);
}
}
}
Save(pPath, DicFitxers);
}
if (Recursiu)
{
clsDadesVerificacioRetorn RetornRecursiu;
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
RetornRecursiu = verifica(Carpeta);
Retorn.FitxersVerificats = Retorn.FitxersVerificats + RetornRecursiu.FitxersVerificats;
Retorn.FitxersHashDiferent = Retorn.FitxersHashDiferent + RetornRecursiu.FitxersHashDiferent;
Retorn.FitxersMidaDiferent = Retorn.FitxersMidaDiferent + RetornRecursiu.FitxersMidaDiferent;
Retorn.FitxersEsborrats = Retorn.FitxersEsborrats + RetornRecursiu.FitxersEsborrats;
}
}
return Retorn;
}
private static clsDadesVerificacioRetorn resultats(string pPath)
{
clsDadesVerificacioRetorn Retorn = new clsDadesVerificacioRetorn();
if (!File.Exists(pPath + "\\hasher.xml"))
{
Console.WriteLine(ObtenirData() + " - No hi ha fitxer de hashos: " + pPath);
}
else
{
Dictionary<string, clsFitxer> DicFitxers;
DicFitxers = CarregaHashos(pPath);
Console.WriteLine(ObtenirData() + " - analitzant: " + pPath);
foreach (KeyValuePair<String, clsFitxer> objFitxer in DicFitxers)
{
Retorn.FitxersVerificats++;
if (objFitxer.Value.Estat == "NO COINCIDEIX")
{
Retorn.FitxersHashDiferent++;
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio) + " - fitxer amb hash canviat: " + pPath + "\\" + objFitxer.Value.Nom);
}
else
{
if (objFitxer.Value.Estat.Contains("MIDA DIFERENT"))
{
Retorn.FitxersMidaDiferent++;
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio) + " - fitxer amb mida diferent: " + pPath + "\\" + objFitxer.Value.Nom);
}
else
{
if (objFitxer.Value.Estat == "ESBORRAT")
{
Retorn.FitxersEsborrats++;
Console.WriteLine(ObtenirData(objFitxer.Value.DataVerificacio) + " - fitxer esborrat: " + pPath + "\\" + objFitxer.Value.Nom);
}
}
}
}
}
if (Recursiu)
{
clsDadesVerificacioRetorn RetornRecursiu;
string[] Carpetes = Directory.GetDirectories(pPath);
foreach (string Carpeta in Carpetes)
{
RetornRecursiu = resultats(Carpeta);
Retorn.FitxersVerificats = Retorn.FitxersVerificats + RetornRecursiu.FitxersVerificats;
Retorn.FitxersHashDiferent = Retorn.FitxersHashDiferent + RetornRecursiu.FitxersHashDiferent;
Retorn.FitxersMidaDiferent = Retorn.FitxersMidaDiferent + RetornRecursiu.FitxersMidaDiferent;
Retorn.FitxersEsborrats = Retorn.FitxersEsborrats + RetornRecursiu.FitxersEsborrats;
}
}
return Retorn;
}
public static Dictionary<string, clsFitxer> CarregaHashos(string pPath)
{
XmlDocument Doc = new XmlDocument();
XmlNode Fitxers;
XmlNodeList llistaDeFitxer;
XmlNode Nom;
XmlNode Hash;
XmlNode DataCreacio;
XmlNode DataVerificacio;
XmlNode Estat;
XmlNode MidaEnBytes;
clsFitxer objFitxer = null;
Dictionary<string, clsFitxer> DicFitxers = new Dictionary<string, clsFitxer>();
Doc.Load(pPath + "\\hasher.xml");
Fitxers = Doc.SelectSingleNode("descendant::fitxers");
llistaDeFitxer = Fitxers.ChildNodes;
foreach (XmlNode Fitxer in llistaDeFitxer)
{
objFitxer = new clsFitxer();
Nom = Fitxer.SelectSingleNode("descendant::nom");
Hash = Fitxer.SelectSingleNode("descendant::hash");
DataCreacio = Fitxer.SelectSingleNode("descendant::datacreacio");
DataVerificacio = Fitxer.SelectSingleNode("descendant::dataverificacio");
Estat = Fitxer.SelectSingleNode("descendant::estat");
MidaEnBytes = Fitxer.SelectSingleNode("descendant::midaenbytes");
if (Nom != null)
{
objFitxer.Nom = Nom.InnerText;
}
else
{
objFitxer.Nom = "Nom null";
}
if (Hash != null)
{
objFitxer.Hash = Hash.InnerText;
}
else
{
objFitxer.Hash = "Hash null";
}
if (DataCreacio != null)
{
objFitxer.DataCreacio = DateTime.ParseExact(DataCreacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
}
else
{
objFitxer.DataCreacio = DateTime.Now;
}
if(DataVerificacio != null)
{
objFitxer.DataVerificacio = DateTime.ParseExact(DataVerificacio.InnerText, "dd/MM/yyyy HH:mm:ss", null);
}
else
{
objFitxer.DataVerificacio = DateTime.Now;
}
if(Estat != null)
{
objFitxer.Estat = Estat.InnerText;
}
else
{
objFitxer.Estat = "Estat null";
}
if(MidaEnBytes != null)
{
objFitxer.MidaEnBytes = long.Parse(MidaEnBytes.InnerText);
}
else
{
objFitxer.MidaEnBytes = 0;
}
DicFitxers.Add(objFitxer.Nom, objFitxer);
}
return DicFitxers;
}
}
}
I classes de retorn que es dediquen a recollir estadístiques:
class clsDadesDesxifratRetorn
{
public int FitxersDesxifratsOK = 0;
public int FitxersDesxifratsKO = 0;
public int FitxersEsborratsOK = 0;
public int FitxersEsborratsKO = 0;
public int CarpetesSenseFitxers = 0;
public int CarpetesPwdIncorrecte = 0;
public int CarpetesJaDesxifrades = 0;
public int CarpetesSenseFitxerConfiguracio = 0;
public string AString()
{
StringBuilder SB = new StringBuilder();
SB.AppendFormat("Fitxers desxifrats OK: {0}{1}", FitxersDesxifratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers desxifrats KO: {0}{1}", FitxersDesxifratsKO, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats OK: {0}{1}", FitxersEsborratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats KO: {0}{1}", FitxersEsborratsKO, Environment.NewLine);
SB.AppendFormat("Carpetes sense fitxers: {0}{1}", CarpetesSenseFitxers, Environment.NewLine);
SB.AppendFormat("Carpetes pwd incorrecte: {0}{1}", CarpetesPwdIncorrecte, Environment.NewLine);
SB.AppendFormat("Carpetes ja desxifrades: {0}{1}", CarpetesJaDesxifrades, Environment.NewLine);
SB.AppendFormat("Carpetes sense fitxer config: {0}{1}", CarpetesSenseFitxerConfiguracio, Environment.NewLine);
return SB.ToString();
}
}
I una altra:
class clsDadesVerificacioRetorn
{
public int FitxersVerificats = 0;
public int FitxersHashDiferent = 0;
public int FitxersEsborrats = 0;
public int FitxersMidaDiferent = 0;
public string AString()
{
StringBuilder SB = new StringBuilder();
SB.AppendFormat("Total fitxers OK: {0}.{1}", FitxersVerificats, Environment.NewLine);
SB.AppendFormat("Hash KO: {0}.{1}", FitxersHashDiferent, Environment.NewLine);
SB.AppendFormat("Esborrats: {0}.{1}", FitxersEsborrats, Environment.NewLine);
SB.AppendFormat("Mida diferent: {0}.{1}", FitxersMidaDiferent, Environment.NewLine);
return SB.ToString();
}
}
I l'última:
class clsDadesXifratRetorn
{
public int FitxersXifratsOK = 0;
public int FitxersXifratsKO = 0;
public int FitxersEsborratsOK = 0;
public int FitxersEsborratsKO = 0;
public int FitxersReadonly = 0;
public int FitxersTamany0 = 0;
public int FitxersOcults = 0;
public int CarpetesJaXifrades = 0;
public int CarpetesSenseFitxerConfiguracio = 0;
public string AString()
{
StringBuilder SB = new StringBuilder();
SB.AppendFormat("Fitxers xifrats OK: {0}{1}", FitxersXifratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers xifrats KO: {0}{1}", FitxersXifratsKO, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats OK: {0}{1}", FitxersEsborratsOK, Environment.NewLine);
SB.AppendFormat("Fitxers esborrats KO: {0}{1}", FitxersEsborratsKO, Environment.NewLine);
SB.AppendFormat("Fitxers readonly: {0}{1}", FitxersReadonly, Environment.NewLine);
SB.AppendFormat("Fitxers tamany 0: {0}{1}", FitxersTamany0, Environment.NewLine);
SB.AppendFormat("Fitxers ocults: {0}{1}", FitxersOcults, Environment.NewLine);
SB.AppendFormat("Carpetes ja xifrades: {0}{1}", CarpetesJaXifrades, Environment.NewLine);
SB.AppendFormat("Carpetes sense fitxer config: {0}{1}", CarpetesSenseFitxerConfiguracio, Environment.NewLine);
return SB.ToString();
}
}
| #07/01/2020 16:59 Programació C# Autor: Alex Canalda
|
<< Posts anteriors |
|