EladElrom.com

Deep Dive Into Technology

Custom object casting in PHP

There are times when you want to do a casting of an object to a custom object in PHP.  The reason you would want to do that is that you would want to enforce properties.  It’s enough to have a small typo when assigning values to create problems in your application.  I think that the best approach is to create a new instance of a class and than assign the object.  Here’s what I would do:

public function ($someVO) {
$someCastVO = new SomeVO();
$someCastVO = $someVO;
$someCastVO->SomePropertyInVO = “123″;
}

Doing this will give you code hinting in most IDEs and help ensure you are using the correct properties.

This is simple, however I’m seeing so many blog posts with no simple straightforward answer.

Static public access modifier in PHP

I am impressed with how PHP have gone such a long way since I used it every day years ago. Back in 2001-2002 PHP used to be that programming language someone would use when programming out of his grandmother’s basement — I hope I am not insulting anyone :) , it was known for the lack of the OOP structure, classes etc.. today it seems it’s not anymore a second citizen language and you can use OOP practices that are well known in other programming languages from using Intellij IDE, debugger with break point, MVC pattern and building a beautiful “enterprise” solution just like other server side languge. One example is access modifiers. It’s a common practice to create a utility helper class that can be used across your application for common tasks. You don’t want to init a class just use a method in it without the need to initialize the class.

As of PHP 5.3.0 (see http://php.net/manual/en/language.oop5.static.php) you to do that. You can skip creating the constructor using “static public function” keywords for your methods and than you can call methods from within the class as follow:

var getSomeCalculation = Helper::doSomeCalculationMethod();

Notice that static properties cannot be accessed through the object using the arrow operator -> so you need to do the following “::”

Debug php using Aptana and Xdebug on Mac

I have been using CodeIgniter and they have nice profiling tool;
$this->output->enable_profiler(TRUE);

PHP has gone long way and you can now use debugging FirePHP however that’s not true debugging tool.  Recently, Aptana are working on adding debugging capability into the Eclipse IDE. With the release of Aptana 3.3.3 you can use the Firefox plugin and set line break point to stop and debug your application — professionally.

Here’s what you need to do, update to the nightly build of Aptana 3.3.3 (at the time of writing it’s not out yet).  Here’s how, In Eclipse use: ‘Help’ > ‘Install New Software’ and add site:
Aptana studio
http://ec2-50-16-19-245.compute-1.amazonaws.com/aptana/studio3/standalone/update/rc/

Update to 3.3.3

Next install PHP Xdebug on Mac, follow this blog post for step by step instructions;
http://kubyshkin.ru/programming/installing-php-xdebug-extension-on-mac-os-x-10-7-lion/

Lastly, remember to update the php.ini file. I am using xampp so it’s here:
cd /Applications/XAMPP/xamppfiles/etc

sudo pico php.ini

[xdebug]
zend_extension=/usr/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so
xdebug.file_link_format=”txmt://open?url=file://%f&line=%1″
xdebug.remote_enable = On
xdebug.remote_autostart = 1

And that’s it!

Long polling system using ajax and php – $.ajax is preferred

Using $.ajax or the $.post tag you can easily create a long polling script to continuously monitor changes using HTTP service. The problem is that most examples are using $.post to do the job and they fail to point out the cross domain concern.

I wouldn’t bother using $.post at all, since it will break in case you try to implement on a separate domain than the deployed long polling script host domain.

Once you try to use the long polling script on a cross domain, the server will not send over the information and it will fail silently using the $.post call (since the $.post is just a wrapper for the $ajax and is limited in functionality), $.ajax call allows you to use the jsonp data type, which will take care of cross domain issues and allow the data through for other domains.

Once you deploy a long polling API on your host this type of script will work on same domain or separate domain:

// JavaScript Document

var callBack;
pollingURL  = "http://[domain]/longpolling.php";

document.write('<');
document.write('script ');
document.write('src="');
document.write("http://code.jquery.com/jquery-latest.js");
document.write('" type="text/javascript"></');
document.write('script');
document.write('>');

function jsonpCallback(data)
{
	callBack(data);
}

function connect()
{
	var object = {
		data: "some data"
	};

    $.ajax({
		url:pollingURL,
		data: object,
		dataType: 'jsonp',
		jsonp: 'callback',
        jsonpCallback: 'jsonpCallback',
		success:function(msg) {
			// alert("Success");
		},
		complete:function() {
			// alert("complete");
		},
		error: function() {
			// alert("error");
		},
	});
}

function start(callBack)
{
	this.callBack = callBack;
	connect();

	setInterval( "connect()", 3000 );
}

Remember to set you php code to format the response as jsonp:

header("content-type: text/javascript");

if (!isset($_GET['data']))
{
	echo "error: client_id is not set";
	die();
}


while(1)
{
	$data = [retrieved from database or somewhere else]

	// if we have new data, return it to the client
	if(!empty($data))
	{
		$obj->data = $data;
		echo $_GET['callback']. '(' . json_encode($obj) . ');';
		break;
	}

	sleep(5000);
}

Additionally, using $.post makes it hard to diagnose the problem. I used Firebug and it pointed to a line of code in Ajax library, while a web proxy showed a correct request respond. The $.ajax tag allows you to set an error callback which can at least show you when there are problems.

Dealing with timezone on MySQL database

Sometimes you need to create a fast mysql command to calculate date/times for a specific logic.

MySQL manual has a great article that helps you create your SQL command:
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_current-timestamp

For instance, instead of retrieving all results from a database iterate through the results using a server side scripting and than update the database, we can do the same operation in one command using MySQL:

For instance, look at this command:
UPDATE `database`.`table` SET `active` = '0' WHERE `active` = 1 AND `checkin_time` < DATE_SUB(NOW(),INTERVAL 10 SECOND)

That will check the last time a user checked in and set the user is inactive. It's important to make sure that once you update the database with the latest time, you need to either use internet time or set the apache server to the same time zone as the MySQL database.

You can find the timezone in phpinfo. For instance using PHP on localhost using XAMPP you can find the time zone here:
http://eladelrom.com/blog/xampp/ (or print it using PHP on a server)

If timezone is not set correctly, you can set it on php.ini
Look for: Change:

date.timezone = 'EST'

Than you can ensure that the MySQL is running on the same timezone running this command:

SELECT NOW();

Update HTML document layout (width & height) using Javascript after browser resize

To adjust the page’s layout you need to listen to change in browser size event. You can do that in jQuery easily and the method in jQuery already taking care of a lot of the logic needed, however if you want to just use Javascript you can. JS has everything you need to get it working.

var oldWidth;
var oldHeight

function resizeHandler()
{
	var newWidth;
	var newHeight;

	if( typeof( window.innerWidth ) == 'number' )  //Non-IE
	{
		newWidth = window.innerWidth;
		newHeight = window.innerHeight;
	}
	else if( document.documentElement &&
	( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) //IE 6+
	{
		newWidth = document.documentElement.clientWidth;
		newHeight = document.documentElement.clientHeight;
	}
	else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) )  // IE4
	{
		newWidth = document.body.clientWidth;
		newHeight = document.body.clientHeight;
	}

	if ( newWidth != oldWidth )
	{
               // implement -- do something

		oldWidth = newWidth;
		oldHeight = oldHeight;
	}
}

Notice that I am checking if the actual size was changed since often the browser will call this method several times as the user resize it’s browser. Also notice that this code is set to take into account different types of browsers.

Than you can set the body to call this method onload

<body onload='parent.resizeHandler()'>

I also noticed that sometimes the event is called before the page completed the layout process so I added a timer:

function callChatAfterOnLoadCompleted()
{
	var t2=setTimeout("parent.resizeHandler()", 500);
}

And on window resize:

window.onresize = function(event)
{
	parent.resizeHandler()
}

Flash Player Settings Camera and Microphone access window "Allow" button unclickable

I came across an issue the other day. The Adobe Flash Player Settings Camera and Microphone access window “Allow” button was unclickable.

When trying to initiate the camera and microphone access for a domain for some odd reason the button to allow was unclickable and you couldn’t press it. The keyboard worked and I was able to tab but when I hit the “enter” key it still wont work and couldn’t grant access to my microphone and camera. Another issue I noticed is that once I moved my window to a second screen you couldn’t even see the warning window.

I Google it for a good 15 mins and couldn’t find an answer, some people were talking about changes in the player but no solutions about the issues I am seeing.

It appears that there couple of things to know about that warning window which can cause issues:

  • Application size – your application can’t be smaller than the size of the warning window otherwise that window wont be clickable and you wont be able to accept the permission to access your mic and camera
  • SWF Object – I notice that the warning is centering so in case you swf object is not set to the correct size of the application and it floats it will create you issues and you may not see the window in certain cases
  • Upgrading Flash Player – the security folders can get corrupted so you may need to clean them at the Global Privacy Settings panel

Keep in mind that you can also go to the Website Privacy Settings panel and always allow a site to access your camera and mic.

Organizing your HTML page's structure using iframe

HTML doesn’t have that OOP structure we all used to when developing high level languages and often I wonder how can I adjust my pages to be organized well. You can create a structure using templates or have a server side script to load pieces and create the document, however sometime you want a more straight forward simple approach. One approach is creating a document and using iframe to hold pieces of the document. for instance: left navigation, middle page, footer etc and than have a document that stitch these together.

For instance, look at the example below:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="style.css" rel="stylesheet" type="text/css">
<title>Untitled Document</title>
</head>

<body>
    <div class="boxborder">
    	<div class="LeftPanel">
	        <iframe id="leftframe" name="leftframe" vspace=0 hspace=0 marginwidth=0 marginheight=0 align="left" scrolling="no"
            	frameborder="0" height="500px" src="leftpage.html"></iframe>
        </div>
        <div class="RightPanel">
	        <iframe id="rightframe" name="rightframe" align="left" vspace=0 hspace=0 marginwidth=0 marginheight=0 scrolling="no"
            	frameborder="0" width="500px" height="500px" src="rightpage.html"></iframe>
        </div>
    <div>
</body>
</html>

Using the following CSS style sheet:

@charset "utf-8";
/* CSS Document */

html, body {
		border: 0px;
		margin: 0px;
}
.boxborder{border:1px black solid;float:left;margin:100px 0 0 100px;}
.LeftPanel{
	float:left;
	width:200px;
}
.RightPanel{
	float:left;
	width:500px;
}
.RightBody {
	background-color:#CCCCCC;
	height:500px;
	text-align:center;
	font-size:18px;
	font-weight:bold;
	font-family:Arial, Helvetica, sans-serif;
	padding:10px 0 0 0;
}
.LeftBody {
	background-color:#666666;
	height:500px;
	color:#FFFFFF;
	font-size:18px;
	font-weight:bold;
	font-family:Arial, Helvetica, sans-serif;
	padding:10px 0 0 55px;
}

You can than create the left page:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="style.css" rel="stylesheet" type="text/css">
<title>Untitled Document</title>
</head>

<body>
	<div class="LeftBody">
    	Left Page
    </div>
</body>
</html>

Creating the best possible quality live stream using FMS in Flash or Flex applications

When it comes to creating an agent/client live stream using FMS there are few parameters to keep in mind:

1. Live feed width
2. Live feed height
3. Camera resolution width
4. Camera resolution height
5. FPS (Frame Per Second)
6. Quality
7. Bandwidth
8. Microphone options

This article is just the tip of the iceberg, but it should give you a good idea and much information needed to build a high quality live stream application for Flash or Flex.

Let’s start with the video stream.

Adobe’s docs talks about this to some extent here:
http://livedocs.adobe.com/flashmediaserver/3.0/hpdocs/help.html?content=00000139.html

I often hear client asking for live stream feed with “porn” quality. The quality is really setting these variables and granular adjusting these variables until you find what’s work best and not just choosing the best CDN out there.

You cannot record a live stream video in high resolution, top quality, high FPS and high quality audio stream on an ok bandwidth and expact it stream great.

I recommend setting these variables at the beginning of the class so you can keep adjusting them until you found what suits you.

private static const LIVE_FEED_WIDTH:int = 220;
private static const LIVE_FEED_HEIGHT:int = 147;
private static const CAM_FEED_WIDTH:int = 80;
private static const CAM_FEED_HEIGHT:int = 53;
private static const FPS:Number = 15; // recommended between 15-25
private static const QUALITY:int = 95; // values from 0-100
private static const BANDWIDTH:int = 0; // when set as 0 will adjust to highest bw based on user's settings

Than when you setup your video and stream you can use these variables:

// setup cameras
cameraVideo = new Video(CAM_FEED_WIDTH,CAM_FEED_HEIGHT);
liveFeedVideo = new Video(LIVE_FEED_WIDTH,LIVE_FEED_HEIGHT);

// Cameras & quality
camera.setMode(LIVE_FEED_WIDTH*0.90,LIVE_FEED_WIDTH*0.90,FPS);
camera.setQuality(BANDWIDTH,QUALITY);

I also recommend setting the smoothing so the stream will display better:

cameraVideo.smoothing = liveFeedVideo.smoothing = true;

The FMS server can be configured as well and you can create your custom client and adjust properties manually when the Bandwidth changes:

netConnection = new NetConnection();
netConnection.client = new Client();

package
{
	public class Client
	{
		public function onBWCheck(... rest):Number
		{
			return 0;
		}

		public function onBWDone(... rest):void
		{
			var p_bw:Number;
			if (rest.length > 0) p_bw = rest[0];
			// your application should do something here
			// when the bandwidth check is complete
			//trace("bandwidth = " + p_bw + " Kbps.");
		}

		public function onFCSubscribe(info:Object):void
		{
			// do something
		}
	}
}

In addition, using out of the box solution such as the build in mx:VideoDisplay, s:VideoDisplay or OSMF can help you set the best values without understanding too much or adjusting too many variables, however without adjusting the default behavior you may be disappointed with the quality.

For instance even the old school mx:VideoDisplay has a build in features such as the autoBandWidthDetection=”true”. When these sets as true the VideoDisplay control should use the built-in automatic bandwidth detection feature. When false, you do not require a main.asc file on Flash Media Server (FMS) 2 to connect to FMS. When true, you need to implement a main.asc and store it in the directory structure of FMS.

As noted in the ASDOC the main.asc file must define the following functions:

      application.onConnect = function(p_client, p_autoSenseBW)
      {
        //Add security code here.
        this.acceptConnection(p_client);
        if (p_autoSenseBW)
          this.calculateClientBw(p_client);
        else
          p_client.call("onBWDone");
      }
      application.calculateClientBw = function(p_client)
      {
        // Add code to set the clients BandWidth.
        // Use p_client.getStats() which returns bytes_in
        // and bytes_Out and check your bandWidth using
        // p_client.call("onBWCheck", result, p_client.payload).
        p_client.call("onBWDone");
      }

      Client.prototype.getStreamLength = function(p_streamName)
      {
        return Stream.length(p_streamName);
      }

Now what about CDN? Do they have anything to do with live stream quality? The answer is yes. Let’s assume you are connecting 1:1 or 1 to many. Connections to feeds from users from same continents number of connections can all effect your stream quality and should be taken into account when selecting your CDN. Akamai and Limelight are the leaders in term of reputation and service, however when you start streaming and don’t publish too many feeds, setting Amazon EC2 may be all that you need to get top notch live stream and once you scale up and you can start taking advantage of CDNs that support more features.

Here’s an example code that can be used as the foundation to building a live stream:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   minWidth="955" minHeight="600"
			   creationComplete="init()">
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.core.FlexGlobals;
			import mx.core.UIComponent;

			private static const LIVE_FEED_WIDTH:int = 220;
			private static const LIVE_FEED_HEIGHT:int = 147;
			private static const CAM_FEED_WIDTH:int = 80;
			private static const CAM_FEED_HEIGHT:int = 53;
			private static const FPS:Number = 15; // recommended between 15-25
			private static const QUALITY:int = 95; // values from 0-100
			private static const BANDWIDTH:int = 0; // when set as 0 will adjust to highest bw based on user's settings

			// settings
			private var userType:int;
			private var sessionId:String = "1";
			private var debugMode:Boolean = true;
			private var rtmpEndPoint:String = "rtmp://[server URL]/live";

			// video variables
			private var camera:Camera;
			private var mic:Microphone;
			private var netConnection:NetConnection;
			private var cameraNetStream:NetStream;
			private var liveFeedNetStream:NetStream;
			private var cameraVideo:Video;
			private var liveFeedVideo:Video;

			// feeds ids
			private var camFeedId:String = "";
			private var liveFeedId:String = "";

			private function init():void
			{
				setURLParams();

				// setup cameras
				cameraVideo = new Video(CAM_FEED_WIDTH,CAM_FEED_HEIGHT);
				liveFeedVideo = new Video(LIVE_FEED_WIDTH,LIVE_FEED_HEIGHT);

				cameraVideo.smoothing = liveFeedVideo.smoothing = true;

				connectToFMS();
			}

			private function setURLParams():void
			{
				var params:Object = FlexGlobals.topLevelApplication.parameters;
				userType = int(params.userType);

				if ( params.userType == "undefined" || params.sessionId == "undefined" || params.rtmpEndPoint == "underfined")
				{
					// debug mode
					userTypeDropDownList.visible = true;
				}
				else
				{
					// live mode
					rtmpEndPoint = params.rtmpEndPoint;
					sessionId = params.sessionId;
					debugMode = false;
				}
			}

			private function setSettingBasedOnUserType():void
			{
				if (userType == UserType.AGENT)
				{
					camFeedId = "agent" + sessionId;
					liveFeedId = "client"  + sessionId;

				}
				else // CLIENT
				{
					camFeedId = "client" + sessionId;
					liveFeedId = "agent" + sessionId;
				}

				startCamFeedCamera();
				startLiveFeedCamera();
			}

			private function connectToFMS():void
			{
				netConnection = new NetConnection();
				netConnection.client = {};

				netConnection.addEventListener(NetStatusEvent.NET_STATUS, onNetConnectStatus);
				netConnection.connect(rtmpEndPoint);
			}

			private function onNetConnectStatus(e:NetStatusEvent):void
			{
				trace("Connected to FMS Successfully!");

				if (!debugMode)
					setSettingBasedOnUserType();
			}

			private function setCamera():void
			{
				camera = Camera.getCamera();
				mic = Microphone.getMicrophone();

				// mic settings
				mic.setLoopBack(false);
				mic.setUseEchoSuppression(true);

				// Cameras & quality
				camera.setMode(LIVE_FEED_WIDTH*0.90,LIVE_FEED_WIDTH*0.90,FPS);
				camera.setQuality(BANDWIDTH,QUALITY);

				cameraNetStream = new NetStream(netConnection);
			}

			private function addMask(circleMask:UIComponent, feed:Image, radius:int):void
			{
				if (circleMask == null)
				{
					circleMask = createCircle(radius);
					this.addElement( circleMask );
				}

				feed.mask = circleMask;
			}

			private function createCircle(r:Number):UIComponent
			{
				var circle:Sprite = new Sprite();
				circle.graphics.lineStyle(1, 0x000000);
				circle.graphics.beginFill(0x000000);
				circle.graphics.drawCircle(r, r, r);
				circle.graphics.endFill();

				var uicom:UIComponent = new UIComponent();

				uicom.addChild(circle);
				uicom.x = uicom.y = 0;
				uicom.width = uicom.height = 100;

				return uicom;
			}

			private function startCamFeedCamera():void
			{
				setCamera();

				cameraVideo.attachCamera(camera);

				cameraNetStream.attachCamera(camera);
				cameraNetStream.attachAudio(mic);
				camFeed.addChild( cameraVideo );

				// publish to FMS
				cameraNetStream.publish(getCameraFeedId, "live");

			}

			private function startLiveFeedCamera():void
			{
				// bring from FMS
				liveFeedNetStream = new NetStream(netConnection);
				liveFeedNetStream.play(getLiveFeedId);
				liveFeedVideo.attachNetStream(liveFeedNetStream);
				liveFeed.addChild( liveFeedVideo );

				// mask
				// addMask(circleMaskLiveFeed, liveFeed, 100);
			}

			private function get getLiveFeedId():String
			{
				return liveFeedId;
			}

			private function get getCameraFeedId():String
			{
				return camFeedId;
			}

		]]>
	</fx:Script>

	<mx:UIComponent id="liveFeed" width="{LIVE_FEED_WIDTH}" height="{LIVE_FEED_HEIGHT}" y="0" x="0" />
	<mx:UIComponent id="camFeed" width="{CAM_FEED_WIDTH}" height="{CAM_FEED_HEIGHT}" />

	<mx:Image id="recordButton" x="0" y="230" click="recordButton.source='assets/images/record_on_icon.gif'"
			  source="assets/images/record_icon.gif"/>
	<mx:Image id="stopButton" y="230" x="41" click="recordButton.source='assets/images/record_icon.gif'"
			  source="assets/images/stop_icon.gif"/>

	<s:DropDownList id="userTypeDropDownList" x="170" y="0"
					width="140" selectedIndex="0"
					change="{userType=userTypeDropDownList.selectedIndex-1; setSettingBasedOnUserType();}" visible="false">
		<mx:ArrayCollection>
			<fx:String>---</fx:String>
			<fx:String>Agent</fx:String>
			<fx:String>Client</fx:String>
		</mx:ArrayCollection>
	</s:DropDownList>

</s:Application>

In regards to the microphone, you can use the Microphone’s setUseEchoSuppression(true). setLoopBack(false) for removing mic’s echo and feedback but that is usually not enough to get top quality audio stream.

in FP 10.3, AIR 2.7 and up Adobe introduced enhanced audio, which includes acoustic echo cancellation and noise suppression etc.

there is a good article on Adobe’s ADC that takes about the new features and best practices:
http://www.adobe.com/devnet/flashplayer/articles/acoustic-echo-cancellation.html

In a nutshell here’s a method that will set the user’s mic with best possible settings:


			private function setMicOptions():Microphone
			{
				var options:MicrophoneEnhancedOptions = new MicrophoneEnhancedOptions();
				var microphone:Microphone = Microphone.getEnhancedMicrophone();

				// settings
				microphone.setLoopBack(false);
				microphone.setUseEchoSuppression(true); // being ignored but setting it anyway
				microphone.encodeQuality = 8;
				microphone.enableVAD = true;
				microphone.codec = SoundCodec.SPEEX;
				microphone.framesPerPacket = 1;
				microphone.setSilenceLevel(0, 2000);
				microphone.gain = 50;
				microphone.setSilenceLevel(0);
				microphone.rate = 16;

				microphone.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
				microphone.addEventListener(StatusEvent.STATUS, statusHandler);

				// options
				options.mode = MicrophoneEnhancedMode.FULL_DUPLEX;
				options.echoPath = 128; // can be increased to 256 for less echo
				options.nonLinearProcessing = true;

				microphone.enhancedOptions = options;

				return microphone;
			}

You can fine tune and adjust these settings but that should give you better results than the default built in settings. Notice that I am using the Speex codec (available from FP 10 and up). Speex is an open-source, royalty-free codec. Flash supports Speex encoding at 16 kHz.

When you use Speex transmission delay is minimized. FP uses an adaptive Speex jitter buffer when playing out messages. FP also using the Speex noise suppression and voice activity detection, which lower transmission’s bandwidth during silence.

Getting information about a page in an iframe that lives on a separate domain

Recently I created an iframe and the page inside of the iframe was redirecting to another page on a different domain. One would think that this is a simple task (just as you can do if they both lives on the same domain) and you can just pull the new URL out of the page using ajax once a change was made in the page or use the pseudo code standard as explained on wikipedia: http://en.wikipedia.org/wiki/XMLHttpRequest.

However these techniques didn’t work since there are cross domain restrictions. The browsers wont allow your parent page to access a different domain’s information since it can be abused by hackers.

HTML5 added the option to use the “postMessage” method and call the parent document. That will allow other domains to access the iframe page, so you would need permission from the parent domain and they can call a method in the parent domain that will let your parent document know that there have been change in the iframe,

For instance, a web master can create a wrapper for his page and place it in a wrapper and than use HTML5 new method “postMessage” to call the parent page and restrict it to a domain or just leave it as a wild card “*”

<?php
	$iframeStartURL = "http://[someURL]";

?>
<html>
<head>
	<title>Wrapper</title>
</head>
<body>

    <form id="frm1" name="frm1">
    	<input type="text" id="txtURL" value="<?php echo $iframeStartURL; ?>" style="visibility:hidden" />
    </form>

    <script type="text/javascript">
        var myURL = document.getElementById("txtURL");
        function GetSRC() {
			try {
				ajax.receive();
			}catch (err){
				alert("Error : " + err );
			}
        }

        var ajax =
        {
            send: function (urlstring) {
                if (!this.ifram) {
                    this.ifram = document.createElement('iframe');
                    this.ifram.style.display = 'none';
                    if (this.ifram.addEventListener) this.ifram.addEventListener('load', ajax.receive, false);
                    else if (this.ifram.attachEvent) this.ifram.attachEvent('onload', ajax.receive);
                    document.body.appendChild(this.ifram);
                }
                this.ifram.setAttribute('src', urlstring);
            },
            receive: function () {
				var newURL = ajax.ifram.getAttribute("src");
				if (newURL != null)
				{
					// send the new URL to parent window
					parent.postMessage(ajax.ifram.contentWindow.location.href, "http://[domain you allow]");
				}

                return;
            }
        };

		ajax.send(myURL.value);

    </script>
</body>
</html>

the parent window will be able to receive the message:

<html>
<head>
	<title></title>
</head>
<body>
    <iframe src="http://[some domain]"
        width="0%" height="0%" style="visibility:hidden">
    </iframe>

    <script>
		window.onload = function()
		{
			window.addEventListener( "message", function (evt) {

				if (evt.origin !== "http://eladelrom.com/blog/") {
					alert("cross domain issue");
				}

				alert(evt.data);
			}, false);
		};
	</script>
</body>
</html>

Other option is to use the “Access-Control-Allow-Origin” to the domain that you are trying to access to allow the parent document from a different domain to access the page.

However, sometimes you are using a page for your iframe that you don’t own or have access to and wont have the ability to use the HTML 5 method, plus the HTML 5 method wont work on all browsers so legacy browsers will suffer.

What you can do is create a server side script that will go and fetch a domain recognize the redirect or change in the page and send the result back to your parent page. For instance, here is how it can be done in PHP:

	$ch = curl_init("http://[domain]/[url]");

	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
	curl_setopt($ch, CURLOPT_HEADER, TRUE);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

	$result = curl_exec($ch);
	$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	curl_close($ch);

	if($code == 307) {
	  // Get the url from the location header
	  $regexp="/Location: (.*)$/m";
	  preg_match($regexp, $result, $matches);
	  $match1 = $matches[1];
	}