Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

drcru posted:

They probably have terrible pings since you're likely somewhere in North America and they're XX hours away by plane.

I'm in the UK and so is the web server the site runs on, but I guess the same applies. Thing is, the game isn't one for which a high ping should make a difference. It's a web version of a board game, and it's played in a turn-based fashion via the web site (nothing more advanced than dynamically generated html pages), so nothing is time-critical. If they have a poor connection then I guess the pages would take longer to load than is ideal, but the way I read his email it sounded like they are sometimes unable to access the website at all. I was wondering whether there are any particularly likely reasons for that.

moops posted:

Don't reinvent the wheel.. Use gettext
http://php.net/gettext
Interesting suggestion and something I wasn't aware of. After a bit of googling I'm not sure how much easier I would find it to use this than to implement a solution of my own. The site has to output a certain number of sentences created out of building blocks and glue, whose precise details depend on the game situation*, and I'm not sure how messy it would be to try and integrate that with gettext. I also noticed that some sources described having to restart the web server if a translation is revised, which isn't an option for my hosting situation.

*e.g.
php:
<?
echo '<img src="gfx/trans1.png" border=\'0\'
alt="The '.$spacenumbers[$i].'industry space in '.
$spacetowns[$i].' is occupied by a'.$flipstatus.'flipped '. //**
$whatplayer.' Tech Level '.$TechLevels[$i].' '.
$whatindustry.'." style="position: absolute; top: '.
$TileYPositions[$CompactBoard][$i].'px; left: '.
$TileXPositions[$CompactBoard][$i].'px; z-index: 8"></a>';
?>
** Here $flipstatus is either ' ' or 'n un'.

Adbot
ADBOT LOVES YOU

KuruMonkey
Jul 23, 2004
Re: Hammerite

Well, you've built your code in a way that makes transaltion very awkward.

Ideally you would be using a system that builds strings with placemarkers for the values you need to insert. Like "you have :things: things remaining". Then run a function to insert your values in one go. You then need to know whether you need to translate before inserting them (in which case you need a method to exclude the placeholder tags from translation, e.g. not translating anything inbetween :: in my example string) or after.

Importantly in this; for the love of god build a string for your alt text then use that string when you build your markup tags; as it stands you have to extract it from your mess of code, since you don't want to be translating the a tag itself.

here's some psuedocode:

non-translated but not a mess either:
php:
<?
$image = 'gfx/trans1.png';
$params = array('things', 14);
$string = 'you have :things: thingies left';
//ready to output:
$alt = parameterise($string, $params);
echo make_img_tag($image, $alt);
?>
Now; parameterise() and make_img_tag() are going to be doing tasks you need to do A LOT - so factor them out into helper functions. Then if you need to alter the way parameters are inserted into strings, its easy to make the change everywhere.
(you can also be assured EVERY img tag is built right if you use a single fuction for them all)

massive change required for translation:
php:
<?
$image = 'gfx/trans1.png';
$params = array('things', 14);
$lang='de';
$string = 'you have :things: thingies left';
//ready to output:
$alt = parameterise(translate($string, $lang), $params);
echo make_img_tag($image, $alt);
?>
It would be possible (but possibly inadvisable) to make the translation step part of parameterise() so that the change only needed to be made in one place and then would be propagated to every string building operation in the program.

But I suspect you have made your bed of monolithic code. You must sleep in it.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

KuruMonkey posted:

But I suspect you have made your bed of monolithic code. You must sleep in it.

I think you may be thinking my code is worse than it actually is. I chose one of the most complicated examples I could find to make my point. The section I c&p'ed is actually part of the contents of a loop (for $i from 0 to 42, do...)

Tap
Apr 12, 2003

Note to self: Do not shove foreign objects in mouth.
I have a 'dataprocessor' library written in PHP that parses through a CSV file that varies in size (1K to 2M). The larger files end up taking quite a bit of memory because of the looping required to manipulate the actual data itself.

Now my question - is there a way to free up memory in PHP during the execution of the script? I call the unset() function on the variables that are unused but I don't think that unset is actually meant to free up memory.

supster
Sep 26, 2003

I'M TOO FUCKING STUPID
TO READ A SIMPLE GRAPH

Tap posted:

I have a 'dataprocessor' library written in PHP that parses through a CSV file that varies in size (1K to 2M). The larger files end up taking quite a bit of memory because of the looping required to manipulate the actual data itself.

Now my question - is there a way to free up memory in PHP during the execution of the script? I call the unset() function on the variables that are unused but I don't think that unset is actually meant to free up memory.
unset() will only free up the memory for that variable next gime garbage collection decides to come around and there's no way to force gc in PHP.

Begby
Apr 7, 2005

Light saber? Check. Black boots? Check. Codpiece? Check. He's more machine than kid now.

Tap posted:

I have a 'dataprocessor' library written in PHP that parses through a CSV file that varies in size (1K to 2M). The larger files end up taking quite a bit of memory because of the looping required to manipulate the actual data itself.

Now my question - is there a way to free up memory in PHP during the execution of the script? I call the unset() function on the variables that are unused but I don't think that unset is actually meant to free up memory.

Hrmm.... I wouldn't know how to optimize your code unless I saw it, but PHP is not always memory efficient when you load up a file. It could very well be that a 2mb file takes up 40mb of memory when you load the whole file up. Its just the way PHP is.

You should read up on how php manages memory and reference counting. Often unset won't do what you expect it to do, for instance in this case

code:
$x = 'hi there';
$y = $x;
unset($x);
Calling unset($x) in this example doesn't do much but free up a single reference. What the php processor did was set aside memory for 'hi there'. Then when you do $y=$x, $y actually becomes a reference to 'hi there' and the string is not actually copied (even though its supposed to be a copy). So when you do unset($x) all that happens is the reference count for 'hi there' is decremented by 1 and no real memory is actually freed.

From a coding and functional viewpoint though, you can work as though it was copied. If you then change the value of $x to something else, $y still will have a value of 'hi there' and $x will get assigned the new value. At that point the original memory location reference count is decremented by 1, and you now have two strings in memory, each with a ref count of 1. No calling unset($x) would actually free up space.

Confusing hey? Well you could be running into issues such as this when trying to optimize your code.

Zorilla
Mar 23, 2005

GOING APE SPIT

Begby posted:


I thought $y =& $x does a reference, not $y = $x . Does it work differently in your example?

supster
Sep 26, 2003

I'M TOO FUCKING STUPID
TO READ A SIMPLE GRAPH

Zorilla posted:

I thought $y =& $x does a reference, not $y = $x . Does it work differently in your example?
What he means is that PHP internally creates $y as a reference until either variable is modified, and then the copy is actually made. This was a great memory optimization introduced in PHP 5 because no one really used reference assignments (=&) like they should have (this is my own inference, not fact).

The following shows this behavior:
php:
<?
define(BASE_MEMORY, memory_get_usage());

function print_memory_change($str = "")
{
    $change = memory_get_usage() - BASE_MEMORY;
    echo "$str{$change}B\n";
}

print_memory_change('Initial: ');

$a = str_repeat(" ", 1048576);
print_memory_change('After $a init: ');

$b = $a;
print_memory_change('After $b "copy": ');

$b[0] = "_";
print_memory_change('After $b modify: ');

unset($a);
print_memory_change('After $a unset: ');

unset($b);
print_memory_change('After $b unset: ');
?>
And the output:
code:
Initial: 112B
After $a init: 1048936B
After $b "copy": 1049144B
After $b modify: 2097904B
After $a unset: 1049344B
After $b unset: 712B
Notice that the only memory usage difference between initializing $a and copying $a to $b is 208 bytes - this is just some overhead from the new variable, the refernece, and the print_memory_change call frame on the stack.

Not until $b (or $a) is modified is the actual value copy needed, and only then does PHP actually make the copy in memory.

supster fucked around with this message at 04:45 on May 20, 2009

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Did PHP garbage collect after the unset calls or does it just consider that memory free because it can be GCed whenever the hell GC runs?

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine

Munkeymon posted:

Did PHP garbage collect after the unset calls or does it just consider that memory free because it can be GCed whenever the hell GC runs?

No way to force it. It runs whenever, though I think you can encourage it to be more frequent with an ini setting, but I can't find it at the moment.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



That's not what I was asking. I'm asking whether PHP is reporting memory use after a hypotheical GC or whether the GC has already run and the memory is acually free to be used again.

spiritual bypass
Feb 19, 2008

Grimey Drawer
Anyone ever use dtrace with PHP? If it works well, I may just switch our servers over to Solaris.

supster
Sep 26, 2003

I'M TOO FUCKING STUPID
TO READ A SIMPLE GRAPH

Munkeymon posted:

That's not what I was asking. I'm asking whether PHP is reporting memory use after a hypotheical GC or whether the GC has already run and the memory is acually free to be used again.
That's a good question. I don't know. Either unset is forcing garbage collection to free up that object iff its reference count is 0, or memory_get_usage() returns the hypothetical memory usage.

I am tempted to say that unset() is actually freeing up the memory. If anyone knows for sure I would really like to know.

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
Getting this error:

quote:

Fatal error: require_once() [function.require]: Failed opening required 'PEAR.php' (include_path='.:/php/includes:/usr/share/php:/usr/share/pear') in /var/www/vhosts/foobar.org/httpdocs/Joomla159/administrator/components/com_civicrm/admin.civicrm.php on line 15

Except... PEAR.php exists in /usr/share/pear. Any ideas?

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Is this kind of memory usage too high? I have 1GB of RAM.

final: 607.7265625kB peak: 860.96484375kB
took 0.010162115097 seconds

edit: I'm doing three sql queries and processing the table data of one of the result sets in this page.

Acer Pilot fucked around with this message at 03:56 on May 21, 2009

supster
Sep 26, 2003

I'M TOO FUCKING STUPID
TO READ A SIMPLE GRAPH
lol no

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

supster posted:

lol no

Thank god. What would be too high for three sql queries? I haven't seen anything go over 1 megabyte.

supster
Sep 26, 2003

I'M TOO FUCKING STUPID
TO READ A SIMPLE GRAPH
Don't worry about it unless it is the direct cause of a problem.

Your question also can't be answered without more information. What is the data? What are you doing with the data? (Don't even bother answering these, it's not a problem.)

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Thanks, I've stopped worrying about it now.

Here's another one, what do you guys use for templating your pages? Other than Smarty that is. Do you roll your own systems or just put the HTML in with your code? I've been using Smarty personally but it seems a little too much for what I need to do.

Roctor
Aug 23, 2005

The doctor of rock.

drcru posted:

Thanks, I've stopped worrying about it now.

Here's another one, what do you guys use for templating your pages? Other than Smarty that is. Do you roll your own systems or just put the HTML in with your code? I've been using Smarty personally but it seems a little too much for what I need to do.

I don't use a templating system personally, but then it becomes my responsibility to make sure I keep anything but control logic out of my views.

Here's a small example of what my views end up looking like.
php:
<?php
foreach($mysqlResult as $res) :
?>
  <div><?php echo $res->title?></div>
  <div><?php echo $res->body?></div>
<?php
endforeach;
?>

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

drcru posted:

Thanks, I've stopped worrying about it now.

Here's another one, what do you guys use for templating your pages? Other than Smarty that is. Do you roll your own systems or just put the HTML in with your code? I've been using Smarty personally but it seems a little too much for what I need to do.

I use the CodeIgniter framework (although I am starting to use Kohana). If smarty is too much, then these are probably way overkill for you, but wouldn't hurt to take a gander.

Kohana: http://www.kohanaphp.com/
CodeIgniter: http://www.codeigniter.com

pooptart
Jun 17, 2003
I AM AN ANTI-AMERICAN LIBERAL WHO THINKS US SOLDERS SHOULD FIGHT INSURGENTS WITH STICKS
Nevermind.

pooptart fucked around with this message at 15:06 on May 23, 2009

comcor
May 11, 2005
Knife-wrench. Practical and safe. For kids!

supster posted:

That's a good question. I don't know. Either unset is forcing garbage collection to free up that object iff its reference count is 0, or memory_get_usage() returns the hypothetical memory usage.

I am tempted to say that unset() is actually freeing up the memory. If anyone knows for sure I would really like to know.

Garbage collection occurs two places: 1) when a scope ends (e.g. a return from a function or method) 2) when you call unset.

You can run a simple test to check that unset() actually causes the memory to be freed. For example, the following code is run and I watch the OSes reported memory usage (via top) - with the unset commented out, memory usage of the process grows and eventually it hits the memory limit. If I run it again with unset uncommented, it runs to completion without taking up any more memory than the "data" string needs while its still active:

code:
<?php
ini_set('memory_limit', '128M');
while ($i < 1000) {
    // give us a unique var name
    $name = "data_$i"; 
    $$name = str_repeat("A", 1024*1024); 
    $i++;
    print $name.' -> '.memory_get_usage()."\n";
    sleep(1);
    //unset($$name); // uncomment me to see that memory is freed
}
?>
For what its worth, the following function has appeared in the PHP 5.3.0 documentation, so now eventually you'll be able to force it:

http://us2.php.net/gc_enable

Sylink
Apr 17, 2004

I am making a wiki like site (I'm not using Mediawiki because I want something simpler) but I want to use/retain a lot of the similar formatting features as far as editing pages.

What is the standard way this is done?

Such as putting <p> tags around blocks of text and converting ==Hello World== into <h2>Hello World</h2> and so on. Is it just straight up string parsing with a lot of counting involved or is this a different way?

Or would it be easier to simply allow certain html tags?

EDIT: Would it be easier for me to just use something like php markdown ? http://michelf.com/projects/php-markdown/

Sylink fucked around with this message at 08:44 on May 24, 2009

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Sylink posted:

I am making a wiki like site (I'm not using Mediawiki because I want something simpler) but I want to use/retain a lot of the similar formatting features as far as editing pages.

What is the standard way this is done?

Such as putting <p> tags around blocks of text and converting ==Hello World== into <h2>Hello World</h2> and so on. Is it just straight up string parsing with a lot of counting involved or is this a different way?

Or would it be easier to simply allow certain html tags?

EDIT: Would it be easier for me to just use something like php markdown ? http://michelf.com/projects/php-markdown/

There are much simpler wikis out there. Why re-invent the wheel?

For the actual answer to your question, look at the source to Mediawiki and others and see how they do it.

Sylink
Apr 17, 2004

I want a different set of searchable attributes for pages and its easier to design it myself.

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Do any of these have anything in common? I saw someone making two way hashes like this and I'd like to try and do the same:

2ed3cbd5
11e1d49a
478c139d
d72d0f17

They look like they're hexadecimal and from what I see it's supposed to be related to the number 1073. Is there something in mcrypt that encodes variables like this?

edit: it looks like it has something to do with pack() and unpack()

Acer Pilot fucked around with this message at 01:39 on May 25, 2009

cannibustacap
Jul 7, 2003

Brrrruuuuuiinnssss
The "Try/Catch" feature of PHP isn't doing what I indend it to do..

php:
<?
while (true) {
  try {
    $xml = new SimpleXMLElement($url,null,true);
  }
  catch (Exception $e) {
    continue;
  }
  if ($xml) break;
}
?>
I am running a test in the above. What I notice is that URL fails like 20 times before it succeeds, so I just want it to continually try until "$xml" is set.

The problem is: The failed grabs shoot an error message out each time!

That is, when the line
php:
<?
  try {
    $xml = new SimpleXMLElement($url,null,true);
  }
?>
When that line fails, I get an:
code:
Warning: SimpleXMLElement::__construct([url]http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=______&Operation=ItemLookup&ItemId=B001413DF8&IdType=ASIN&ResponseGroup=Reviews&Version=2008-08-19&ReviewPage=1&ReviewSort=SubmissionDate[/url]) [function.SimpleXMLElement---construct]: failed to open stream: HTTP request failed! HTTP/1.1 503 Service Unavailable in /home/eric/www/test-eric2.php on line 15
It will cycle through that like 20 times until finally the $xml pops out.


How do I make sure the try/catch actually does suppress errors and not bug the end user?


I am fine with it failing 20 times, as long as it doesn't bug me with error messages and it, at some point, works. 20 failed attempts only delays the page by 2 seconds or so.

EDIT:

I think I found it! I just add the @ sign before "new"

So @new

cannibustacap fucked around with this message at 08:03 on May 26, 2009

Supervillin
Feb 6, 2005

Pillbug
Also you can set error_reporting explicitly, so you don't have to supress each individual error that might occur.
code:
error_reporting(E_ALL); // show everything (during development)
error_reporting(0);     // supress everything (during production)

Tron Paul
Dec 5, 2006

I'm trying to make a CMS for a Flash application that reads data from XML. I'm trying to use DOM PHP (it seemed a little more legit than SimpleXML when I started).

Reading and displaying XML with DOM is easy enough, but is there a simple way to edit it? Obviously I'm still pretty new to PHP, but I understand enough about the various DOM objects and methods I think, so it shouldn't be too hard to help if anyone can.

Also if anyone knows of a better way to manipulate XML, I'm open to that as well.

Thanks!

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

usingpond posted:

I'm trying to make a CMS for a Flash application that reads data from XML. I'm trying to use DOM PHP (it seemed a little more legit than SimpleXML when I started).

Reading and displaying XML with DOM is easy enough, but is there a simple way to edit it?

Use the DOM XML Methods for editing to edit it? What exactly are you having trouble figuring out what to do?

Tron Paul
Dec 5, 2006

Lumpy posted:

Use the DOM XML Methods for editing to edit it? What exactly are you having trouble figuring out what to do?

Well basically, I wanted to edit a child from this:

code:
<root>
   <parent name="parent">
      <child>info</child>
   </parent>
</root>
To this:
code:
<root>
   <parent name="parent">
      <child>DIFFERENT INFO</child>
   </parent>
</root>
I can't seem to figure out an easy way to use the replaceChild method, or if that's even the correct method to use. All the examples I've found are part of a huge framework that are really complex, and nothing seems to simply explain how to do such a basic function.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

usingpond posted:

Well basically, I wanted to edit a child from this:

code:
<root>
   <parent name="parent">
      <child>info</child>
   </parent>
</root>
To this:
code:
<root>
   <parent name="parent">
      <child>DIFFERENT INFO</child>
   </parent>
</root>
I can't seem to figure out an easy way to use the replaceChild method, or if that's even the correct method to use. All the examples I've found are part of a huge framework that are really complex, and nothing seems to simply explain how to do such a basic function.

I have no idea if you are using PHP4 or 5, here's a 4 example

php:
<?
// assume you've read in the XML to $myXML
$root = $myXML->document_element();
$parentTag = $root->first_child(); // you could skip this and do it directly below, but to be clear.
$childTag = $parentTag->first_child();
$childTag->replace_child("DIFFERENT INFO",$childTag->first_child());
?>
and since I'm such a drat nice guy, here's a PHP5 example:

php:
<?
$myXML = new DOMDocument();
$myXML->loadXML('<root><parent name="parent"><child>info</child></parent></root>');
$xpath = new DOMXpath($myXML);
$nodelist = $xpath->query('/root/parent/child');
$kidNode = $nodelist->item(0);
/* 
you could also have done:
$kidNode = $myXML->firstChild->firstChild->firstChild;
*/
$newContent = $myXML->createTextNode("DIFFERENT INFO");
$kidNode->replaceChild($newContent,$kidNode->firstChild);
echo "<PRE>";
echo htmlentities($myXML->saveXML());
echo "</PRE>";
?>

Lumpy fucked around with this message at 00:46 on May 27, 2009

Tron Paul
Dec 5, 2006

You are a drat nice guy! I am using PHP5, so thanks a bunch.

Works great, by the way!

Tron Paul fucked around with this message at 18:03 on May 27, 2009

Jreedy88
Jun 26, 2005
thirty4
I'm working on some PHP code some old guy set up here at work. I hadn't looked at anything PHP until two days ago, so I'm still fairly new to this. I came across this and it didn't look right. Also, I don't think it's working as intended. Please shed some light on this.

This function is called in one part of a file:
executefootagetransaction(false);

Here's the function signature:
function executefootagetransaction($zero, $consumeroll = false)


Firstly, if you're going to call a function, don't you need to supply both arguments? Secondly, what is that $consumeroll = false nonsense in the signature?

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Jreedy88 posted:

I'm working on some PHP code some old guy set up here at work. I hadn't looked at anything PHP until two days ago, so I'm still fairly new to this. I came across this and it didn't look right. Also, I don't think it's working as intended. Please shed some light on this.

This function is called in one part of a file:
executefootagetransaction(false);

Here's the function signature:
function executefootagetransaction($zero, $consumeroll = false)


Firstly, if you're going to call a function, don't you need to supply both arguments? Secondly, what is that $consumeroll = false nonsense in the signature?

Firstly, no.
Secondly, that's how you make it so you don't have to supply all the arguments.

In PHP, and many other languages, you can set arguments to default values, so taht if the argument is not supplied, it's set. Here's fun made up code to learn you:

php:
<?

function blah($name="Dave",$msg="Sup d00d")
{
 echo "Hey $name, $msg";
}

blah(); // "Hey Dave, Sup d00d"
blah("Larry"); // "Hey Larry, Sup d00d"
blah("Skippy","you suck"); // "Hey Skippy, you suck"
?>

Jreedy88
Jun 26, 2005
thirty4

Lumpy posted:

Firstly, no.
Secondly, that's how you make it so you don't have to supply all the arguments.

In PHP, and many other languages, you can set arguments to default values, so taht if the argument is not supplied, it's set. Here's fun made up code to learn you:

php:
<?

function blah($name="Dave",$msg="Sup d00d")
{
 echo "Hey $name, $msg";
}

blah(); // "Hey Dave, Sup d00d"
blah("Larry"); // "Hey Larry, Sup d00d"
blah("Skippy","you suck"); // "Hey Skippy, you suck"
?>


I figured it was something like that. Thanks for the information.

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
Out of curiosity, is there any way to skip the first argument in that? So like...

php:
<?
blah(,"you suck"); // "Hey Dave, you suck"
?>
?

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Golbez posted:

Out of curiosity, is there any way to skip the first argument in that? So like...

php:
<?
blah(,"you suck"); // "Hey Dave, you suck"
?>
?

I do not say this with 100% certainty (but like 99.8%), but no. You can't pass over arguments.

Adbot
ADBOT LOVES YOU

SuckerPunched
Dec 20, 2006

Lumpy posted:

I do not say this with 100% certainty (but like 99.8%), but no. You can't pass over arguments.

I say it with 100% certainty. You can not do that.

You could do like

blah(null, 'crap');

or

blah('', 'dongs');

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply