Regulæruttrykk - igjen

Regulæruttrykk, objektorientering, samt problemstillinger omkring optimalisering og sikkerhet.

Regulæruttrykk - igjen

Innlegg ingeva » 24.11.2011 20:44

Jeg har etter mange år med regulæruttrykk egentlig ikke lært det skikkelig.
Nå har jeg slitt litt med et problem, og må be om litt hjelp.

Jeg vil sjekke at et ord (brukernavn uten mellomrom) kan brukes som del av et filnavn (fornavnet).
Det vil si at alle bokstavene må være tillatt i et filnavn, med unntak av punktum.

Etter mye prøving og feiling har jeg ikke funnet en *enkel* måte å tolke punktum som feil.
Punktum skiller som kjent mellom for- og etternavn på en fil, og i "min" sammenheng kan
det lett føre til feiltolking.

Jeg har laget dette uttrykket (nytt brukernavn ligger i $newname):

if (!preg_match('/[a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]/', $newname))
errmess ('Brukernavnet har ulovlige tegn.');

dvs. at enkelte tegn og skandinaviske bokstaver kan godtas. Problemet er
at også punktum godtas av denne testen, selv om det ikke er med i stringen.

Så altså: Hva må jeg gjøre for at punktum IKKE skal bli godtatt?
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg Nukleuz » 24.11.2011 20:48

Foreslår at du heller skriver en RegExp hvor du sjekker mot en "hvit liste", og ikke en "svart liste" ;-)

Edit: Ikke godta punktum:

Kode: Merk alt
^\.


^ = not
\ = escape

Du må escape punktum, siden den er "reservert" i regexp.

Kan denne hjelpe deg: http://www.cheatography.com/davechild/c ... pressions/ ?
Mvh
Joachim M. Giæver
http://development.giaever.org
Brukerens avatar
Nukleuz
Seniormedlem
 
Innlegg: 1659
Registrert: 09.12.2006 2:08
Bosted: Tromsø

Re: Regulæruttrykk - igjen

Innlegg ingeva » 24.11.2011 20:52

Nukleuz skrev:Foreslår at du heller skriver en RegExp hvor du sjekker mot en "hvit liste", og ikke en "svart liste" ;-)

Edit: Ikke godta punktum:
Kode: Merk alt
^\.


^ = not
\ = escape

Du må escape punktum, siden den er "reservert" i regexp.
Kan denne hjelpe deg: http://www.cheatography.com/davechild/c ... pressions/ ?

For det første: Cheat-sheetet har jeg sjekket, men fant ikke ut av det.
For det andre: Jeg brukte ^ for "not" men da ble ingenting godtatt:

Kode: Merk alt
'/[^\.a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]/'

gir altså feil på rubbel og bit. Hva gjør jeg feil?

Jeg prøvde forresten også å flytte det sist:
Kode: Merk alt
'/[a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ^\.]/'

med det resultat at punktum fortsatt godtas.

Forøvrig er vel dette en "white-list" - hvor alt som er i listen er OK - men punktum, som ikke står i listen, er fortsatt OK, men skulle ikke vært det..... :(
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg Fuzzy76 » 24.11.2011 21:28

Fordi du ikke spesifiserer start av streng, antall, eller slutt av streng. Altså vil de første matche på ALT så lenge det finnes ETT tegn i strengen som ikke er punktum. /$[...]+^/ er nok en bedre grunnstruktur.
Brukerens avatar
Fuzzy76
Moderator
 
Innlegg: 1266
Registrert: 29.11.2006 11:44
Bosted: Tromsø

Re: Regulæruttrykk - igjen

Innlegg ingeva » 24.11.2011 22:32

Fuzzy76 skrev:Fordi du ikke spesifiserer start av streng, antall, eller slutt av streng. Altså vil de første matche på ALT så lenge det finnes ETT tegn i strengen som ikke er punktum. /$[...]+^/ er nok en bedre grunnstruktur.

Dette skjønte jeg ikke. Den stringen starter jo med dollar, som er string-slutt.
Det er annet der også som jeg ikke forstår, og akkurat nå har jeg ikke tid til å teste.
Men jeg ville satt pris på å få dette med teskje. Jeg kan tydeligvis mindre om denne enn det jeg trodde. :)
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg hepp » 24.11.2011 22:54

Kode: Merk alt
if (!preg_match('/[a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]/', $newname)) 

Det regulære uttrykket sjekker om strengen inneholder et av tegnene spesifisert. ~.a vil derfor matche, da den inneholder en a.

Du kan derfor enten sjekke at den inneholder kun disse tegnene fra starten til slutten av strengen, eller sjekke om den inneholder andre bokstaver enn de tillatte.

Kode: Merk alt
if ( ! preg_match('/^[a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]+$/D', $newname)) {
  // Ulovlige tegn i strengen
} 

Har her lagt til en modifier D for ikke å matche newline på slutten av strengen.

Alternativt
Kode: Merk alt
if (preg_match('/[^a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]/', $newname)) {
  // Ulovlige tegn i strengen
} 
Insanity: doing the same thing over and over again and expecting different results.
Brukerens avatar
hepp
Seniormedlem
 
Innlegg: 1589
Registrert: 17.12.2003 22:06

Re: Regulæruttrykk - igjen

Innlegg ingeva » 24.11.2011 23:27

hepp skrev:
Kode: Merk alt
if (!preg_match('/[a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]/', $newname)) 

Det regulære uttrykket sjekker om strengen inneholder et av tegnene spesifisert. ~.a vil derfor matche, da den inneholder en a.

En streng som inneholdt ovenstående tegn ble godtatt.
Bortsett fra punktum ble strengen ikke godtatt så snart den inneholdt et tegn som ikke var i uttrykket.

hepp skrev:Du kan derfor enten sjekke at den inneholder kun disse tegnene fra starten til slutten av strengen, eller sjekke om den inneholder andre bokstaver enn de tillatte.

Det var det jeg ønsket.

hepp skrev:
Kode: Merk alt
if ( ! preg_match('/^[a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]+$/D', $newname)) {
  // Ulovlige tegn i strengen
} 

Har her lagt til en modifier D for ikke å matche newline på slutten av strengen.

Ikke nødvendig. Stringen vil aldri inneholde linjeskift.

hepp skrev:Alternativt
Kode: Merk alt
if (preg_match('/[^a-zA-Z0-9_\-@!#&()æøåÆØÅäöÄÖ]/', $newname)) {
  // Ulovlige tegn i strengen
} 

Dette ser smartere ut ja. Det var kanskje noe sånt nukleuz siktet til. Skal prøve det.

Der var det!
Det enkle er alltid det beste. Det er alltid lett når man har funnet svaret! :)

Hjertelig takk for hjelpen, alle!
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg DavidS » 25.11.2011 0:26

hepp skrev:Har her lagt til en modifier D for ikke å matche newline på slutten av strengen.

Nå skal jeg ikke ta deg i og ikke vite følgende, men det kan være et greit tips:
"\z" istedenfor "$" vil ha samme nytte (dollar godtar newline på slutten av stringen, mens \z gjør ikke det).

Men pytt pytt!

Jeg kan jo heller ikke la være å skrive om litt heller.. :
Kode: Merk alt
if (preg_match('/^[\w@!#&()æøåÆØÅäöÄÖ_-]+\z/'$newname)) {
  
// Lovlig string, fra start til slutt
}  
DavidS
Seniormedlem
 
Innlegg: 3667
Registrert: 17.05.2006 17:08

Re: Regulæruttrykk - igjen

Innlegg hepp » 25.11.2011 0:50

Copy, pastet og tenkte på whitespace først i etterkant. Definitivt en mer sexy regex det der ;)
Insanity: doing the same thing over and over again and expecting different results.
Brukerens avatar
hepp
Seniormedlem
 
Innlegg: 1589
Registrert: 17.12.2003 22:06

Re: Regulæruttrykk - igjen

Innlegg ingeva » 25.11.2011 3:23

DavidS skrev:
Kode: Merk alt
if (preg_match('/^[\w@!#&()æøåÆØÅäöÄÖ_-]+\z/', $newname)) {
  // Lovlig string, fra start til slutt
}  

Synd å si det, men på tross av at det så smart ut, fungerer det ikke.
"ø" i stringern blir ikke godtatt. Jeg sjekket ikke de andre "spesielle" tegnene.
Hva tjener egentlig +\z til? Det ser jo ut til å fungere uten?
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg Fuzzy76 » 25.11.2011 10:26

Jeg tenkte motsatt, jeg mente ^ først og $ sist :)
Brukerens avatar
Fuzzy76
Moderator
 
Innlegg: 1266
Registrert: 29.11.2006 11:44
Bosted: Tromsø

Re: Regulæruttrykk - igjen

Innlegg ingeva » 25.11.2011 12:34

Fuzzy76 skrev:Jeg tenkte motsatt, jeg mente ^ først og $ sist :)

OK. Nå fungerer det iallfall som det skal. Uttrykket ser slik ut:

Kode: Merk alt
if (preg_match('/[^\w@!#&()æøåÆØÅäöÄÖ_-]/', $newname)) {
      // FEIL!
}
Altså hvis $newname inneholder ett eller flere tegn som IKKE finnes i regexet, så er det feil.
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg Nukleuz » 25.11.2011 16:30

Det kan jo ikke være rett, i og med at du har en ^ (not) med i klassen.

Funker:

Kode: Merk alt
function valNewname( $newName ) {
    return preg_match( '/^[\w@!#&()æäøöå_-]+\z/i', $newName );
}

if ( !valNewname( $newname ) ) {
    echo 'False!';
}
 


(i = case sensitive, for å kutte ned på regexp)
Mvh
Joachim M. Giæver
http://development.giaever.org
Brukerens avatar
Nukleuz
Seniormedlem
 
Innlegg: 1659
Registrert: 09.12.2006 2:08
Bosted: Tromsø

Re: Regulæruttrykk - igjen

Innlegg ingeva » 25.11.2011 17:23

[quote="Nukleuz"]Det kan jo ikke være rett, i og med at du har en ^ (not) med i klassen.

Det funker kanskje ikke i teorien, men det funker i praksis, og det er det som teller.
Jeg har testet med svært mange kombinasjoner og får rett og galt på de riktige stedene.
Det skal ikke være case-sensitivt. Både store og små bokstaver er tillatt. White-space er ikke.

I dette tilfelle er en funksjon overkill, siden det bare brukes ett sted.
Jeg gjør tilsvarende også et par andre steder, men med et litt modifisert regex.
Takket være hjelpen jeg har fått virker det nå slik det skal, og da er jeg fornøyd.
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg Nukleuz » 28.11.2011 9:52

Hei.

Jeg mener at dersom det ikke funkerer i teorien, men likevel ser ut til å fungere i praksis - er ikke det godt nok. Og en sikkerhetsrisiko.

Lykke til!
Mvh
Joachim M. Giæver
http://development.giaever.org
Brukerens avatar
Nukleuz
Seniormedlem
 
Innlegg: 1659
Registrert: 09.12.2006 2:08
Bosted: Tromsø

Re: Regulæruttrykk - igjen

Innlegg ingeva » 28.11.2011 11:01

Nukleuz skrev:Hei.
Jeg mener at dersom det ikke funkerer i teorien, men likevel ser ut til å fungere i praksis - er ikke det godt nok. Og en sikkerhetsrisiko.
Lykke til!

Sikkerhetsrisikoen består vel i så fall bare i at et sett brukerdata ikke blir funnet, og det er knapt mer enn et irritasjonsmoment i dette tilfelle - ikke en risiko.
Men det ser ikke ut til å fungere i praksis. Det fungerer i praksis! :)

Men takk for ditt engasjement!
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika

Re: Regulæruttrykk - igjen

Innlegg adeneo » 28.11.2011 15:22

Jeg er ikke så veldig sprek på regulære uttrykk, men som Nukleuz sier så matcher du på not når du skriver [^.....], noe som kanskje av en eller annen grunn virker, men som ikke er en spesielt god måte å gjøre det på.
Jeg har fått med meg såpass at dette er noe regex egentlig ikke er tiltenkt for, og man burde normalt prøve å skrive det andre veien i stedet.

Ut i fra det opprinnelige spørsmålet så ønsker du feil dersom strengen inneholder punktum, og en regex virker litt unødvendig for meg hvis det er det eneste du egentlig er ute etter, da det finnes en rekke verktøy for slikt i PHP.

Du kan bruke indexOf, strstr, strpos og sikkert mange andre løsninger for å oppnå dette enklere, noe slikt kanskje:

Kode: Merk alt
if (strpos($newName, '.') !== false) { //ikke feil }


eller

Kode: Merk alt
$kontroll = strstr($newName, '.');
if ($kontroll === false) { // feil }


Bare noen eksempler som må være bedre enn å bruke det som kalles "zero-width-assertions" (kanskje mer normalt kalt "look-aheads"), i regex'er, som er langt fra optimalt.
Eventuelt kan du matche strengen til godtatte tegn med en regex (riktige veien), og så bruke ett av PHP's string verktøy til å sjekke at den ikke inneholder punktum etterpå eller noe slikt.
adeneo
Medlem
 
Innlegg: 628
Registrert: 08.04.2011 21:09

Re: Regulæruttrykk - igjen

Innlegg ingeva » 28.11.2011 16:11

adeneo skrev:Jeg er ikke så veldig sprek på regulære uttrykk, men som Nukleuz sier så matcher du på not når du skriver [^.....], noe som kanskje av en eller annen grunn virker, men som ikke er en spesielt god måte å gjøre det på.
Jeg har fått med meg såpass at dette er noe regex egentlig ikke er tiltenkt for, og man burde normalt prøve å skrive det andre veien i stedet.

Ut i fra det opprinnelige spørsmålet så ønsker du feil dersom strengen inneholder punktum, og en regex virker litt unødvendig for meg hvis det er det eneste du egentlig er ute etter, da det finnes en rekke verktøy for slikt i PHP.

Du kan bruke indexOf, strstr, strpos og sikkert mange andre løsninger for å oppnå dette enklere, noe slikt kanskje:

Kode: Merk alt
if (strpos($newName, '.') !== false) { //ikke feil }


eller

Kode: Merk alt
$kontroll = strstr($newName, '.');
if ($kontroll === false) { // feil }


Bare noen eksempler som må være bedre enn å bruke det som kalles "zero-width-assertions" (kanskje mer normalt kalt "look-aheads"), i regex'er, som er langt fra optimalt.
Eventuelt kan du matche strengen til godtatte tegn med en regex (riktige veien), og så bruke ett av PHP's string verktøy til å sjekke at den ikke inneholder punktum etterpå eller noe slikt.

Hvis jeg hadde bare ønsket feil på punktum, så ville jeg gjort det slik du foreslår.
Jeg kunne ha brukt mitt opprinnelige regex PLUSS det du foreslår for å få med meg punktum, men jeg ville ha en løsning hvor jeg kunne bruke ett regex for å oppnå det jeg ville. Det har jeg funnet nå - med god hjelp fra deltakerne her. Det fungerer. Jeg har testet det frem og tilbake, og det virker hver gang, enten jeg skriver mitt "ord" rett eller galt. Da er jeg fornøyd. Jeg har fått det slik jeg vil ha det. Jeg har også lagt til /s i regex'et for å akseptere en string som også inneholder whitespace. Filnavn kan også inneholde white-space, iallfall i Linux, selv om det byr på visse problemer i Windows.
Det eneste som ergrer meg en smule er at æøåÆØÅäöÄÖ ikke er inkluder i \w, men de som har laget dette er stort sett amerikanere som ennå ikke har forstått at verden består av mer enn USA. Sånn har det vært i alle år, og det blir vel ikke stort bedre i vår levetid. Vi får være overbærende og innstille oss på å leve med det. Det er som kjent heller ikke velkomment i domenenavn, selv om problemet var kjent allerede på 1960-tallet, lenge før internett og web var påtenkt - men inntil et godt stykke ut på 70-tallet brukte vi jo bare 7-bits ASCII.
For de som bruker Windows er det fremdeles vanskelig å hente filer på Web med navn som starter på disse "sære" bokstavene. Det er til og med problemer med mellomrom! Forstå det den som kan.
"If you're staying with Microsoft you're getting more and more overwhelmed to update and change your whole IT infrastructure." Peter Hofmann . . . . Se her.
Brukerens avatar
ingeva
Seniormedlem
 
Innlegg: 1078
Registrert: 24.01.2011 6:48
Bosted: Sandvika


Gå til Avansert PHP

Hvem er i forumet

Brukere som leser i dette forumet: Ingen registrerte brukere og 4 gjester