Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 09:07 Der er 29 kommentarer og
1 løsning

preg_replace_callback php-kode i evaluering

Jeg har en preg_replace_callback hvor der kan ske at der er noget php kode med i mit input. Hvis det sker får jeg fejl. Hvordan kan jeg undgå det?

Fejlen opstår i følgende linje:

$str = preg_replace_callback('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/', create_function('$matches', 'return $matches[1].$wordwrap_callback($matches[2], $wrap).$matches[3];'), $str);
Avatar billede nielle Nybegynder
04. oktober 2007 - 09:16 #1
1) I stedet for at du bruger create_function() - lav en funktion ved siden af og angiv at det er den du bruger på callback-pladsen. Derved kommer du uden om at der kaldes eval() på din kode, og dermed skulle fejlen forsvinde af sig selv.

2) Man kan altis spekulere i om der overhovedet burde være PHP kode i din tekst...
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 09:32 #2
hov.. jeg mener selvfølgelig ikke at php koden skal evalueres, men at den kun skal behandles som ren tekst.. :)

jeg ved heller ikke om det er der fejlen præcis ligger..

jeg har lige ændret lidt på min kode, da den egentlig er en del af en class

$str = preg_replace_callback('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/', create_function('$match', 'return $match[1].$this->utf8_wordwrap_callback($match[2], $this->wrap).$match[3];'), $str);

Fatal error: Using $this when not in object context in /var/www/www.electrobeat.dk/www/v3/req/functions.php(424) : runtime-created function on line 1

den kan åbenbart ikke finde ud af hvor den skal referere til?
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 09:33 #3
så ikke lige du havde skrevet.. forsøger lige at lave en seperat funktion som du nævner
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 09:40 #4
Warning: preg_replace_callback() [function.preg-replace-callback]: Requires argument 2, 'callback_wordwrap', to be a valid callback in

    function utf8_wordwrap(&$str)
    {
        if(preg_match("/^$this->pattern_split$/", $str))
        {
            if(preg_match("/^$this->pattern_atag$/i", $str)) $str = preg_replace_callback("/$this->pattern_atag/i", 'callback_wordwrap_atag', $str);
            else $str = preg_replace_callback('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/', 'callback_wordwrap_tag', $str);
        }
        else $str = preg_replace_callback('/[^ \n]+/', 'callback_wordwrap', $str);
    }
   
    function callback_wordwrap_atag($match)
    {
        return $match[1].$this->utf8_wordwrap_link($match[2], $this->wrap).$match[3];
    }
   
    function callback_wordwrap_tag($match)
    {
        return $match[1].$this->utf8_wordwrap_callback($match[2], $this->wrap).$match[3];
    }
   
    function callback_wordwrap($match)
    {
        return $this->utf8_wordwrap_callback($match[0], $this->wrap);
    }

jeg ved egentlig heller ikke om det bare er nok at angive selve funktionen i sin preg_replace_callback uden objectet $this-> ?
Avatar billede nielle Nybegynder
04. oktober 2007 - 09:48 #5
Din callback funktion kaldes svjv. udenfor utf8_wordwrap klasens kontekst - du kan derfor ikke referere til $this.
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 09:54 #6
jeg er ikke helt med?

hvad udløser fejlen?
Avatar billede nielle Nybegynder
04. oktober 2007 - 09:56 #7
At du bruger "$this" i din callback_wordwrap_tag() funktion. Den er effektivt placeret udenfor klassen, og derfor kender den slet ikke $this. Der er intet du kan gøre for at udgå dette - sådan fungere callbacks i PHP (og andre sprog).
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 10:00 #8
med andre ord findes der ikke en løsning på mit problem? :(
Avatar billede pidgeot Nybegynder
04. oktober 2007 - 10:07 #9
Jo, det gør der sikkert nok - men ikke når callback_wordwrap ikke ligger i den klasse $this henviser til.

Tag et kig på syntaksen for callback-parametre - http://dk2.php.net/callback.

Såfremt du har brug for det ligger i en anden klasse, må du placere din reference til objektet et sted du kan komme til det udenfor klassen - hvordan du skal gøre det afhænger af en række ting der ikke fremgår af spørgsmålet, men en mulighed var at have disse funktioner i en separat klasse som du instantierer og giver en reference til objektet $this henviser til der hvor du kalder preg_replace_callback.
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 10:08 #10
Oprindelig havde jeg egentlig lavet mine preg's med /e flags

Umiddelbart virkede det, men hvis man ville poste php kode (som selvfølgelig ikke skulle evalueres men gå igennem som ren tekst) fik jeg fejl

I starten af min class og inden jeg påbegynder formateringen af stringen kører jeg den ellers igennem en stripslashes()

function utf8_wordwrap(&$str)
    {
        if(preg_match("/^$this->pattern_split$/", $str))
        {
            if(preg_match("/^$this->pattern_atag$/i", $str)) $str = preg_replace("/$this->pattern_atag/ie", 'stripslashes("\\1".$this->utf8_wordwrap_link("\\2", $this->wrap)."\\3")', $str);
            else $str = preg_replace('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/e', 'stripslashes("\\1".$this->utf8_wordwrap_callback("\\2", $this->wrap)."\\3")', $str);
        }
        else $str = preg_replace('/[^ \n]+/e', 'stripslashes($this->utf8_wordwrap_callback("\\0", $this->wrap))', $str);
    }
   
    function utf8_wordwrap_callback($str, $wrap)
    {
        if($wrap)
        {
            $str_len = str_utf8len($str);
            $wrap_count = ceil($str_len / $wrap);
           
            if($wrap_count > 1)
            {
                $pointer = 0;
                for($i = 0; $i <= $wrap_count; $i++)
                {
                    $arr[] = $this->utf8_substr($str, $pointer, $wrap);
                    $pointer += $wrap;
                }
               
                $str = implode(' ', $arr);
            }
        }
       
        return $str;
    }
Avatar billede nielle Nybegynder
04. oktober 2007 - 10:11 #11
Du kan jo "udkommentere" din PHP-kode før at du sender den igennem:

Ret "<?" og "?>" til f.eks. "[?" og "?]", send resultatet igennem din preg_replace_callback(), og bagefter retter du dem tilbage til "<?" og "?>"...
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 10:17 #12
pidgeot >
alle mine funktioner er i en og samme klasse
Avatar billede hoppe11 Nybegynder
04. oktober 2007 - 10:20 #13
ja, det var selvfølgelig en mulighed, nielle

men jeg har også ladet mig fortælle at det er en dårlig ide at bruge /e pga at det kan være svært at lave "kriterier" for sine matches?
Avatar billede nielle Nybegynder
04. oktober 2007 - 10:31 #14
Den har jeg ikke lige en menining om. Hvorfor skulle det være svært?
Avatar billede hoppe11 Nybegynder
09. oktober 2007 - 16:05 #15
nielle > det ved jeg ikke? det er ikke mig der er eksperten :)

jeg kan bare huske at jeg på et tidspunkt blev rådet til at bruge preg_replace_callback()

jeg har lidt travlt i øjeblikket, men ser på det så snart jeg har tid
Avatar billede nielle Nybegynder
09. oktober 2007 - 18:21 #16
Der er nogle sikkerhedsmæssige aspekter af at bruge .../e - men andet er der vist ikke med det. :^)
Avatar billede nielle Nybegynder
16. oktober 2007 - 08:39 #17
Er du kommet videre med denne her?
Avatar billede hoppe11 Nybegynder
16. oktober 2007 - 17:17 #18
hey nielle

nej, og gør det nok heller ikke lige indenfor de næste dage, men smid et spm så deler vi points

jeg må oprette det igen senere :)
Avatar billede nielle Nybegynder
16. oktober 2007 - 19:13 #19
Jeg smider et svar :^)

Men vi kan da bare fortsætte her når du engang får tid og lyst :^)
Avatar billede hoppe11 Nybegynder
17. oktober 2007 - 19:16 #20
Men nu skal jeg måske også lige være helt sikker på at jeg ved hvad /e modifieren gør :)

Den evaluerer vel kun selve output? Men hvad nu hvis man smider noget php kode igennem?

Hvis jeg smider en string ind i min preg_replace med /e får jeg fejl


Catchable fatal error: Object of class sql2txt could not be converted to string in /var/www/www.electrobeat.dk/www/v3/req/functions.php(425) : regexp code on line 1
Avatar billede hoppe11 Nybegynder
17. oktober 2007 - 19:18 #21
altså hvis der ryger rå php kode igennem.. koden skal ikke eksekveres

min preg:
preg_replace('/[^ \n]+/e', 'stripslashes($this->utf8_wordwrap_callback("\\0", $this->wrap))', $str);
Avatar billede nielle Nybegynder
17. oktober 2007 - 19:31 #22
Du kan læse om 'e' her:

http://dk2.php.net/manual/en/reference.pcre.pattern.modifiers.php

Kort fortalt forsøger den at kalde eval() på de der replaces med. Hvis der derfor er noget PHP-kode lignende i dette så skal dette opfylde korrekt PHP syntaks og ellers kommer der en fejlmeddelelse á la det du viser.
Avatar billede hoppe11 Nybegynder
17. oktober 2007 - 19:42 #23
med andre ord kan det altså ikke lade sig gøre at bruge /e samtidig med at der muligvis er noget php kode i input'et?
Avatar billede hoppe11 Nybegynder
17. oktober 2007 - 19:43 #24
her er hele min funtion for at give dig lidt overblik over det jeg vil

eventuel php kode i input'et skal ikke evalueres

function utf8_wordwrap(&$str)
    {
        if(preg_match("/^$this->pattern_split$/", $str))
        {
            if(preg_match("/^$this->pattern_atag$/i", $str)) $str = preg_replace("/$this->pattern_atag/ie", 'stripslashes("\\1".$this->utf8_wordwrap_link("\\2", $this->wrap)."\\3")', $str);
            else $str = preg_replace('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/e', 'stripslashes("\\1".$this->utf8_wordwrap_callback("\\2", $this->wrap)."\\3")', $str);
        }
        else $str = preg_replace('/[^ \n]+/e', 'stripslashes($this->utf8_wordwrap_callback("\\0", $this->wrap))', $str);
    }
Avatar billede nielle Nybegynder
17. oktober 2007 - 19:45 #25
Problemet er mere om der kommer noget PHP kode ind via $str.
Avatar billede hoppe11 Nybegynder
17. oktober 2007 - 20:11 #26
du mener ind i mine "match" eks. \\1 \\2 osv.
Avatar billede hoppe11 Nybegynder
18. oktober 2007 - 08:21 #27
Jeg har nu forsøgt at omskrive det hele med preg_replace_callback, men det virker ikke, dog får jeg ingen fejl. Der bliver kun returneret små bider af min tekst

Jeg prøvede også tidligere det her, men havde problemer med at referere til min callback funktioner i "preg_replace_callback" idet alle funktioner findes i en class

    function utf8_wordwrap(&$str)
    {
        if(preg_match("/^$this->pattern_split$/", $str))
        {
            if(preg_match("/^$this->pattern_atag$/i", $str)) $str = preg_replace_callback("/$this->pattern_atag/i", array($this, 'utf8_wordwrap_link_callback'), $str);
            else $str = preg_replace_callback('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/', array($this, 'utf8_wordwrap_callback'), $str);
        }
        else $str = preg_replace_callback('/[^ \n]+/', array($this, 'utf8_wordwrap_callback3'), $str);
       
        /*
        if(preg_match("/^$this->pattern_split$/", $str))
        {
            if(preg_match("/^$this->pattern_atag$/i", $str)) $str = preg_replace("/$this->pattern_atag/ie", 'stripslashes("\\1".$this->utf8_wordwrap_link("\\2", $this->wrap)."\\3")', $str);
            else $str = preg_replace('/(<[^>]+>)(([^<]+)(<\/\\1+>))?/e', 'stripslashes("\\1".$this->utf8_wordwrap_callback("\\2", $this->wrap)."\\3")', $str);
        }
        else $str = preg_replace('/[^ \n]+/e', 'stripslashes($this->utf8_wordwrap_callback("\\0", $this->wrap))', $str);
        */
    }
   
    function utf8_wordwrap_link_callback($arr)
    {
        return $arr[1].$this->utf8_wordwrap_link($arr[2], $this->wrap).$arr[3];
    }
   
    function utf8_wordwrap_link_callback2($str, $wrap)
    {
        $str_len = str_utf8len($str);
       
        if($str_len > $wrap)
        {
            $str_seq = floor($wrap * 1.2 / 2);
            $str = $this->utf8_substr($str, 0, $str_seq).'[...]'.$this->utf8_substr($str, $str_len-$str_seq, $str_len);
        }
       
        return $str;
    }
   
    function utf8_wordwrap_callback($arr)
    {
        return $arr[1].$this->utf8_wordwrap_callback2($arr[2], $this->wrap).$arr[3];
    }
   
    function utf8_wordwrap_callback2($str, $wrap)
    {
        if($wrap)
        {
            $str_len = str_utf8len($str);
            $wrap_count = ceil($str_len / $wrap);
           
            if($wrap_count > 1)
            {
                $pointer = 0;
                for($i = 0; $i <= $wrap_count; $i++)
                {
                    $arr[] = $this->utf8_substr($str, $pointer, $wrap);
                    $pointer += $wrap;
                }
               
                $str = implode(' ', $arr);
            }
        }
       
        return $str;
    }
   
    function utf8_wordwrap_callback3($arr)
    {
        return $this->utf8_wordwrap_callback($arr[0], $this->wrap);
    }
Avatar billede hoppe11 Nybegynder
18. oktober 2007 - 17:17 #28
endelig :)

tak for hjælpen
Avatar billede nielle Nybegynder
18. oktober 2007 - 23:03 #29
Skal det forstås som at du fik knækket den? :^)
Avatar billede hoppe11 Nybegynder
18. oktober 2007 - 23:49 #30
ja umiddelbart vil jeg tro det :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester