[PHP/Regex] CGI Error bij aanroepen preg_match_all

Pagina: 1
Acties:

Onderwerpen


Verwijderd

Topicstarter
Voor een PHP script heb ik een class TemplateParser geschreven. Deze kan door middel van Regular Expressions een HTML opsplitsen in losse templates.
Deze losse templates worden aangegeven d.m.v. een 'start' en een 'end' tag in HTML comment formaat. Deze zien er zo uit: <!--#START:template_name--> en <!--#END:template_name-->.

Het uiteindelijke doel is dat deze templates los van elkaar in de database worden geplaatst en het dus gemakkelijker is pagina's te construeren.

Nu is het geval, dat er bij het aanroepen van preg_match_all een CGI error plaats vind, namelijk de volgende:
CGI Error
The specified CGI application misbehaved by not returning a complete set of HTTP headers. The headers it did return are:
Ik heb gegoogled op deze error, en heb een aantal oplossingen gevonden:
  • Niet de juiste rechten op extensions/php.exe
  • Een PHP bug (bron: http://bugs.php.net/bug.php?id=25504)
    maar dit is niet helemaal mijn situatie.
  • Het gebruik van de CLI versie van php.exe in plaats van de CGI versie.
Deze oplossingen heb ik allemaal geprobeerd, zonder resultaat.

De fout vind zich plaats in de volgende PHP code:
PHP:
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    function AddCompleteTemplate($input) {

        //First check input 
        if (!empty($input)) {
        
            
            // First thing to do is to split up the template
            $successive = false;
            $matches = array();

            $regex = "/(<!--#START:(.+)-->)((.|\n)*)(<!--#END:\\2-->)/";
            
            // HIER gaat het fout
            preg_match_all($regex, $input, $matches);
            //-------------------------
            
            // Loop through the matches         
            for ($i = 0; $i < count($matches[0]); $i++) {           

                if ($this->addtemplate($matches[2][$i], $matches[3][$i])) {
                
                    $successive = true;
                    
                } else {
                    
                    $successive = false;
                    
                }
                
            }
            
            return $successive;
            
        } else {
        
            // Invalid input
            return false;
            
        }

/*
 * De rest van TemplateParser
 */


Nog enkele opmerkelijke dingen:
  • PHP 4.4.0 draait als CGI module onder IIS 5 (Windows XP)
  • De gebruikte regular expression is getest.
  • preg_replace werkt wel.
Wie kan mij hier mee helpen?

[ Voor 3% gewijzigd door Verwijderd op 17-09-2005 13:28 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
*kick* Het probleem is helaas nog steeds niet opgelost. :r

[ Voor 4% gewijzigd door Verwijderd op 19-09-2005 19:51 ]


Acties:
  • 0 Henk 'm!

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Verwijderd schreef op maandag 19 september 2005 @ 19:51:
*kick* Het probleem is helaas nog steeds niet opgelost. :r
Als je het php-script CLI uitvoert, welke headers krijg je dan? (En vooral, wat komt er voor die headers?). (misschien zie je daar toevallig errors naar voren komen).

Lijkt me overigens wel een PHP-bug. (PHP verstuurt afaik de headers altijd voor error meldingen ed, misschien dat php hierop crasht (dan heeft php iig geen tijd om headers te sturen) ).

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Dit wijst inderdaad op een gecrasht php proces (of een gecrasht child process / thread van de webserver)

Ik zou er niet te veel tijd in stoppen, probeer een oplossing te verzinnen zonder preg_match_all o.i.d. en post een bug op php.net.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
drm schreef op maandag 19 september 2005 @ 22:58:
Dit wijst inderdaad op een gecrasht php proces (of een gecrasht child process / thread van de webserver)

Ik zou er niet te veel tijd in stoppen, probeer een oplossing te verzinnen zonder preg_match_all o.i.d. en post een bug op php.net.
Zou het dan toch een fout in de regular expression kunnen zijn? Ik heb de regular expression getest in expresso (een regular expression tool geschreven mbv .NET. Nu weet ik dat de regex engine in .NET net even iets anders werkt dan in PHP (perl).

Zijn er mensen die ervaring hebben met een PHP crash naar aanleiding van een verkeerde regular expression?

Ik zou het anders ook niet weten en zal een work-around moeten zoeken.

In ieder geval bedankt!

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

De regex is voor zover ik kan zien in orde. Een crash kan ik ook niet reproduceren. 't Hangt natuurlijk ook af van de input die je aan de regex voert, misschien kan je daar even een voorbeeldje van laten zien.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Tjoekbezoer
  • Registratie: Maart 2003
  • Laatst online: 18-11-2024
Ik zie zelf ook zo snel niks mis met je code. Ik wil overigens best eens proberen jouw template engine op mijn server te laten draaien, om te zien of het mss aan je installatie ligt. Wat ik ook kan doen is jou mijn template engine sturen, die werkt nl op dezelfde manier (voor zover ik dat kan zien). Laatste voorstel is natuurlijk maar een halve maatregel, maar als tijd niet je vriend is kan het je mss helpen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Tjoekbezoer schreef op dinsdag 20 september 2005 @ 13:09:
Ik wil overigens best eens proberen jouw template engine op mijn server te laten draaien, om te zien of het mss aan je installatie ligt.
Bedankt voor je aanbod, maar ik heb zelf een apache testserver tot mijn beschikking. Daar had ik nog niet aan gedacht. Wel is mijn bedoeling de templateparser op ieder systeem te kunnen laten werken. Dus de 'bug' moet er zowieso uit, of ik moet een goede work-around ontwikkelen.

Hier heb ik een stukje voorbeeld-code die de parser moet filteren:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!--#START:panel_main_welcome-->
<div id="pagetitle">;;pnl_welcome_title;;</div>
<div class="text">;;pnl_welcome_msg;;</div>
<!--#END:panel_main_welcome-->

<!--#START:panel_page_title-->
<div id="pagetitle">{0}</div>
<!--#END:panel_page_title-->

<!--#START:panel_main_result_table-->
<div>
<table width="558" border="1" cellpadding="2" cellspacing="1" id="restable">
<caption>;;pnl_gen_stats_main;;</caption>
  <tr>
    <td width="200" class="ttext">;;pnl_gen_stats_totvis;;:</td>
    <td width="64" class="text">{0}</td>
    <td width="200" class="ttext">;;pnl_gen_stats_avgweek;;:</td>
    <td width="64" class="text">{4}</td>
  </tr>
  <tr>
    <td class="ttext">;;pnl_gen_stats_blogitems;;:</td>
    <td class="text">{1}</td>
    <td class="ttext">;;pnl_gen_stats_avgcompp;;:</td>
    <td class="text">{5}</td>
  </tr>
  <tr>
    <td class="ttext">;;pnl_gen_stats_blogcomments;;:</td>
    <td class="text">{2}</td>
    <td class="ttext">;;pnl_gen_stats_bloggingdays;;:</td>
    <td class="text">{6}</td>
  </tr>
</table>
</div>
<!--#END:panel_main_result_table-->

  • Tjoekbezoer
  • Registratie: Maart 2003
  • Laatst online: 18-11-2024
Moet het ook mogelijk zijn om blokken te kunnen nesten? Dus een blok in een blok? of kunnen ze alleen onder elkaar geplaatst worden.

Overigens denk ik dat je regular expression nog wat problemen gaat opleveren. Ik heb het niet getest, dus pin me er niet op vast, maar hij lijkt me wat te greedy om al je blokken te vinden.

PHP:
1
$regex = "/(<!--#START:(.+)-->)((.|\n)*?)(<!--#END:\\2-->)/";


Misschien dat dat beter werkt. Overigens heb ik het persoonlijk nooit op deze manier aan de praat gekregen, ik heb het op een andere manier aangepakt (Bij mij is het wel mogelijk om blokken te nesten, dus mss dat mijn methode voor jou nutteloos is)

De vraag is of je er wat aan hebt, maar ik post hier maar gewoon de methode die bij mij de template analyseert, en een object georienteerd boom ervan maakt voor me. De details zijn niet zo relevant in dit geval, wat ik je wil laten zien is hoe ik mijn regular expression gebruik:

PHP:
1
define( "REG_ANALYZEBLOCKS", "/(BEGIN:|END:)\s*([^\f\n\r\t]+?)\s*\%\]([\s\S]*?)\\[\%/ims" );


Dat is 'em. Nog nooit problemen mee gehad. Dit ding herkent een tag als [% BEGIN: main %] en alles wat er achteraan komt, tot hij weer een blockname vind (kan zowel een BEGIN als een END zijn). Als het een BEGIN is voegt hij de tekst die hij erna vindt toe aan het nieuwe block wat 'ie net gevonden heeft. Vindt 'ie een END, dan voegt ie de tekst die erna komt toe aan het block waar 'ie hiervoor mee bezig was. Het is altijd ellende als ik probeer uit te leggen hoe mijn template engine werkt, hopelijk volg je me een beetje :)

Hier iig het stuk code die de tree voor me maakt (er is wat irrelevante code tussenuit gehaald om het leesbaar te maken):

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function maketree( $currentblockname="" ) {
    if( preg_match_all( REG_ANALYZEBLOCKS, $this->content, $res, PREG_SET_ORDER ) ) {
        // Loop thru all the blocks
        for( $i=0; $i < count( $res ); $i++ ) {
            list( $all, $status, $blockname, $content ) = $res[$i];
            
            if( is_object( $currentblock ) )
                $path = $currentblock->path;

            switch( $blockname )
            {
                default:
                    if( $status=="BEGIN:" )
                    {
                        // Start of a new block
                        unset( $block );
                        $block = new Block( $blockname, $content, COMPACT_DEFAULT );
                        
                        if( $i == 0 )
                        { // The main block gets special treatment
                            $this->main = $block;
                            $currentblock = &$this->main;
                        }
                        else
                        {
                            // de add_raw methode zorgt ervoor dat $block als kind wordt toegevoegd aan $currentblock
                            $currentblock->add_raw( $block );
                            $currentblock = &$block;
                        }
                    }
                    else
                    {
                        // End of a block, add this content to the parent
                        $block = &$currentblock->parent;
                        $block->elements[] = $content;
                        $currentblock = &$block;
                    }
            }
        }
        
        return true;
    }
    else
    {
        return false;
    }
}


Wat ik je als laatste nog kan aanraden:
  • Probeer je regular expression ook even op het droge, dus buiten je klasse om en zie of hij daar wel werkt.
  • Zet je regular expression in een if clause. Kan complete onzin zijn hoor, maar preg_match_all lijkt wat gevoelig als ik de bug reports er over lees. Niet geschoten is altijd mis nietwaar.
  • Zet overal debug meldingen tussendoor om te zien welke variabelen hij wel vult, welke niet. Misschien dat één van de parameters die je aan preg_match_all geeft per ongeluk leeg zijn, en dat is alsnog flipt?

Verwijderd

Topicstarter
Heel erg bedankt voor je uitgebreide reactie!

Blokken nesten is niet van belang in mijn parser class, nog niet althans.
  • Probeer je regular expression ook even op het droge, dus buiten je klasse om en zie of hij daar wel werkt.
  • Zet je regular expression in een if clause. Kan complete onzin zijn hoor, maar preg_match_all lijkt wat gevoelig als ik de bug reports er over lees. Niet geschoten is altijd mis nietwaar.
  • Zet overal debug meldingen tussendoor om te zien welke variabelen hij wel vult, welke niet.
    Misschien dat één van de parameters die je aan preg_match_all geeft per ongeluk leeg zijn, en dat is alsnog flipt?
De punten die je noemt ben ik allemaal al bijlangs gelopen, zonder resultaat helaas |:(

Vanavond ben ik van plan de methode waar de regular expression wordt gebruikt overnieuw te schrijven, en ga proberen een work-around te vinden voor deze regular expression.

Bedankt voor je verduidelijking mbv code, misschien dat het herkennen van geneste templates toch nog van pas kan komen!

Ondanks dat mijn probleem niet opgelost is, heb ik wel verscheidene reacties met oplossingen gehad, en denk dat hiermee mijn topic gesloten kan worden. bedankt!
Pagina: 1