webForumDet fria alternativet

Koda attachment

13 svar · 632 visningar · startad av nkrantz

nkrantzMedlem sedan apr. 2002830 inlägg
#1

Hallå,

Sitter med ett program i .net som skall skicka ett mail och man skall kunna bifoga en fil.

Problemet som jag inte kan lösa är hur jag skall koda filen som skall bifogas. Fick följande meddelande från min handledare, men jag förstår det ändå inte. Någon som kan ge lite kod så att jag förstår? (exempelvis hur man kodar en sträng så att det funkar...)

kortfattat: ta tre tecken, omvandla till asciikod, betrakta dem som 24 bitar, dela upp de 24 bitarna i 4 grupper om 6 bitar. Betrakta dem som ett tal och ta rätt tecken av de tillåtna tecknen (A-Z,a-z,0-9,=).
Bra funktioner att använda är
ASC: omvandla ett tecken till ascii
OCT: omvandla ett tal till octala tal (0-7, dvs tre bitar)

oct((ASC(tkn1)*256+ASC(tkn2))*256+asc(tkn3))

// Nippe

renholmMedlem sedan apr. 20012 266 inlägg
#2

Inte säker på vad din handledare vilj, dock är bifogade filer kodade i Base64 och detta gör du med .NET på följande sätt:

string kodad = Convert.ToBase64String(dinbyteArray);
tydalMedlem sedan juni 20034 013 inlägg
#3

Eftersom jag inte vet vilket programmeringsspråk du använder/vill använda så kan jag bara berätta hur du ska göra.

Om vi tar lite teori först. Allting i datorn lagras i bitar. En bit är en etta eller en nolla. Den har alltså två lägen (kombinationer), och det räcker inte så långt, utan man behöver fler bitar för att kunna göra något användbart. För varje bit man lägger till ökar antalet kombinationer med det dubbla. Två bitar, 2*2 = 4 kombinationer, fyra bitar = 2*2*2*2 = 16 kombinationer. Åtta bitar blir 256 kombinationer och det tyckte man verkade lagom att rymma alfabetet, siffror, specialtecken och diverse funktioner, så det beslutade man för att kalla en byte, ett tecken.

Varje tecken i datorn utgörs alltså egentligen av ett tal mellan 0 och 255, och det är det som lagras i dina filer. Att det ändå visas som bokstäver beror på att datorn har en tabell (så kallad ASCII-tabell) som den går efter där det står att exempelvis 65 ska visas som A och 100 som d. Nu får emellertid inte alla olika bokstäver för alla världens språk rum på bara 256 platser och därför finns det olika varianter av teckentabeller så varje land ska kunna ha sina bokstäver. Det är därför å, ä och ö kan se konstiga ut, för då använder du en annan teckentabell än den som texten skrevs med. Några exempel på teckentabeller är PC8-437, 850, ISO-8859-1 och UTF-8.

Alla tal mellan 0 och 255 utgör dock inte tecken utan 0-31 är reserverade för specialkoder, exempelvis enter, backsteg, escape, tab, null och eof (end-of-file). Dessa koder är ju inte avsedda att skrivas i text, utan de benämns non-printable characters. Om de skulle dyka upp lite hipp som happ när man tittar på en text så vore det inte så bra, för null används för att tala om att strängen slutar där och eof att filen slutar där, samtidigt som det också finns koder för att åstadkomma pip-ljud i högtalaren.

Men varför skulle då dessa koder dyka upp hipp som happ? Jo, om filen i fråga inte består av text, dvs att ettorna och nollorna står för något annat än bokstäver. Exempelvis en bild, en bmp-fil. I en bmp-fil står varje byte för hur mycket färg en bildpunkt på skärmen ska ha. Du kanske har stött på begreppet 24-bitars färg. Det innebär att 24 bitar används för färginformation, 8 bitar för mängden rött, 8 för grönt och 8 för blått. 0 betyder ingenting och 255 är max. Om du tar och skapar en ny bild i Paint och väljer en färg med värdet 65 på röd, 65 på grön och 65 på blå och sedan fyller hela bilden med den färgen och sparar den i BMP-format 24-bit, så kommer alltså den filen att fyllas med värdet 65. Om du nu öppnar den filen i Anteckningar så kommer den att tolkas som text, och som jag sagt tidigare så står 65 för bokstaven A i teckentabellen och du kommer alltså att få upp en massa A:n på skärmen...

Men om det hade varit någon svart punkt på bilden hade det blivit 0 och eftersom det ligger mellan 0 och 31 så är det inget tecken utan en kod, och då blir det inte alltid så bra. Anteckningar kan hantera det, men i e-post är det värre.

Hur gör man då om man vill skicka filer i e-post som kan innehålla "förbjudna" värden? (Det rör sig inte bara om BMP-filer med vissa färger i, utan alla bildfiler, ljudfiler och program.)

Jo, man måste ju på något sätt omvandla de farliga värdena till ofarliga. Vilka är ofarliga? A-Z, a-z och 0-9. Det blir 26+26+10 = 62 tecken. Lägger vi till ytterligare två tecken får vi 64 vilket är exakt lika med 2*2*2*2*2*2, dvs 6 bitar, och då blir det smidigt, för då blir principen enkel. Vi har ju våra ettor och nollor som vi normalt läser en byte i taget (dvs åtta i taget) och slår upp i en tabell (ASCII-tabellen) för att avgöra vad som ska visas på skärmen. Men nu kan vi alltså istället läsa sex i taget och använda en annan tabell. A-Z, a-z, 0-9 och så de två extra tecknen + och /

"Allt" du ska göra är alltså att läsa in sex bitar i taget, slå upp tecknet i tabellen och skriva ut det i e-postmeddelandet.

Du kan börja med att sätta upp den nya tabellen. Till det använder man en array. Vi kan kalla den base64:

base64[0] = 'A';
base64[1] = 'B';
..
base64[25] = 'Z';
base64[26] = 'a';
..
base64[51] = 'z';
base64[52] = '0';
..
base64[61] = '9';
base64[62] = '+';
base64[63] = '/';

Sedan är nog det enklaste att göra som din handledare skrivit att läsa in tre tecken och dela upp dem i fyra...

Formeln du har fått tar tre tecken (tkn1, tkn2, tkn3) och lägger ihop deras värden. Sedan görs talet till det oktala talsystemet, och där har man bara åtta siffror: 0-7. Eftersom åtta går jämnt upp i 2: 2*2*2 = 8, vilket alltså är tre bitar, så får det den fördelen att varje siffra utgör tre bitar. Och eftersom vi nu vill ha sex bitar så tar vi bara siffrorna två och två...

Vi gör om talet till vårt vanliga räknesystem med tio siffror genom att multiplicera första siffran med åtta och lägga till den andra. Sedan slår du bara upp det talet i tabellen och skriver ut det tecknet till e-postmeddelandet...

tydalMedlem sedan juni 20034 013 inlägg
#4

Sammanfattning:

1. Loopa igenom din sträng och plocka ut tre tecken i taget.
2. Lägg in de tre tecknen i formeln.
3. Omvandla svaret till en sträng.
4. Upprepa fyra gånger.
5. Ta två tecken från strängen och omvandla till två siffror.
6. Multiplicera första siffran med åtta och lägg till den andra.
7. Slå upp resultatet i base64-tabellen.
8. Skriv tecknet till e-postmeddelandet.
9. Slut upprepning.

Om, när du kommer till slutet av texten som ska kodas, det inte finns tre tecken kvar så ersätter du de saknade tecknen med = i e-postmeddelandet.

tydalMedlem sedan juni 20034 013 inlägg
#5

Exempel:

Vi ska koda: test

De tre första bokstäverna (tes) skickas till formeln. Resultatet blir: 35062563

Vi tar de första två siffrorna: 35
Multiplicerar den första med åtta och lägger till den andra:
3*8 + 5 = 24 + 5 = 29. 29 slås upp i tabellen som visar sig vara d. Första tecknet i den kodade strängen: d.

Nästa två siffror 06: 0 * 8 + 6 = 6 som slås upp i tabellen och ger G: dG

Nästa: 2 * 8 + 5 = 16 + 5 = 21: V och vi har: dGV

6 * 8 + 3 = 51: z

dGVz

Vi går vidare med resten av bokstäverna, men det är bara en kvar: t och tkn2 och tkn3 blir därför 0. (Obs värdet 0, inte tecknet '0'.)

Formeln ger: 35000000

3 * 8 + 5 = 24 + 5 = 29 ger tecknet d: dGVzd
0 * 8 + 0 = 0 ger tecknet A: dGVzd

Sen fattas två bokstäver eftersom det skulle varit tre och vi lägger till två likhetstecken:

dGVzdA==

Detta är alltså strängen test base64-kodad.

nkrantzMedlem sedan apr. 2002830 inlägg
#6

tydal, du är en stjärna! En bättre förklaring har jag aldrig sett maken till! Tack så mycket! Ska vid tillfälle se om det funkar också ;)

mvh,
nippe

nkrantzMedlem sedan apr. 2002830 inlägg
#7

Har lite problem med hanteringen av om det är mindre än 3 tkn kvar i slutet. Om det är två tecken som blir över funkar det, men om det bara är ett tecken över så kodar min kod base64 strängen fel.

If chars.Length = 3 Then
            att = Oct((Asc(Mid(chars, 1, 1)) * 256 + Asc(Mid(chars, 2, 1))) * 256 + Asc(Mid(chars, 3, 1)))

            att.ToString()
            attString += base64(Mid(att, 1, 1) * 8 + Mid(att, 2, 1)) + _
            base64(Mid(att, 3, 1) * 8 + Mid(att, 4, 1)) + _
            base64(Mid(att, 5, 1) * 8 + Mid(att, 6, 1)) + _
            base64(Mid(att, 7, 1) * 8 + Mid(att, 8, 1))
        ElseIf chars.Length = 2 Then
            att = Oct((Asc(Mid(chars, 1, 1)) * 256 + Asc(Mid(chars, 2, 1))) * 256)

            att.ToString()
            attString += base64(Mid(att, 1, 1) * 8 + Mid(att, 2, 1)) + _
            base64(Mid(att, 3, 1) * 8 + Mid(att, 4, 1)) + _
            base64(Mid(att, 5, 1) * 8 + Mid(att, 6, 1)) + _
            "="
        ElseIf chars.Length = 1 Then
            att = Oct((Asc(chars) * 256))

            att.ToString()

            attString += base64(Mid(att, 1, 1) * 8 + Mid(att, 2, 1)) + _
            base64(Mid(att, 3, 1) * 8 + Mid(att, 4, 1)) + _
            "=="
        End If

Någon som ser varför?

// Nippe

nkrantzMedlem sedan apr. 2002830 inlägg
#8

Löste det själv. Multiplicera med 256 en gång till i slutet... Varför förstår jag inte, men det funkar ;)

// Nippe

nkrantzMedlem sedan apr. 2002830 inlägg
#9

Hej igen,

Har nu alltså lyckats att koda en sträng till base64, mycket nöjd över mina framsteg. Men när jag försöker läsa in en .zip fil till en sträng och sedan använda min funktion så funkar det inte. Jag antar att det beror på att min kod inte klarar att koda binärt, eller något sånt.

Någon som kan förklara hur jag ska gå tillväga? The master tydal kanske? ;)

// Nippe

UlfTMedlem sedan maj 20018 027 inlägg
#10

nkrantz skrev:

Har nu alltså lyckats att koda en sträng till base64, mycket nöjd över mina framsteg. Men när jag försöker läsa in en .zip fil till en sträng och sedan använda min funktion så funkar det inte. Jag antar att det beror på att min kod inte klarar att koda binärt, eller något sånt.

Pröva att öppna filen binärt. Då har du en lång sträng av bytes. Det borde gå att göra exakt på samma sätt med den strängen som med de korta strängar du redan har provat med. Poängen med base64, är ju att koda om binära filer så att de kan transporteras som text. Utresultatet kommer således bli text när kodningen är klar, så du skriver inget binärt.

nkrantzMedlem sedan apr. 2002830 inlägg
#11

Okej, ska testa det, men problemet kanske ligger i att jag försöker göra om indatan till en sträng... Funktionen tar ju tre tecken i taget...

Får testa i morgon! Tack så länge!

// Nippe

UlfTMedlem sedan maj 20018 027 inlägg
#12

nkrantz skrev:

Okej, ska testa det, men problemet kanske ligger i att jag försöker göra om indatan till en sträng... Funktionen tar ju tre tecken i taget...

Ta tre bytes i taget från den binära filen, och gör samma beräkningar med dessa.

nkrantzMedlem sedan apr. 2002830 inlägg
#13

Jag börjar komma en bit på vägen, men får följande felmeddelande som jag suttit med i några timmar nu:

An unhandled exception of type 'System.InvalidCastException' occurred in microsoft.visualbasic.dll

Additional information: Cast from string "" to type 'Double' is not valid

Jag försöker ens inte att konvertera om datatyperna. Hämtar ju ett värde i base64 arrayen som är a-zA-z0-9, så jag förstår inte vad smo händer... Har angett *** på de raderna som ger felen..

Dim att As String
        Dim attString As String
        attString = ""
            att = Oct((Asc(Mid(chars, 1, 1)) * 256 + Asc(Mid(chars, 2, 1))) * 256 + Asc(Mid(chars, 3, 1)))

            att.ToString()
           *** attString += base64(Mid(att, 1, 1) * 8 + Mid(att, 2, 1)) + "" + _
           *** base64(Mid(att, 3, 1) * 8 + Mid(att, 4, 1)) + "" + _
           *** base64(Mid(att, 5, 1) * 8 + Mid(att, 6, 1)) + "" + _
           *** base64(Mid(att, 7, 1) * 8 + Mid(att, 8, 1))

Någon som har ngt tips?

// Nippe

UlfTMedlem sedan maj 20018 027 inlägg
#14

nkrantz skrev:

An unhandled exception of type 'System.InvalidCastException' occurred in microsoft.visualbasic.dll

Additional information: Cast from string "" to type 'Double' is not valid

Tänk dig att du har fått en sträng med bara sju tecken, istället för åtta, när du ska slå upp i base64-tabellen. Då kommer Mid(att, 8, 1) returnera "", vilket inte kan konverteras till något tal som går att använda för att referera till base64-arrayen. Anledningen till att det kan bli så, är att det tal du räknade fram med Oct, kanske började med nollor, förmodligen därför att den eller de första byten, var lika med noll. Har du då fått "00012345" efter den oktala beräkningen, så har du i själva verket "12345". Du ska alltså hänga på tre nollor i början av strängen. Sedan har du åtta tecken i din sträng som du kan referera till.

144 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
141 ms — hämta tråd, inlägg och bilagor (db)