1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

URL Rewrite Affecting Queries

Discussion in 'Programming' started by scottlpool2003, May 2, 2014.

  1. #1
    I've tried to narrow it down as best I can and the only conclusion I'm coming to is an URL rewrite as the exact same code works fine on a page that doesn't use it.

    I'm using the Windows URL Rewrite module and have set up a corresponding outbound rule.

    Now I'm trying to do an insert, but it inserts 4 times. I have the same result if I do a +1 update.

    Am I correct in thinking it's the Rewrite?
     
    scottlpool2003, May 2, 2014 IP
  2. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #2
    It definitely is the Rewrite, I just switched on the rewrite for the test page that was functioning correctly and I have the same result.

    This isn't something I have come across before, does anybody have any idea for a workaround?
     
    scottlpool2003, May 2, 2014 IP
  3. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #3
    Welcome to one of the many reasons I refuse to use Microsoft iiS... My idea for a workaround being "Install Apache".

    What language are you processing it with? What are you typing in AS the redirect? Is an equivalent to PHP's $_SERVER 'REQUEST_URI' or 'QUERY_STRING' available so you could maybe process the data being passed yourself instead of relying on the Engine?

    There's a reason in the software I write (for apache) I flat redirect every request not on my whitelist to a single index.php
    # redirect all 'unknown' requests to index.php
    RewriteEngine On
    RewriteRule !\.(gif|jpg|png|css|js|html|htm|txt|ico|zip|gz|rar|pdf|xml|wav|mp3|mp4|mpg|flv|swf|mkv|ogg|avi|webm|woff|svg|eot|ttf)$ index.php
    Code (markup):
    Then parse the request myself with this object:
    final class request {
    	private static $data = [];
    	public static function value($index = 0, $clean = false) {
    		if ($index === true) { $index = 0; $clean = true; }
    		if (count(self::$data) == 0) {
    			$path = trim(str_replace(['\\','%5C'],'/',
    				parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH)
    			),'/');
    			if (strpos($path,'..')) bomb('hackingDetected', 'uptreeFail');
    			$path = substr($path, strlen(HTTP_ROOT) - 1);
    			self::$data = empty($path) ? ['introduction'] : explode('/',$path);
    			foreach (self::$data as &$p) $p = urldecode($p);
    		}
    		return isset(self::$data[$index]) ? (
    			$clean ? cleanName(self::$data[$index]) : self::$data[$index]
    		) : false;
    	}
    }
    Code (markup):
    Admittedly that's for processing 'friendly' URI's like http://www.ewiusb.com/breakdown -- where request::value() or request::value(0) would return 'breakdown'. As it doesn't rely on playing goofy tricks with trying to change directories into getData it's just more reliable, and easier to implement across different servers. (ngnix, apache, iis, etc).

    Really though it's hard to answer without you including either your web.config (given what you've said I'm assuming that's what you're working with) or explaining what you are redirecting and to where.
     
    deathshadow, May 2, 2014 IP
  4. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #4
    I know what you mean, I switched from Linux to Windows because I thought Linux was overly complicated. Oh, how wrong I was!

    Here is the actual rule from the Rewrite Generator in IIS:

    The original url was: /viewstory.php?id=123&title=This-Is-A-Title

    Here is how I was linking to it:

    
    //Title for friendly urls
    $title = preg_replace('/[^A-Za-z0-9-]+/', '-', $row['subject']);
    
    echo "<h2><a href='/" . $row['id'] . "/$title.html' title='" . ucwords(htmlallentities($row['subject'])) . "'>" . htmlallentities($row['subject']) . "</a></h2>";
    
    PHP:
    Web.config outbound rule:
    
                    <rule name="OutboundRewriteUserFriendlyURL1" preCondition="ResponseIsHtml1">
                        <match filterByTags="A, Form, Img" pattern="^(.*/)viewstory\.php\?id=([^=&amp;]+)&amp;(?:amp;)?title=([^=&amp;]+)$" />
                        <action type="Rewrite" value="{R:1}{R:2}/{R:3}/" />
                    </rule>
    
    PHP:
    Rewrite:
    
                    <rule name="RewriteUserFriendlyURL1" stopProcessing="true">
                        <match url="^([^/]+)/([^/]+)/?$" />
                        <conditions>
                            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        </conditions>
                        <action type="Rewrite" url="viewstory.php?id={R:1}&amp;title={R:2}" />
                    </rule>
    
    PHP:
    Redirect: (If anything, I think this is the culpret)
    
                    <rule name="RedirectUserFriendlyURL1" stopProcessing="true">
                        <match url="^viewstory\.php$" />
                        <conditions>
                            <add input="{REQUEST_METHOD}" pattern="^POST$" negate="true" />
                            <add input="{QUERY_STRING}" pattern="^id=([^=&amp;]+)&amp;title=([^=&amp;]+)$" />
                        </conditions>
                        <action type="Redirect" url="{C:1}/{C:2}" appendQueryString="false" />
                    </rule>
    
    PHP:
     
    scottlpool2003, May 7, 2014 IP
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #5
    "simplification" can not only have diminishing returns, it can have the opposite of the intended effect. Sometimes it becomes possible for something to become so over-simplified it makes doing a complex task harder, if not impossible -- there's a reason in web development the term "false simplicity" is being bandied about more and more. What often LOOKS simpler or people are convinced is simpler just because some artsy fartsy type or magazine called it such... isn't.

    As to your problem, I think much of it might lie here:
    echo "<h2><a href='/" . $row['id'] . "/$title.html' title='" . ucwords(htmlallentities($row['subject'])) . "'>" . htmlallentities($row['subject']) . "</a></h2>";
    Code (markup):
    Ignoring the pointless bandwidth wasting redundant title attribute (there is only ONE legitimate reason to make a TITLE identical to the content of a tag, and I don't see no accesskeys on that), the back-assward use of quotes and slow string additon :p you are making $title.html -- but I don't see your rewrite rules set up to handle that.

    Assuming any of those actually worked (which to be honest the whole thing seems WAY to complex for it's own good) I would have thought it would return ;title=whatever.html -- is your redirect handler set up to handle that .html "extension for nothing"?

    I mean, one of the whole reasons to play redirect games like this is to NOT use a .html extension -- well, unless you're doing 300-style redirects which you quite obviously are not.

    Still, there's a reason my code for that markup would be:
    echo '
    	<h2>
    		<a href="', $row['id'], '/', $title, '" >
    			', htmlallentities($row['subject']), '
    		</a>
    	</h2>';
    Code (markup):
    Not sure why you'd be using the row ID as your directory either, I'd think that part would be near impossible to parse using IIs services. I could do it in Apache, but that would be a flat redirect of all requests EXCEPT a whitelist as per above. Not even sure how I'd go about that in IIs.
     
    deathshadow, May 7, 2014 IP
  6. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #6
    I see your point, although I'm not sure how adding .html would cause this issue. I'm not great when it comes to these things, but in the web.config, it's only set up to handle the first and second condition, so shouldn't it ignore the third condition which would be the .html?

    I'll take the .html out and see what happens.
     
    scottlpool2003, May 7, 2014 IP
  7. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #7
    It turned out not to be the case. I disabled the redirect rule to check if that was the issue but it wasn't. I did have AddThis on there which appends the URL with a tracker code, so I disabled that and I get the same result. The result is unpredictable though, sometimes it inserts 4 times, others 5 and my latest test was 8 almost like it's consistently inserting until the page finishes loading.

    Here is the code for the page (I know you're not gonna like it lol!), is there anything I am missing here?

    
    <?php
    require("config.php");
    require("functions.php");
    require("header.php");
          //Get stories
          $statement = $dbconn->prepare('
                  SELECT stories.id, stories.dateposted, stories.subject, stories.body, images.name, stories.cat_id
                  FROM stories
                  LEFT OUTER JOIN images ON stories.id = images.story_id
                  WHERE stories.id = :id
          ');
          $statement->execute([
                              ":id" => $_GET['id']
                              ]);
          while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
            $cat_id = $row['cat_id'];
            //Check if admin is logged in, if so, show the admin box
            if(check_login()) {
                  echo "<div id='options_box'>Actions:<ul>";
    
                  echo "<li class='add'><a href='/addimages.php?id=" . $_GET['id'] . "'> Add Images </a></li>";
                  echo "<li class='delete'><a href='/deletestory.php?id=" . $_GET['id'] . "'> Delete Story </a></li>";
                  echo "<li class='edit'><a href='/editstory.php?id=" . $_GET['id'] . "'> Edit Story </a></li>";
                  echo "<ul></div>";
            }//End check login
    
            echo "<div class='story_holder'>";
            //Title for friendly urls
            $title = preg_replace('/[^A-Za-z0-9-]+/', '-', ucwords($row['subject']));
    
            //echo "<h2><a href='/$row[id]/$title.html' title='" . $row['subject'] . "'>" . $row['subject'] . "</a></h2>";
            echo "<h2><a href='/$row[id]/$title.html' title='" . ucwords(htmlallentities($row['subject'])) . "'>" . htmlallentities($row['subject']) . "</a></h2>";
            echo "<p class='date'>";
            echo date("D jS F Y g.iA", strtotime($row['dateposted'])) . "<br/>";
            echo "</p>";
    
            // query to show current images
            $statement = $dbconn->prepare("
              SELECT * FROM images WHERE story_id = :story_id
            ");
            $statement->execute([
              "story_id" => $_GET['id']
            ]);
            $imagerow = $statement->fetchAll(PDO::FETCH_ASSOC);
            if (empty($imagerow)){
              //Was going to show generic image
            }else {
              //Check if admin is logged in
              foreach ($imagerow AS $imagerow){
                echo "<div class='img_wrapper'>";
                echo "<img src='/images/" . $imagerow['name'] . "' style=\"max-width:490px;margin-bottom:1em;border:1px solid silver;padding:3px;\">";
                  if(check_login()) {
                    echo "<div class='img_action'><a href='/deleteimage.php?image_id=" . $imagerow['id'] . "&story_id=" . $_GET['id'] . "'><img src='/images/basic/cancel.gif' alt='Delete?'></a></div>";
                  }
                echo "</div>";
                }
              }
              $title = htmlallentities(ucfirst($title));
    ?>
    
    <div id="shareContainer">
      <h2>Share this story</h2>
      <label for="direct">Direct Link (Twitter/Facebook)</label> <input type="text" id="direct" value="http://www.horwichadvertiser.co.uk/<?php echo "" . $row['id'] . "";?>/<?php echo $title;?>.html" onclick="select()" /><br />
      <label for="blog">HTML (Websites & Blogs)</label> <input type="text" id="blog" value='<a href="http://www.horwichadvertiser.co.uk/<?php echo "" . $row['id'] . "";?>/<?php echo $title;?>.html" title="<?php echo "" . $row['subject'] . "";?>" target="_blank"><?php echo "" . $row['subject'] . "";?></a>' onclick="select()" /><br />
      <label for="forum">BB (Forums)</label> <input type="text" id="forum" value='[url=http://www.horwichadvertiser.co.uk/<?php echo "" . $row['id'] . "";?>/<?php echo $title;?>.html]<?php echo "" . $row['subject'] . "";?>[/url]' onclick="select()" />
    </div>
    <?php
      $text = nl2br(htmlallentities($row['body']));
      //print iconv('UTF-8', 'ASCII//TRANSLIT', $text); //"Mystring "
      echo "$text</div>";
    ?>
    <div class="fb-comments" data-href="http://www.horwichadvertiser.co.uk/<?php echo $_GET['id'];?>/<?php echo $_GET['title'];?>" data-width="487" data-numposts="100" data-colorscheme="light"></div>
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=424833514225219";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));</script>
    <?php
          }//End while loop
          //Add view
          //Add story views            INSERT INTO story_views (storyid, cat_id) VALUES (:storyid, :catid)
          $statement = $dbconn->prepare("
            INSERT INTO story_views (storyid, cat_id) VALUES (:id, :cat_id)
          ");
          $statement->execute([
            ":id" =>  $_GET['id'],
            ":cat_id" =>  $cat_id
        ]);
        echo "<pre>";
        print_r($statement->errorInfo());
        echo "</pre>";
    
    
    require("/footer.php");
    ?>
    
    PHP:
     
    scottlpool2003, May 7, 2014 IP
  8. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #8
    Sorry I forgot to add, with regards to Apache, I'm running Plesk which doesn't support Apache as of version 10.
     
    scottlpool2003, May 7, 2014 IP