php-general Digest 15 Sep 2006 18:39:46 -0000 Issue 4349

Topics (messages 241807 through 241840):

Re: Form to subscribe a yahoo group
        241807 by: Manuel Lemos

Re: RSS Creator
        241808 by: Manuel Lemos

Re: Pre-printed forms
        241809 by: Google Kreme
        241831 by: Richard Lynch

Re: Question on explode and join.
        241810 by: Google Kreme

Re: security include from remote server
        241811 by: Miguel Vaz
        241823 by: Jon Anderson
        241838 by: Richard Lynch
        241839 by: Richard Lynch

Class question
        241812 by: Roger Helgesen
        241813 by: Thomas Munz
        241814 by: Andrei
        241815 by: Roger Helgesen

Just say "hello"
        241816 by: AraDaen
        241818 by: Joe Wollard
        241834 by: Ryan A
        241835 by: Dave Goodchild

correctly reading binary data from http post
        241817 by: Marek 'MMx' Ludha
        241822 by: Arpad Ray
        241837 by: Marek 'MMx' Ludha

php - mysql query issue
        241819 by: Dave Goodchild
        241820 by: Brad Bonkoski
        241821 by: Dave Goodchild
        241825 by: Andrei
        241830 by: Richard Lynch

Re: Months between two dates
        241824 by: Larry Garfield

Odd PHP memory issue
        241826 by: Matthew H. North
        241827 by: Michael B Allen
        241829 by: Richard Lynch

!diff => same
        241828 by: Richard Lynch

Re: DOM Question.  No pun intended.
        241832 by: Richard Lynch

Session issues
        241833 by: Dave Goodchild
        241836 by: Brad Fuller

Re: R: [PHP] session_start() and fopen
        241840 by: Richard Lynch

Administrivia:

To subscribe to the digest, e-mail:
        [EMAIL PROTECTED]

To unsubscribe from the digest, e-mail:
        [EMAIL PROTECTED]

To post to the list, e-mail:
        php-general@lists.php.net


----------------------------------------------------------------------
--- Begin Message ---
Hello,

on 09/06/2006 10:57 AM Wagner Garcia Campagner said the following:
> I have a web site and a yahoo group aswell.
> 
> I want to add a form in my site so that the visitor can put his/her e-mail 
> address and get subscribed in a yahoo group that i own.
> 
> I already have this form working... but the problem is that when the visitor 
> put his/her e-mail address and click the "Subscribe"
> button he/she gets redirected to the yahoo web site stating that he/she is 
> subscribed to the group.
> 
> I wanted to avoid this... so that the visitor doesn't leave my site... i was 
> thinking that i could make a form requesting the e-mail
> address and then send this information to another PHP script on my site... 
> this PHP script could send the information to the Yahoo
> web site and get the answer from then... and finally i could print something 
> for the visitor like "you were subscribed in the
> group"... so that he/she could stay in my web site and doesn't get 
> redirected...
> 
> Is there a way to do this using PHP???

This HTTP client class comes with an add-on that for logging in Yahoo
and executing some actions on behalf of the logged user, like for
instance inviting a user to subscribe to a group, as you need:

http://www.phpclasses.org/httpclient


-- 

Regards,
Manuel Lemos

Metastorage - Data object relational mapping layer generator
http://www.metastorage.net/

PHP Classes - Free ready to use OOP components written in PHP
http://www.phpclasses.org/

--- End Message ---
--- Begin Message ---
Hello,

on 08/31/2006 02:58 AM John Taylor-Johnston said the following:
> Has anyone created an RSS feed creator in PHP? I could make one fast
> enough, but ...

You may want to take a look at this RSS writer class:

http://www.phpclasses.org/rsswriter


-- 

Regards,
Manuel Lemos

Metastorage - Data object relational mapping layer generator
http://www.metastorage.net/

PHP Classes - Free ready to use OOP components written in PHP
http://www.phpclasses.org/

--- End Message ---
--- Begin Message ---
On 14 Sep 2006, at 05:35 , Man-wai Chang wrote:
How do you guys and gals use PHP+HTML+CSS to print a report to
preprinted forms with precision?

PDF. Printing support in HTML, even with CSS2 and 3, is primitive (and not well supported).

Generating a PDF is pretty straight forward though.

--
<http://en.wikipedia.org/wiki/TOFU>

--- End Message ---
--- Begin Message ---
On Thu, September 14, 2006 6:35 am, Man-wai Chang wrote:
> How do you guys and gals use PHP+HTML+CSS to print a report to
> preprinted forms with precision?

I'm not good enough with CSS to answer this directly.

If you find, as I suspect, that printers are just too diverse and
outright flaky for CSS to work right, you may want to consider:
http://php.net/fdf

> if the report is to be printed at client side, how do you do it? Via
> networked printer?

If it's getting printed at the client side, it's up to the
browser/user to choose their printer...

You've got zero control over that, as it should be.

Or else I'm completely misunderstanding this part...

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---

On 13 Sep 2006, at 11:02 , Dave Goodchild wrote:

$_SESSION['profane'] = false;

   foreach ($_POST as $value) {
       foreach ($swearbox as $profanity) {
           if (preg_match("/$profanity/i", $value)) {
           $errors = true;
           $_SESSION['profane'] = true;
mail(TECHEMAIL, 'profane content attack attempt on DJST', "From: {$_SERVER['REMOTE_ADDRESS']} Time: " . date('d F Y G:i:s', time()- TIMEDIFF),
'[EMAIL PROTECTED]');
           }
       }
   }

wouldn't that trigger on "assassination"<1> is "ass" was in $swearbox?

<1> twice

--
Do not meddle in the affairs of Dragons for you are crunchy and taste good with ketchup
--- End Message ---
--- Begin Message ---



Yes, 10 minutes after i sent my last email i realized that. They would be txt files, easily read anywhere.

        Encoders, you say? What do you mean?


        Pag




At 02:16 15-09-2006, Jon Anderson wrote:



If your sysadmins are trying to steal the code, all they'd have to do is download the same code your local scripts refer to (http://server/code.php.txt)...Seems to me that you might be better off using an encoder of some kind so they don't get their hands on the source. Using what I suggested is in no way secure or fast.

jon

--- End Message ---
--- Begin Message ---
Miguel Vaz wrote:
Yes, 10 minutes after i sent my last email i realized that. They would be txt files, easily read anywhere.

Encoders, you say? What do you mean?
This is one example. There are many more.

http://www.zend.com/products/zend_guard

I'm not sure if there are any open-source encoders, but I wouldn't be surprised either way.

jon

--- End Message ---
--- Begin Message ---
On Wed, September 13, 2006 6:48 pm, Miguel Vaz wrote:
>       I am doing a php+mysql website at my office, hosted locally but open
> to the web, but i wouldnt like to host my files on our office server.

You can use allow_url_fopen and then http://php.net/require (and
include) will be able to suck down PHP source from ANY place on the
Internet and execute it locally.

Of course, if you don't 100% TRUST that other place you are getting
the code from, you've got a major security hole.

And if you suspect people might want to attempt to hijack the
connection between the servers and feed you their own PHP instead of
your own, or even your own PHP *plus* their PHP (man-in-the-middle
attack) then you've got a major security hole.

And, of course, if somebody else is foolish enough to blindly install
something on the server that sucks down random PHP code from somewhere
else and executes it, you've got a major security hole.

So, it *CAN* be done, but with all kinds of potentials for major
security holes.

Depending on your needs/risk/skills/exposure, you may or may not want
to do this.  You'd want to at least consider making it an SSL or VPN
tunnel or something, so that the code is not subject to man in the
middle attack.

You might instead want to explore setting up rsync so you can have the
source in two places, or using subversion or CVS so you have have the
source in a single place, or some similar idea of having both sites
snag the source from a trusted location on a regular basis.

> I could host them somewhere else but our mysql database cant be
> accessed from the outside, only from our server.

If they are not letting you access the database from another server,
not even one specific server with mysql specially set up for that
purpose, then they'll probably be aghast at the idea of sucking down
random bits of PHP code from somewhere else and running it.

>       I thought about having a simple php local file that would include my
> files that are hosted someplace else, and therefor be able to access
> my local database, would that be possible? My first thought would
> probably be no, but i cant really do any tests right now, thats why i
> am asking you guys.

It *CAN* be done.  It's just probably not a Good Idea, in most cases,
or at least there's probably a Better Way.

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---
On Thu, September 14, 2006 8:00 pm, Miguel Vaz wrote:
>
>
>          Yes, right on the spot. Main reasons being code theft and
> using it on other projects. This being done by our office (its
> actually a college and i work in a multimedia department) system
> administrators, which are nothing left than arrogant leaches.
>
>          All i was missing from your suggestion was the fact that i
> would need to have my files remotely hosted and not using the .php
> extension. Great help, thanks.

Errrr.

Now, instead of just the arrogant leaches [sic] in your department,
college, etc, you have opened up your code to the ENTIRE WORLD of
arrogant leaches to steal...

I don't think this is what you want...

Maybe just find a new job. :-)

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---
I have 3 classes, CLASS A,B and C

class A {
         var $some_var;
          var $class_B;
         function A(){
               $this->class_B = new B();
               $this->some_var=2;
         }
}

class B {
         var $some_var;
          var $class_C;
         function B(){
               $this->class_C = new C();
               $this->some_var= some_var_from_class_A;
         }
}

class C {
         var $some_var;
function C(){
               $this->some_var= some_var_from_class_A;
         }
}



How can class B and C get the value of $some_var_class_A without using "$this->class_B = new B($some_var);"


roger helgesen

--- End Message ---
--- Begin Message ---
Use 'extends' syntax for sub classes

class A {
          var $some_var;
           var $class_B;
          function A(){
                $this->class_B = new B();
                $this->some_var=2;
          }
}

class B extends A {
          var $class_C;
          function B(){
                $this->A();
                $this->class_C = new C();
               //  $this->some_var= some_var_from_class_A; <-- $this->some_var 
contains the value allready
          }
}

class C extends A {
          function C(){
                $this->A();
                // $this->some_var= some_var_from_class_A; <-- $this->some_var 
contains the value allready
          }
}

on Friday 15 September 2006 11:01, Roger Helgesen wrote:
> I have 3 classes, CLASS A,B and C
>
> class A {
>           var $some_var;
>            var $class_B;
>           function A(){
>                 $this->class_B = new B();
>                 $this->some_var=2;
>           }
> }
>
> class B {
>           var $some_var;
>            var $class_C;
>           function B(){
>                 $this->class_C = new C();
>                 $this->some_var= some_var_from_class_A;
>           }
> }
>
> class C {
>           var $some_var;
>
>           function C(){
>                 $this->some_var= some_var_from_class_A;
>           }
> }
>
>
>
> How can class B and C get the value of $some_var_class_A without using
> "$this->class_B = new B($some_var);"
>
>
> roger helgesen

--- End Message ---
--- Begin Message ---
        Well in this example it will get to an infinite loop, but anyway like
Thomas said you must check into extending classes.

        Andy

Thomas Munz wrote:
> Use 'extends' syntax for sub classes
> 
> class A {
>           var $some_var;
>            var $class_B;
>           function A(){
>                 $this->class_B = new B();
>                 $this->some_var=2;
>           }
> }
> 
> class B extends A {
>           var $class_C;
>           function B(){
>                 $this->A();
>                 $this->class_C = new C();
>                //  $this->some_var= some_var_from_class_A; <-- 
> $this->some_var contains the value allready
>           }
> }
> 
> class C extends A {
>           function C(){
>                 $this->A();
>                 // $this->some_var= some_var_from_class_A; <-- 
> $this->some_var contains the value allready
>           }
> }
> 

--- End Message ---
--- Begin Message ---
What does "$this->A(); "" do ?(in constructor of class B)
does it make another instance of class A, and if not why do I have to parse vars to the A constructor ($this->A($var1,$var2))?.
I dont think that is what I want.
A can have many instances of B. B can have many instances of C.


                                                     A
B B B B
                     CCCC         CCCC      CCCC        CCCC

Should not a instanse(object) of class B bee able to request av var of the calling object (class A)?

Sorry about this stupid questions, I'm not a coder.
Thomas Munz wrote:
Use 'extends' syntax for sub classes

class A {
          var $some_var;
           var $class_B;
          function A(){
                $this->class_B = new B();
                $this->some_var=2;
          }
}

class B extends A {
          var $class_C;
          function B(){
                $this->A();
                $this->class_C = new C();
               //  $this->some_var= some_var_from_class_A; <-- $this->some_var 
contains the value allready
          }
}

class C extends A {
          function C(){
                $this->A();
                // $this->some_var= some_var_from_class_A; <-- $this->some_var 
contains the value allready
          }
}

on Friday 15 September 2006 11:01, Roger Helgesen wrote:
I have 3 classes, CLASS A,B and C

class A {
          var $some_var;
           var $class_B;
          function A(){
                $this->class_B = new B();
                $this->some_var=2;
          }
}

class B {
          var $some_var;
           var $class_C;
          function B(){
                $this->class_C = new C();
                $this->some_var= some_var_from_class_A;
          }
}

class C {
          var $some_var;

          function C(){
                $this->some_var= some_var_from_class_A;
          }
}



How can class B and C get the value of $some_var_class_A without using
"$this->class_B = new B($some_var);"


roger helgesen


--- End Message ---
--- Begin Message ---
Hi from Spain. This is my first post and im sure it wont be last :)



AraDaen

--- End Message ---
--- Begin Message ---
Hi AraDaen, and welcome to the list ;-)

On Sep 15, 2006, at 7:32 AM, AraDaen wrote:


Hi from Spain. This is my first post and im sure it wont be last :)



AraDaen

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


--- End Message ---
--- Begin Message ---
RTFM




Oops, sorry, that seems to be everyone favourite so
thought i would be the first one to say it... and
welcome to the list :)

Cheers!

------
- The faulty interface lies between the chair and the keyboard.
- Creativity is great, but plagiarism is faster!
- Smile, everyone loves a moron. :-)

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

--- End Message ---
--- Begin Message ---
Lea el f**king manual!

On 15/09/06, Ryan A <[EMAIL PROTECTED]> wrote:

RTFM




Oops, sorry, that seems to be everyone favourite so
thought i would be the first one to say it... and
welcome to the list :)

Cheers!

------
- The faulty interface lies between the chair and the keyboard.
- Creativity is great, but plagiarism is faster!
- Smile, everyone loves a moron. :-)

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php




--
http://www.web-buddha.co.uk
http://www.projectkarma.co.uk

--- End Message ---
--- Begin Message ---
Hi.

I need to send large binary data over http post (so that urlencoding
or base64 encoding is not an option). I use request like this:
http://people.ksp.sk/~mmx/request
(there is a zero byte between A and B). There are 3 bytes of data, but when I do
<?php echo strlen($HTTP_POST_VARS['DATA']); ?>
it yields 1 (it truncates the string after the first zero byte). Is
there a way to access all of the binary post data correctly?
Thanks in advance for any advice.

--
Marek 'MMx' Ludha

--- End Message ---
--- Begin Message ---
Marek 'MMx' Ludha wrote:
I need to send large binary data over http post (so that urlencoding
or base64 encoding is not an option). I use request like this:
http://people.ksp.sk/~mmx/request
(there is a zero byte between A and B). There are 3 bytes of data, but when I do
<?php echo strlen($HTTP_POST_VARS['DATA']); ?>
it yields 1 (it truncates the string after the first zero byte). Is
The fact you're accessing it as an element of $HTTP_POST_VARS (which should be $_POST anyway) means it's expected to be URL encoded. Instead set your request Content-Type to octet-stream and grab the whole post body at once.

eg.

// To send...

$c = stream_context_create(
   array(
       'http' => array(
           'method' => 'post',
           'header' => 'Content-Type: application/octet-stream',
           'content' => "whatever you want \x00 here"
       )
   )
);
file_get_contents('http://example.com/foo.php', false, $c);
// To receive

$data = file_get_contents('php://input');

--- End Message ---
--- Begin Message ---
As I read through my first email again I see I didn't write clearly
what I intended, sorry for this. I already have an application that
sends binary data with requests like the one mentioned before. Now I
need to parse those requests using PHP. Since the content-type is
multipart/form-data, neither php://input nor $HTTP_RAW_POST_DATA
works.
That request type was taken from an example from w3c webpage
(http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4), so I
believe there will not be much trouble parsing them.

On 9/15/06, Arpad Ray <[EMAIL PROTECTED]> wrote:
The fact you're accessing it as an element of $HTTP_POST_VARS (which
should be $_POST anyway) means it's expected to be URL encoded.
Instead set your request Content-Type to octet-stream and grab the whole
post body at once.

eg.

// To send...

$c = stream_context_create(
    array(
        'http' => array(
            'method' => 'post',
            'header' => 'Content-Type: application/octet-stream',
            'content' => "whatever you want \x00 here"
        )
    )
);
file_get_contents('http://example.com/foo.php', false, $c);

// To receive

$data = file_get_contents('php://input');



--- End Message ---
--- Begin Message ---
Hi all. I am building an online events listing and when I run the following
query I get the expected result set:

SELECT events.id AS eventid, name, postcode, start_time, dates.date FROM
events, dates_events, dates WHERE dates_events.event_id = events.id and
dates_events.date_id = dates.id AND dates.date >= '$start_string' AND
dates.date <= '$end_string' ORDER BY date ASC

...however, when I look for a one-off event the following query fails:

SELECT events.id AS eventid, name, postcode, start_time, dates.date FROM
events, dates_events, dates WHERE dates_events.event_id = events.id and
dates_events.date_id = dates.id AND dates.date = '$start_string'  ORDER BY
date ASC

...if I query for that date in the dates table using this:

SELECT * FROM dates WHERE date = '$start_string'

I get the date record I expect. The second query above cannot seem to look
for a date that equals the supplied string (BTW, all data has been escaped
prior to interpolation in the query string!)

Any ideas why not? I know it's more of a mySQL question so apologies in
advance!

--
http://www.web-buddha.co.uk
http://www.projectkarma.co.uk

--- End Message ---
--- Begin Message ---
Have you tried echoing out your query to run on the backend itself?
Maybe there is some problem with how your join is being constructed...
Perhaps a left outer join is called for? Hard to tell without having knowledge of your table structure and table data...

-B

Dave Goodchild wrote:
Hi all. I am building an online events listing and when I run the following
query I get the expected result set:

SELECT events.id AS eventid, name, postcode, start_time, dates.date FROM
events, dates_events, dates WHERE dates_events.event_id = events.id and
dates_events.date_id = dates.id AND dates.date >= '$start_string' AND
dates.date <= '$end_string' ORDER BY date ASC

...however, when I look for a one-off event the following query fails:

SELECT events.id AS eventid, name, postcode, start_time, dates.date FROM
events, dates_events, dates WHERE dates_events.event_id = events.id and
dates_events.date_id = dates.id AND dates.date = '$start_string' ORDER BY
date ASC

...if I query for that date in the dates table using this:

SELECT * FROM dates WHERE date = '$start_string'

I get the date record I expect. The second query above cannot seem to look for a date that equals the supplied string (BTW, all data has been escaped
prior to interpolation in the query string!)

Any ideas why not? I know it's more of a mySQL question so apologies in
advance!


--- End Message ---
--- Begin Message ---
On 15/09/06, Brad Bonkoski <[EMAIL PROTECTED]> wrote:

Have you tried echoing out your query to run on the backend itself?
Maybe there is some problem with how your join is being constructed...
Perhaps a left outer join is called for?  Hard to tell without having
knowledge of your table structure and table data...

Yep, I've echoed it and it says:

"...WHERE dates.date = '2006-10-03'..."

I think you're right on the join stakes, I will investigate further, many
thanks and have a great weekend.

--- End Message ---
--- Begin Message ---
        Also you should check if dates.date is a DATE type, not DATETIME. Lost
some time on that when I wanted to select enregs for a specific date,
field was DATETIME and I was querying `date` = '2006-01-01'... :p

        Andy

Dave Goodchild wrote:
> On 15/09/06, Brad Bonkoski <[EMAIL PROTECTED]> wrote:
>>
>> Have you tried echoing out your query to run on the backend itself?
>> Maybe there is some problem with how your join is being constructed...
>> Perhaps a left outer join is called for?  Hard to tell without having
>> knowledge of your table structure and table data...
>>
>> Yep, I've echoed it and it says:
> 
> "...WHERE dates.date = '2006-10-03'..."
> 
> I think you're right on the join stakes, I will investigate further, many
> thanks and have a great weekend.
> 

--- End Message ---
--- Begin Message ---
On Fri, September 15, 2006 7:35 am, Dave Goodchild wrote:
> Hi all. I am building an online events listing and when I run the
> following
> query I get the expected result set:

> Any ideas why not? I know it's more of a mySQL question so apologies
> in
> advance!

Well, you'd have to tell us what's in $start_string.

Otherwise, we are just making wild guesses with nothing to back them up.

And, really, to be 100% certain, you'd want to echo out the query
you've built after $start_string is interpolated.

$query = "SELECT ... '$start_string' ...";
echo $query, "<hr />\n";
mysql_query($query, $connection);

After you've done that, it's dollars to donuts that you won't need us
to answer the question. :-)

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---
Depending on what you mean by "how many months", this could work too.

$months = (strtotime($time2) - strtotime($time1)) / (60*60*24*30)

That is, the number of seconds between those two dates divided by the number 
of seconds in a month (where month is normalized to 30 days).  That may or 
may not be an acceptable normalization for what you're doing.  

Cheers.

On Friday 15 September 2006 01:16, Phillip Baker wrote:
> Greetings Gents,
>
> I want to take two dates formatted as
> 11/1/1998
> 10/1/2008
>
> And find out how many months have elapsed between them.
> I was wondering if there was a quick and dirty way to do this without a for
> loop.

-- 
Larry Garfield                  AIM: LOLG42
[EMAIL PROTECTED]               ICQ: 6817012

"If nature has made any one thing less susceptible than all others of 
exclusive property, it is the action of the thinking power called an idea, 
which an individual may exclusively possess as long as he keeps it to 
himself; but the moment it is divulged, it forces itself into the possession 
of every one, and the receiver cannot dispossess himself of it."  -- Thomas 
Jefferson

--- End Message ---
--- Begin Message ---
Hello All,

I've been struggling with a rather obscure PHP memory issue for the
last few days.  Here's my setup:

FreeBSD 5.5
Apache2.0, PHP 5.1.6, and MySQL 4.1.x compiled from scratch (that is,
we're not using FreeBSD ports)
PHP is compiled with --enable-memory-limit and the limit is set to 8MB

We're developing a web application that involves traversal of a
hierarchical database structure (MySQL, PEAR::DB, and
PEAR::DB::DataObject).  Currently that traversal is done recursively,
and involves visiting thousands of nodes in the tree.  However, the
tree is relatively flat, and the recursion never gets more than 4 or 5
calls deep.  A severely truncated but illustrative version of the code
of interest is:

<?php

// ... setup database connection and other infrastructure ...

trigger_error(memory_get_usage());
$result = traverse_hierarchy();
trigger_error(memory_get_usage());

// ... do something with $result

?>

Exactly what the traverse_hierarchy function does is mostly irrelevant
to my question, as will become clear in a moment.

In practice, the first trigger_error outputs ~2.5MB (mostly in
$GLOBALS['_DB_DATAOBJECT']...), and the 2nd, after the traversal,
outputs ~8MB.  This puts us dangerously near our limit, and frequently
causes the application to quit as it reaches the 8MB limit.

The problem is this: the amount of data gathered is nowhere near the
~5.5 MB that PHP claims has been allocated during execution of
traverse_hierarchy, and attempts to figure out WHERE that memory has
been assigned have failed.  Consider the following alterations to the
code:

<?php

// ... setup database connection and other infrastructure ...

trigger_error(memory_get_usage());
$result = traverse_hierarchy();
trigger_error(memory_get_usage());
clear_globals();
trigger_error(memory_get_usage());

// function to iteratively unset all globals
function clear_globals() {
        foreach ($GLOBALS as $k => &$v) {
                if ($k === 'GLOBALS')
                        continue;
                $before = memory_get_usage();
                unset($v);
                unset($$k);
                unset($GLOBALS[$k]);
                $after = memory_get_usage();
                trigger_error($k.':'.($before-$after));
                unset($k);
        }
        unset($GLOBALS);
}

?>

The above code outputs the memory allocated before and after the
traversal, and before and after a function call (clear_globals) that
iteratively 'unset's all members of the $GLOBALS array.  It also
outputs the amount of memory reclaimed after each unset of the members
of $GLOBALS.

When I wrote this I expected something like the following (ignoring
the superfluous error text generated by trigger_error):

2500000
8000000
(key):(memory released)
.
.
.
40000

Where 40000 is about the minimum memory footprint of an empty PHP
script as reported by memory_get_usage(), and where one of the
(key):(memory released) outputs would identify the memory hogging
culprit.  However, what I got instead was something like:

2500000
8000000
(key):(memory released)
.
.
.
5500000

After unsetting ALL globals within the global context (there are no
stack frames present, and therefore no non-global variables), PHP
still claimed my script was holding onto 5.5MB!!

Note that traverse_hierarchy does not do anything that results in
additional code being evaluated.  There are no new function
definitions, includes, or evals.  So the additional memory is not
being used to store any new function or class definitions.  All
non-global memory allocated by the function (theoretically) goes away
when the function exits, and all globals allocated by the function get
unset by the clear_globals function.  I'm leaking memory somewhere --
the question is where?

I've scoured my own code -- and even tentatively looked at
DB_DataObject -- for cases of circular references, and have found
none.

The question is this: Given the following assumptions:

1) PHP's memory manager reclaims memory when all references to that memory are
gone.
2) A reference is 'gone' when it goes out of scope or is 'unset'.
3) The only references that remain in the global context are
references to globals (all non-global variables have gone out of scope
and that memory reclaimed)
4) $GLOBALS is a PHP special associative array that contains the name and
value of all global variables.
5) By doing unset($GLOBALS[$varname]) and unset($$varname), where $varname
is
each key of the $GLOBALS array, I am effectively eliminating all remaining
references, and all allocated memory should be reclaimed by the memory
manager (except perhaps for memory associated with function and class
definitions).
6) Resources (think database resources) are automatically freed by
garbage collection when there are no more references to them
7) No additional code is being evaluated within traverse_hierarchy
8) I'm correct that there aren't any circular references in my code
nor in any PEAR module code

Are there any other ways that user code can result in this apparent
memory leak situation?  If so, what are they?

Or, are any of my first 6 assumptions incorrect?

Thanks for any help,

-- 
Matthew H. North
mailto:[EMAIL PROTECTED]

--- End Message ---
--- Begin Message ---
On Fri, 15 Sep 2006 08:42:26 -0700
"Matthew H. North" <[EMAIL PROTECTED]> wrote:

> 6) Resources (think database resources) are automatically freed by
> garbage collection when there are no more references to them

Resources can be "persistent". Try traversing a small tree and print
memory usage after each of several executions. If the memory is increasing
each time there is a memory leak in the extension. I doubt that is the
problem but it's a good test because it will show you with certainty
that data is in fact being released when the script exits. Then I would
scale down your test. Create a db connection and close it printing
memory usage along the way to make sure all memory is restored within
the script execution. If that doesn't work there are memory references
hanging around *somewhere*.

Mike

-- 
Michael B Allen
PHP Active Directory SSO
http://www.ioplex.com/

--- End Message ---
--- Begin Message ---
On Fri, September 15, 2006 10:42 am, Matthew H. North wrote:
> We're developing a web application that involves traversal of a
> hierarchical database structure (MySQL, PEAR::DB, and
> PEAR::DB::DataObject).  Currently that traversal is done recursively,
> and involves visiting thousands of nodes in the tree.  However, the
> tree is relatively flat, and the recursion never gets more than 4 or 5
> calls deep.  A severely truncated but illustrative version of the code
> of interest is:

So you are just visiting the nodes, and not doing anything with them?

It's entirely possible that PEAR::DB and/or DataObject are trying to
cache something to "help" you...

You should be able to quickly hack a *BAD* page of code with minimal
error checking to do whatever queries PEAR::DB is doing for you.

Take those out of the picture with just mysql_query() calls to see if
it's in your code, or in PEAR code.

This will at least break the problem into the "my code" versus "their
code" category.

For some web apps, the advantages of PEAR::DB and friends is pretty
thin...

> trigger_error(memory_get_usage());
> $result = traverse_hierarchy();

At crucial points within the hierarchy, perhaps at nodes/leaves you
expect to be at specific milestones (halfway, 25%, 75%, ...) start
adding code that does crude things like:

if ($node->name == 'This one node we think is halfway through')
trigger_error(memory_get_usage());

Log the numbers into a db with the node names and then later graph it
to see if the memory is getting chewed up in a straight line or if it
jumps at some point.

If there's a big jump somewhere, you know where to look.

If it's a straight line, then you can start doing the same thing line
by line to find where the RAM is going.

> 2500000
> 8000000
> (key):(memory released)
> .
> .
> .
> 5500000
>
> After unsetting ALL globals within the global context (there are no
> stack frames present, and therefore no non-global variables), PHP
> still claimed my script was holding onto 5.5MB!!

Did you close down the DB connection and kill the PEAR objects?...

PHP's garbage collection has had... issues... in the past.

> The question is this: Given the following assumptions:
>
> 1) PHP's memory manager reclaims memory when all references to that
> memory are
> gone.

Well, it tries to anyway...

It's not always that simple, particular with variable variables and
other dynamic features.

> 2) A reference is 'gone' when it goes out of scope or is 'unset'.

Scope seems like it should be simple, but it's not.

Use unset to be certain.

> 3) The only references that remain in the global context are
> references to globals (all non-global variables have gone out of scope
> and that memory reclaimed)

See #1.

PHP "scope" is not as clean-cut as C.

A simple "for" loop in PHP leaves the iterator variable, last I checked.

Inside a function, that should go out of scope.  Outside a function,
it stays around.  foreach, I think, correctly un-scopes the vars.

> 4) $GLOBALS is a PHP special associative array that contains the name
> and
> value of all global variables.

Yes.

> 5) By doing unset($GLOBALS[$varname]) and unset($$varname), where
> $varname
> is
> each key of the $GLOBALS array, I am effectively eliminating all
> remaining
> references, and all allocated memory should be reclaimed by the memory
> manager (except perhaps for memory associated with function and class
> definitions).

No.

Dangling pointers and references not correctly cleaned up from a
function are left out in limbo.

> 6) Resources (think database resources) are automatically freed by
> garbage collection when there are no more references to them

Probably, eventually, if PHP's GC kicks in when you think it does.

To be certain, close the DB references when you are done with them.

> 7) No additional code is being evaluated within traverse_hierarchy
> 8) I'm correct that there aren't any circular references in my code
> nor in any PEAR module code

Circular references are not a problem, really.

It's the ones that get chopped off from any connection to anything you
can get ahold of and start releasing that matter.

And if you get a whole big chain of them, with no root to tie onto to
start releasing...

> Are there any other ways that user code can result in this apparent
> memory leak situation?  If so, what are they?

PHP Extensions can have a memory leak.  Ain't much PHP can do about
that, really.

> Or, are any of my first 6 assumptions incorrect?

They're a little too optimistic. :-)

In the meantime, of course, just crank up your memory_limit to 16M --
It's going to be the default in PHP6 anyway, and many many many web
apps these days need 16M just to start.

Not that you want to ignore the problem, but you've got better things
to do than chase this down in fire drill mode if your servers can
handle 16M limit instead of 8M.

If you're talking super high-volume high-load site, maybe this IS
priority #1.

But for MOST web apps, on MOST common usage, cranking to 16M instead
of 8M to "solve" the problem, as irritating as it might be to your
purist soul, is the Right Answer.  You'll never notice the difference,
it won't cost you a dime, and you'll be able to move on to the next
task.

Long-term, you want to find out what you are doing to chew up 5.5M for
nothing, and stop doing that, of course, as it WILL matter some day.


-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---
I'm working on a project where I believe the code could be re-factored
for a vast improvement.

I'm interested in hearing about tools that are the opposite of "diff"

The goal is to locate common chunks of code, and to re-factor them
into include files, functions, whatever.

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---
Crude outside-the-box work-around...

You are only looking for <div and </div and what's between them, right?

Playing with strpos and a simple stack for nested DIVs should let you
hack this in a crude parser:

<?php
//Untested code, off the top of my head:
$divs = array();
$stack = array();
$offset = 0;
$len = strlen($html);
while($offset < $len){
  $divpos = strpos($html, '<div', $offset);
  $endpos = strpos($html, '</div', $offset);
  if ($divpos === false && $endpos === false) break;
  if ($divpos !== false && $divpos < $endpos){
    array_push($stack, array($offset, $divpos));
    $offset = $divpos + 1;
  }
  else{
    $start = array_pop($stack);
    $divs = array($start, array($offset, $endpos));
    $offset = $endpos + 1;
  }
}
var_dump($divs);
?>

This should give you offsets to the beginning/end of each DIV tag.

I'm sure I've got a one-off error or I'm not tracking quite the right
numbers, or that I'm tracking extra numbers you don't need, but the
idea is sound.

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---
--- Begin Message ---
Hi all. I am using php sessions in an online events listing to carry around
user data until all data is clean and then entering it into a database after
the final form has been submitted. On the first form the user selects a
category and postcode, and the processing script validates and cleans these
fields and passes them into corresponding session variables, same for 3 more
forms. All works like a dream - until now. Now the user enters the category
and postcode, goes to the next form, and the variables are not there in the
session. I am var_dumping the session at the top of each page to track the
behaviour to see what is happening and it only occurs here - when the user
goes back one page in each case their previously entered values are there
(as I echo the session variable in the fields), but not in the session
array.

Has anyone encountered this kind of problem with sessions before?

--
http://www.web-buddha.co.uk
http://www.projectkarma.co.uk

--- End Message ---
--- Begin Message ---
Is this only happening when the user clicks the "back" button in the
browser?

I recently had a similar problem with IE caching pages even when the header
is set to (supposedly) prevent caching.  Apparently there is a bug with IE
which requires a specific workaround.

The fields are pre-filled with the data the user entered (not the session
data; as you said the fields are filled in but the data isn't present in the
$_SESSION array)

Here is the workaround I found which works for my site.  I put this code at
the top of my page, before the call to session_start()

<code>

if(!strpos(strtolower($_SERVER[HTTP_USER_AGENT]), "msie") === FALSE)
{
   header("HTTP/1.x 205 OK");
} else {
   header("HTTP/1.x 200 OK");
}
header("Pragma: no-cache");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // date in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-cache, cachehack=".time());
header("Cache-Control: no-store, must-revalidate");
header("Cache-Control: post-check=-1, pre-check=-1", false);

</code>

Once the code is in place, clear your browser cache (temporary internet
files) before testing it or else it may still use the local (cached) copy.

Hope that helps,

Brad

-----Original Message-----
From: Dave Goodchild [mailto:[EMAIL PROTECTED] 
Sent: Friday, September 15, 2006 1:01 PM
To: PHP
Subject: [PHP] Session issues

Hi all. I am using php sessions in an online events listing to carry around
user data until all data is clean and then entering it into a database after
the final form has been submitted. On the first form the user selects a
category and postcode, and the processing script validates and cleans these
fields and passes them into corresponding session variables, same for 3 more
forms. All works like a dream - until now. Now the user enters the category
and postcode, goes to the next form, and the variables are not there in the
session. I am var_dumping the session at the top of each page to track the
behaviour to see what is happening and it only occurs here - when the user
goes back one page in each case their previously entered values are there
(as I echo the session variable in the fields), but not in the session
array.

Has anyone encountered this kind of problem with sessions before?

-- 
http://www.web-buddha.co.uk
http://www.projectkarma.co.uk

--- End Message ---
--- Begin Message ---
On Thu, September 14, 2006 1:17 pm, Fabri wrote:
> Hi Christopher: this is just a simplified code, I use it to generate
> some
> xml file, no loop is present.
>
> Try it as it is: you will find that two files will be generated while
> it
> should be only one.
> If you remove 'session_start()' then only one file will be generated:
> that's
> correct!

I suspect you are seeing a browser issue...

If your browser chooses to access the URL twice, just to get the
content, there's not much PHP can do about that...

It's only triggered by the session_start() because the browser is
stoopid about cookies, in some fashion.

Since all browsers are stoopid about cookies in some fashion, this
should come as no surprise. :-)

-- 
Like Music?
http://l-i-e.com/artists.htm

--- End Message ---

Reply via email to