Replacing ampersands in URL
Results 1 to 10 of 10

Thread: Replacing ampersands in URL

  1. #1
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6

    Replacing ampersands in URL

    I inherited a two-year-old PHP application and a problem was just identified. Being a generalist who is still learning PHP, my present level of expertise isn't enough to help me.

    The application calls another script to authenticate against an MSSQL database, and then queries that database for educational course information. The user picks a state from first dropdown, which controls which list of schools is shown in the second dropdown. When both state and school are picked, the browser URL bar is populated with a query. So far, so good, except that any school that happens to have an ampersand in the name of the school will break the query because %26 is not being used in the place of the ampersand. They are taken to the results page fine, but the returned data halts right at the ampersand.

    For example, the user picks "IA", then "Iowa State Univ Science & Tech", and gets this broken query:

    Code:
    http://www.example.com/phpapplication.php?state=IA&city=&school=Iowa State Univ Science & Tech&button_trans=Submit+Query
    While on the broken results page it's possible to edit the URL and rerun the query correctly. Corrected query:
    Code:
    http://www.example.com/phpapplication.php?state=IA&city=&school=Iowa State Univ Science %26 Tech&button_trans=Submit+Query
    That doesn't help the user of course, but at least it reassures me that this will probably require a pretty simple fix.

    I've been experimenting, but so far I have not managed to locate a good fix or workaround. Urlencode and rawurlencode both seem to break this even further, and I've tried out str_replace as well but can't seem to get the syntax right. I would appreciate help from anyone who might have keen enough eyes to locate the problem or lend insight. I'll post the full code next. TIY!

  2. #2
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6
    Sorry for the delay in posting the code in question (minus my experiments). Here's the code, broken into two more posts:

    Code:
    <head>
    
    <script type="text/javascript" language="JavaScript">
    //<!--
    function submitForm(){
    	document.transfer_art.submit();
    }
    function toggleLayer(whichLayer)
    {
    
    	if (document.getElementById)
    	{
    		// this is the way the standards work
    		var style2 = document.getElementById(whichLayer).style;
    		style2.display = style2.display? "":"block";
    	}
    	else if (document.all)
    	{
    		// this is the way old msie versions work
    		var style2 = document.all[whichLayer].style;
    		style2.display = style2.display? "":"block";
    	}
    	else if (document.layers)
    	{
    		// this is the way nn4 works
    		var style2 = document.layers[whichLayer].style;
    		style2.display = style2.display? "none":"block";
    	}
    }
    
    function searchHelp(theURL) {
    	newwindow = window.open(theURL, '', 'height=400, width=300, toolbar=no, scrollbars=yes, menubar=no, statusbar=no');
    	if (window.focus) {newwindow.focus()}
    }
    
    //-->
    </script>
    
    </head>
    <body>
    
    <?php
    	
    
    	//Call up onnection info for DB.
    	require ('scripts/db.php');
    	
    	//Replace old codes.
    	function convertCodes($input) {
    		$search = array("L1", "2", "3", "4", "5", "RIP", "RIC", "RAC", "1");
    		$replace = array("AL", "SS", "SCI", "MTH,SCI", "MTH", "IP", "IC", "AC", "AL");
    		$return = str_replace($search, $replace, $input);
    		return $return;
    	}
    	
    	//Enable searching of old codes as well as new ones.
    	function convertCodesReverse($input) {
    		$search = array("1", "2", "3", "4", "5", "RIP", "RIC", "RAC", "1", "2", "3", "4", "5", "RIP", "RIC", "RAC");
    		$replace = array("AL", "SS", "SCI", "MTH,SCI", "MTH", "IP", "IC", "AC", "al", "ss", "sci", "mth,sci", "mth", "ip", "ic", "ac");
    		$return = str_replace($replace, $search, $input);
    		return $return;
    	}
    	
    	//The following SQL statements are used to populate the drop-down lists for
    	//State, City and School.
    		
    	$sql_state = "SELECT DISTINCT state FROM transfer_articulation ORDER BY state";
    	
    	$sql_city = "SELECT DISTINCT city FROM transfer_articulation WHERE state = '" . strip_tags(stripslashes($_GET['state'])) . "' ORDER BY city";
    	
    	$sql_school = "SELECT DISTINCT sbgi_desc FROM transfer_articulation WHERE state = '" . strip_tags(stripslashes($_GET['state'])) . "' ORDER BY sbgi_desc";
    	
    	//This list of IF statements makes the Advanced search possible. A search criteria
    	//will be included if and only if the user inputs into its corresponding
    	//input box, otherwise it is left empty and doesn't affect the SQL statement.
    	
    	if(!empty($_GET['subject'])){
    		$subject = "AND (SUBJ_UNIV LIKE '%" . strip_tags(stripslashes($_GET['subject'])) . "%' OR SUBJ_TRANS LIKE '%" . strip_tags($_GET['subject']) . "%') ";
    		
    	}
    	if(!empty($_GET['course'])){
    		$course = "AND (NUMB_UNIV LIKE '%" . strip_tags(stripslashes($_GET['course'])) . "%' OR NUMB_TRANS LIKE '%" . $_GET['course'] . "%') ";
    		
    	}
    	if(!empty($_GET['title'])){
    		$title = "AND (TITLE_UNIV LIKE '%" . strip_tags(stripslashes($_GET['title'])) . "%' OR TITLE_TRANS LIKE '%" . $_GET['title'] . "%') ";
    		
    	}
    	if(!empty($_GET['attributes'])){
    		$attributes = "AND ATTRIBUTES LIKE '%" . convertCodesReverse(strip_tags(stripslashes($_GET['attributes']))) . "%' ";
    		
    	}
    	if(!empty($_GET['term'])){
    		$term = "AND TERM_ACCEPT LIKE '%" . strip_tags(stripslashes($_GET['term'])) . "%' ";
    		
    	}
    	if(!empty($_GET['state'])){
    		$_SESSION['state_name'] = $_GET['state'];
    		$state = "STATE LIKE '" . strip_tags(stripslashes($_GET['state'])) . "' ";
    		
    	}
    	if(!empty($_GET['city'])){
    		$city = "AND CITY LIKE '" . strip_tags(stripslashes($_GET['city'])) . "' ";
    		
    	}
    	if(!empty($_GET['school'])){
    		$_SESSION['school_name'] = $_GET['school'];
    		$school = "AND SBGI_DESC LIKE '" . str_replace("'", "''", strip_tags(stripslashes($_GET['school']))) . "' ";
    		
    	}
    	
    	$_SESSION['subject'] = $subject;
    	$_SESSION['course'] = $course;
    	$_SESSION['title'] = $title;
    	$_SESSION['attributes'] = $attributes;
    	$_SESSION['term'] = $term;
    	$_SESSION['state'] = $state;
    	$_SESSION['city'] = $city;
    	$_SESSION['school'] = $school;
    	$_SESSION['school_name'] = $_GET['school'];
    	$_SESSION['historic'] = $_GET['historic'];
    	
    	//The mssql_query built-in function is used here to pass the SQL to the
    	//database and return the result set as an array.
    	$rs_state = mssql_query($sql_state, $conn);
    	$rs_city = mssql_query($sql_city, $conn);
    	$rs_school = mssql_query($sql_school, $conn);
    	
    	
    ?>
    (Lotsa code, so one more post to go)

  3. #3
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6
    ...And here is the second part of the code:

    Code:
    <h2>Inputs</h2>
    
    	  <div id="search" style="width:490px">
    	  <div class="selection_area" style="float:left; height:300px; width:230px; margin-right:10px">
    	  <h4>Basic Search: </h4>Choose a state or province first, then an institution.  For international institutions, select "XX".<hr />
    	  <form action="<?=$_SERVER['PHP_SELF']?>" method="get" name="transfer_art">
    	  	<div style="margin-bottom:5px"><select name="state" onChange="javascript:document.transfer_art.submit();">
    			<option value="">State</option>
    			<? while($firstline = mssql_fetch_array($rs_state)){ ?>	
    				<? $line['state'] = rtrim($firstline['state']); ?>
    					<option value="<?=$line['state']?>" <? if($_GET['state'] == $line['state']){echo "selected";} ?>><?=$line['state']?></option>
    			<? } ?>
    		</select>
    		</div>
    		
    		<!--<div style="margin-bottom:5px">2.&nbsp;<select name="city" onChange="javascript:document.transfer_art.submit();">
    			<option value="">City</option>
    			<? while($firstline = mssql_fetch_array($rs_city)){ ?>
    				<? $line['city'] = rtrim($firstline['city']); ?>
    					<option value="<?=$line['city']?>" <? if($_GET['city'] == $line['city']){echo "selected";} ?>><?=$line['city']?></option>
    			<? } ?>
    		</select>
    		</div>-->
    		
    		<div style="margin-bottom:10px"><select name="school" onChange="javascript:document.transfer_art.submit();" style="margin-right:5px">
    			<option value="">Institution</option>
    			<? while($firstline = mssql_fetch_array($rs_school)){ ?>
    				<? $line['sbgi_desc'] = rtrim($firstline['sbgi_desc']); ?>
    					<option value="<?=$line['sbgi_desc']?>" <? if($_GET['school'] == $line['sbgi_desc']){echo "selected";} ?>><?=$line['sbgi_desc']?></option>
    			<? } ?>
    		</select>
    		<? if(empty($_GET['state'])) { ?>
    		<? } ?>
    		</div>
    		
    		<? if(!empty($_GET['school'])) { ?>
    		<h4>Quick Buttons:</h4>
    		Return complete list of classes.
    		<hr />
    			<div style="margin-top:10px; margin-bottom:2px">
    				<input name="catalog" type="reset" value="Current Catalog" onClick="parent.location='<? echo "$_SERVER[PHP_SELF]?state=$_GET[state]&city=$_GET[city]&school=$_GET[school]&button_trans=Submit+Query"; ?>'" />
    			</div>
    			<div>
    				<input style="width:170px" name="button_historic" type="reset" value="View All Historic Records" onClick="parent.location='<? echo "$_SERVER[PHP_SELF]?state=$_GET[state]&school=$_GET[school]&button_trans=Submit+Query&historic=View+All+Historic+Records"; ?>'">
    			</div>
    		<? } ?>
    		</div>
    		<? if(!empty($_GET['school'])) { ?>
    		
    			
    			<div class="selection_area" style="float:right; width:200px; height:300px">
    				<h4>Advanced Search: </h4>Enter all or part of a word or number;  wildcards are not needed.<hr />
    				
    				<table width="100%" border="0" cellpadding="1" cellspacing="0">
    					<tr>
    						<td><a href="help.html#subject" onclick="javascript:searchHelp('help.html#subject'); return false;">Subject:</a></td>
    						<td><input name="subject" type="text" size="12" /></td>
    					</tr>
    					<tr>
    						<td><a href="help.html#course" onclick="javascript:searchHelp('help.html#course'); return false;">Course:</a></td>
    						<td><input name="course" type="text" size="12" /></td>
    					</tr>
    					<tr>
    						<td><a href="help.html#title" onclick="javascript:searchHelp('help.html#title'); return false;">Title:</a></td>
    						<td><input name="title" type="text" size="12" /></td>
    					</tr>
    					<tr>
    						<td><a href="help.html#groupCodes" onclick="javascript:searchHelp('help.html#groupCodes'); return false;">Group Codes:</a></td>
    						<td><input name="attributes" type="text" size="12" /></td>
    					</tr>
    				</table>
    				
    				<div style="margin-top:10px">
    					<input name="historic" type="checkbox" value="historic" <? if($_GET['historic']){echo "checked";} ?>/>
    						&nbsp;Include Historic Records in Search
    				</div>
    				<div style="margin-top:10px">
    					<input name="button_trans" type="submit" value="Submit Query">
    					&nbsp;
    					<input name="reset" type="reset" value="Reset" onClick="parent.location='<? echo "$_SERVER[PHP_SELF]"; ?>'"/>
    				</div>		
    			</div>
    			<div class="selection_area" style="position:absolute; top:207px; left:540px; width:150px; height:230px">
    			<h4>Links</h4>
    			<p>Looking for <a href="individualCourseLookup.php">Individual Course Lookups </a>?</p>
    			<p><a href="faq.htm">FAQs about Transferring Credits</a></p>
    			
    			</div>
    		</div>
    		
    		<div align="center" style="clear:both; margin-bottom:10px; padding-top:10px; border-top:thin solid black">
    			
    			<? if(isset($_GET['button_trans'])) {?>
    				<!--<input name="new" type="reset" value="Open Results in New Page" onClick="window.open('new.php')"/>&nbsp;--><input name="new" type="reset" value="Show/Hide Search Form" onClick="toggleLayer('search')"/>
    			<? } ?>
    		</div>
    		<? } ?>
    	  </form>
    	  
    	  <?
    	  //An IF statement is used here to display the results only when the query is submitted.
    	  //It also forces the program to wait until the user has entered all input boxes
    	  //before constructing the SQL statement and passing it to the DB.
    	  
    	  if(isset($_GET['button_trans'])){
    	  
    	  //This nested IF statement is used to see if the user wishes to include historical
    	  //rows in the results. If so, the SQL is modified to include all term_accept results
    	  
    	  	if(isset($_GET['historic'])){
    			$sql_advanced = "SELECT SBGI_DESC, CITY, STATE, SUBJ_UNIV, SUBJ_TRANS, TITLE_TRANS, TITLE_UNIV, NUMB_UNIV, NUMB_TRANS, TERM_ACCEPT, ATTRIBUTES FROM transfer_articulation WHERE $state $school $subject $course $title $attributes $term ORDER BY CASE WHEN ASCII(SUBJ_TRANS)>57 then 0 else 1 end, SUBJ_TRANS, NUMB_TRANS";
    			}else{
    			$sql_advanced = "SELECT SBGI_DESC, CITY, STATE, SUBJ_UNIV, SUBJ_TRANS, TITLE_TRANS, TITLE_UNIV, NUMB_UNIV, NUMB_TRANS, ATTRIBUTES, TERM_ACCEPT FROM transfer_articulation a
        WHERE (TERM_ACCEPT =
                (select max(TERM_ACCEPT) from transfer_articulation b
                  where b.SBGI_CODE=a.SBGI_CODE
                    and b.TITLE_TRANS=a.TITLE_TRANS
                    and b.NUMB_TRANS=a.NUMB_TRANS))
    			AND $state $school $subject $course $title $attributes $term ORDER BY CASE WHEN ASCII(SUBJ_TRANS)>57 then 0 else 1 end, SUBJ_TRANS, NUMB_TRANS";
    			}
    			
    			$rs = mssql_query($sql_advanced, $conn);
    			
    		?>
    	<div class="data">
      	<table width="100%" align="left" border="0" cellpadding="2" cellspacing="0">
    	<tr align="center" bgcolor="#E0E0E0"><td colspan="4" style="color:#006600; font-weight:bold"><? echo stripslashes($_GET['school']); ?></td><td colspan="4" style="color:#006600; font-weight:bold">Local Equivalent</td></tr>
    		<tr bgcolor="#336633">
    			<th align="center" width="9%">Subject</th>
    			<th align="center" width="9%">Course</th>
    			<th align="center" width="27%">Title</th>
    			<th align="center" width="1%">&nbsp;</th>
    			<th align="center" width="9%">Subject</th>
    			<th align="center" width="9%">Course</th>
    			<th align="center" width="27%">Title</th>
    			<th align="center" width="8%">Group Codes</th>
    		</tr>
    	  	<? 	$count = 1;
    			$color1 = "#FFFFFF";
    			$color2 = "#FFFFCC";
    				while($line = mssql_fetch_assoc($rs)){
    					$row_color = ($count % 2) ? $color1 : $color2;	  			
    					echo "<tr bgcolor=" . $row_color . "><td align=left>"
    					.$line['SUBJ_TRANS']."</td><td align=left>"
    					.$line['NUMB_TRANS']."</td><td align=left>"
    					.$line['TITLE_TRANS']."</td><td bgcolor=#FFFFFF align=left>&nbsp;</td><td align=left>"
    					.$line['SUBJ_UNIV']."</td><td align=left>"
    					.$line['NUMB_UNIV']."</td><td align=left>"
    					.$line['TITLE_UNIV']."</td><td align=left>"
    					.convertCodes($line['ATTRIBUTES'])."</td></tr>";
    					$count++;
    				}
    		} 
    			mssql_close($conn);
    		?>
    </body>

  4. #4
    High Energy Magic Dept. NogDog's Avatar
    Join Date
    Aug 2006
    Location
    Ankh-Morpork
    Posts
    13,886
    Assuming you are building the query string within your PHP code, you'll want to use the urlencode() function, e.g.:
    PHP Code:
    $urlSchool urlencode($school);
    $urlState urlencode($state);
    $url "http://www.example.com/page.php?state=$state&smp;school=$school"
    Please give us a simple answer, so that we don't have to think, because if we think, we might find answers that don't fit the way we want the world to be." ~ from Nation, by Terry Pratchett

    "But the main reason that any programmer learning any new language thinks the new language is SO much better than the old one is because hes a better programmer now!" ~ http://www.oreillynet.com/ruby/blog/...ck_to_p_1.html


    eBookworm.us

  5. #5
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6
    Quote Originally Posted by NogDog View Post
    Assuming you are building the query string within your PHP code, you'll want to use the urlencode() function, e.g.:
    PHP Code:
    $urlSchool urlencode($school);
    $urlState urlencode($state);
    $url "http://www.example.com/page.php?state=$state&smp;school=$school"
    Thanks for the quick reply, NogDog. (Code was a bit delayed in appearing after initial post).
    Last edited by christopherious; 08-25-2008 at 08:45 PM.

  6. #6
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6
    Given that the kind of URL that needs to be constructed would be something like:
    Code:
    http://www.example.com/page.php?state=IA&city=&school=Iowa&#37;20State%20Univ%20Science%20%26%20Tech&button_trans=Submit+Query
    ...then would it make sense to place the following after all the $_SESSION lines, near the end of the large chunk of PHP code in my second post above, and just before the Inputs area?

    Code:
    	//Ensure that school names containing an ampersand do not break the query in URL
    	$urlState = urlencode($state);
    	$urlCity = urlencode($city);
    	$urlSchool = urlencode($school);
    	$url = "http://www.example.com/page.php?state=$state&smp;city=$city&smp;school=$school&smp;button_trans=Submit+Query";
    Written that way, it seemed to have no effect, but then again I'm still pretty clueless when it comes to fixing someone else's PHP when it's as complex as this is (yeah, I know, it's probably less complex than I realize).

  7. #7
    High Energy Magic Dept. NogDog's Avatar
    Join Date
    Aug 2006
    Location
    Ankh-Morpork
    Posts
    13,886
    I'm not sure where in the code you are actually setting and using this URL, so I don't really know what the problem may be. I don't see anything wrong with the code in your last post, but then I don't know what you do with $url after you set it.
    Please give us a simple answer, so that we don't have to think, because if we think, we might find answers that don't fit the way we want the world to be." ~ from Nation, by Terry Pratchett

    "But the main reason that any programmer learning any new language thinks the new language is SO much better than the old one is because hes a better programmer now!" ~ http://www.oreillynet.com/ruby/blog/...ck_to_p_1.html


    eBookworm.us

  8. #8
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6
    Quote Originally Posted by NogDog View Post
    I'm not sure where in the code you are actually setting and using this URL, so I don't really know what the problem may be. I don't see anything wrong with the code in your last post, but then I don't know what you do with $url after you set it.
    It looks like the URL in question is constructed in two places, soon after the"Quick Buttons" line (see code in context in this post above). First instance, for example:

    PHP Code:
    <? if(!empty($_GET['school'])) { ?> <h4>Quick Buttons:</h4> Return complete list of classes. <hr /> <div style="margin-top:10px; margin-bottom:2px"> <input name="catalog" type="reset" value="Current Catalog" onClick="parent.location='<? echo "$_SERVER[PHP_SELF]?state=$_GET[state]&city=$_GET[city]&school=$_GET[school]&button_trans=Submit+Query"?>'" /> </div> <div> <input style="width:170px" name="button_historic" type="reset" value="View All Historic Records" onClick="parent.location='<? echo "$_SERVER[PHP_SELF]?state=$_GET[state]&school=$_GET[school]&button_trans=Submit+Query&historic=View+All+Historic+Records"?>'"> </div> <? ?>
    Before posting here, I had made the following change in an experiment (using both urlencode and rawurlencode). But it only broke the URL even more and produced a 404:

    PHP Code:
    <? if(!empty($_GET['school'])) { ?> <h4>Quick Buttons:</h4> Return complete list of classes. <hr /> <div style="margin-top:10px; margin-bottom:2px"> <input name="catalog" type="reset" value="Current Catalog" onClick="parent.location='<? echo urlencode("$_SERVER[PHP_SELF]?state=$_GET[state]&city=$_GET[city]&school=$_GET[school]&button_trans=Submit+Query"); ?>'" /> </div> <div> <input style="width:170px" name="button_historic" type="reset" value="View All Historic Records" onClick="parent.location='<? echo urlencode("$_SERVER[PHP_SELF]?state=$_GET[state]&school=$_GET[school]&button_trans=Submit+Query&historic=View+All+Historic+Records"); ?>'"> </div> <? ?>
    This is what the URL ended up looking like (with the above urlencode change):

    Code:
    http://www.example.com/foldername/%2Ffoldername%2Fpage.php%3Fstate%3DTX%26city%3D%26school%3DTexas+A+%26+M+Univ-Kingsville%26button_trans%3DSubmit%2BQuery
    In addition to the duplicate instance of the subfolder name (not mentioned in my posts above), other parts of the URL such as slashes and pluses are replaced.
    Last edited by christopherious; 08-25-2008 at 10:04 PM.

  9. #9
    High Energy Magic Dept. NogDog's Avatar
    Join Date
    Aug 2006
    Location
    Ankh-Morpork
    Posts
    13,886
    You don't want to encode the entire URL, just the query string values, so you would need to break it up into something like:
    PHP Code:
    <?php if(!empty($_GET['school']))
    ?> <h4>Quick Buttons:</h4> Return complete list of classes. <hr /> 
    <div style="margin-top:10px; margin-bottom:2px">
    <input name="catalog" type="reset" value="Current Catalog" onClick="parent.location='<?php echo
    $_SERVER['PHP_SELF'] . "?state=" urlencode($_GET[state]) . "&city=" .
    urlencode($_GET[city]) . "&school=" urlencode($_GET[school]) .
    "&button_trans=Submit+Query"?>'" /> </div> <div>
    <input style="width:170px" name="button_historic" type="reset" value="View All Historic Records" onClick="parent.location='<?php echo
    $_SERVER[PHP_SELF] . "?state=" urlencode($_GET[state]) . "&school=" urlencode($_GET[school]) .
    "&button_trans=Submit+Query&historic=View+All+Historic+Records"?>'"> </div> <?php ?>
    Please give us a simple answer, so that we don't have to think, because if we think, we might find answers that don't fit the way we want the world to be." ~ from Nation, by Terry Pratchett

    "But the main reason that any programmer learning any new language thinks the new language is SO much better than the old one is because hes a better programmer now!" ~ http://www.oreillynet.com/ruby/blog/...ck_to_p_1.html


    eBookworm.us

  10. #10
    PHP Neophyte
    Join Date
    Aug 2008
    Posts
    6
    That was very helpful and instructive, NogDog. Thanks again.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •