To post messages, you must join the IMS Public Community (free).   |   You also can also join the Common Cartridge Alliance.
IMS GLC Public Forums and Resources
Decrease font size
Increase font size
Topic Title: ../php-simple/adslist/ads.php does not work
Topic Summary:
Created On: 06/20/2011 10:06 AM
Status: Post and Reply
Linear : Threading : Single : Branch
Topic Tools Topic Tools
View topic in raw text format. Print this topic.
 06/20/2011 10:06 AM
User is offline View Users Profile Print this message

Author Icon
olive

Posts: 5
Joined: 06/15/2011

Hi there!
Let me tell you that I think that LTI is a wonderfull concept.
However:
I tried to play around with LTI.
I inserted "ads" into the ads.ads in my MySQL-Database, after creating it with the
given script.
there was no output on behalf of ads.php after calling it through php-simple/lms.php.
Although the Documentation stated otherwise.
So I though well, I might as well copy ads.php to another file and start working on it.

After copying the entire Code into another file, located in the same folder I get an error :Could not establish context: Could not find context in session " .

So I have 2 questions:
1) why isn't ads.php showing any results,although results are present and users are created
2)Why is the code in ads.php giving an error when copied to another file


I assume the second point is due to the name being different, so the file name - postfix identifies the DB-name/Table name(?),so:
where do I find Documentation which talks about stuff like this.

Sincerely

olive
 06/29/2011 08:40 AM
User is offline View Users Profile Print this message

Author Icon
CharlesSeverance

Posts: 50
Joined: 01/23/2009

Olive thanks for the question. I assume that you went all the way through the setup instructions in:

http://ims-dev.googlecode.com/...mple/adlist/index.htm

There is also a presentation about how this all works at:

http://www.imsglobal.org/devel...05-20-blti-php-02.pdf

In terms of no ad output after you call it from lms.php, all you should get at the beginning is a "Create new Ad" link.

I would go through ads.php, adding die("Message"); to step through and see how far it gets.

You may be dealing with something like PHP5 versus PHP4 and have errors set to be completely silent.

/Chuck
 07/05/2011 07:49 AM
User is offline View Users Profile Print this message

Author Icon
foryougautam

Posts: 4
Joined: 07/05/2011

Dear Chuk,
I am new to LTI and also facing the same problem could you please update your code.I follow the
the all of your instruction but not able to configure
 07/12/2011 08:34 AM
User is offline View Users Profile Print this message

Author Icon
olive

Posts: 5
Joined: 06/15/2011

Hi there!
The problem that nothing is shown, is a problem with Firefox 3.6.18 under Ubuntu Linux.
Chrome has no problems though, neither have FF4.x versions for Windows.
The rest was a PHP4 vs PHP5 issue,and sessions are handled differently.
I had to change the order in which session() and header() are called.

I agree with foryougautam.
A port to PHP5.x and mysqli would be outstanding.
None the less, the class-structure is very good, just writing a wrapper for webapps, not ment to be for LTI, using greate parts of your code.
Once again thanks for the Code.

@foryougautam:

Following Code is the the original code altered by me.
public $MYCONNECTION; in class BLTI is never set.
I changed that.
Since the class is created every time we have a call to the script it works perfectly.
Have fun with my adaption,they are minor though, only a couple of lines ,and I am not very happy with them.


blti.php
(line 102,103 btw it seems like it always ends up entering this if-clause)
(I patched it like this so that I may have a basis to work with,
You might want to recheck it though in case you want to use it on a productive system)
------------------------------------

<?php

require_once 'OAuth.php';


// Returns true if this is a Basic LTI message
// with minimum values to meet the protocol
function is_basic_lti_request() {
$good_message_type = $_REQUEST["lti_message_type"] == "basic-lti-launch-request";
$good_lti_version = $_REQUEST["lti_version"] == "LTI-1p0";
$resource_link_id = $_REQUEST["resource_link_id"];
if ($good_message_type and $good_lti_version and isset($resource_link_id) ) return(true);
return false;
}

/**
* A Trivial memory-based store - no support for tokens
*/
class TrivialOAuthDataStore extends OAuthDataStore {
private $consumers = array();

function add_consumer($consumer_key, $consumer_secret) {
$this->consumers[$consumer_key] = $consumer_secret;
}

function lookup_consumer($consumer_key) {
if ( strpos($consumer_key, "http://" ) === 0 ) {
$consumer = new OAuthConsumer($consumer_key,"secret", NULL);
return $consumer;
}
if ( $this->consumers[$consumer_key] ) {
$consumer = new OAuthConsumer($consumer_key,$this->consumers[$consumer_key], NULL);
return $consumer;
}
return NULL;
}

function lookup_token($consumer, $token_type, $token) {
return new OAuthToken($consumer, "");
}

// Return NULL if the nonce has not been used
// Return $nonce if the nonce was previously used
function lookup_nonce($consumer, $token, $nonce, $timestamp) {
// Should add some clever logic to keep nonces from
// being reused - for no we are really trusting
// that the timestamp will save us
return NULL;
}

function new_request_token($consumer) {
return NULL;
}

function new_access_token($token, $consumer) {
return NULL;
}
}


// Basic LTI Class that does the setup and provides utility
// functions
class BLTI {

public $valid = false;
public $complete = false;
public $message = false;
public $basestring = false;
public $info = false;
public $row = false;
public $context_id = false; // Override context_id
public $MYCONNECTION;

function __construct($parm=false, $usesession=true, $doredirect=true) {


// If this request is not an LTI Launch, either
// give up or try to retrieve the context from session
if ( ! is_basic_lti_request() ) {
if ( $usesession === false ) return;
if ( strlen(session_id()) > 0 ) {
$row = $_SESSION['_basiclti_lti_row'];
if ( isset($row) ) $this->row = $row;
$context_id = $_SESSION['_basiclti_lti_context_id'];
if ( isset($context_id) ) $this->context_id = $context_id;
$info = $_SESSION['_basic_lti_context'];
if ( isset($info) ) {
$this->info = $info;
$this->valid = true;
//THE NEXT 2 lines are mine IDIDIT

$this->MYCONNECTION = mysql_connect("localhost","adsuser","adspassword");
mysql_select_db("ads");
return;
}
$this->message = "Could not find context in session";
return;
}
$this->message = "Session not available";
return;
}

// Insure we have a valid launch
if ( empty($_REQUEST["oauth_consumer_key"]) ) {
$this->message = "Missing oauth_consumer_key in request";
return;
}
$oauth_consumer_key = $_REQUEST["oauth_consumer_key"];

// Find the secret - either form the parameter as a string or
// look it up in a database from parameters we are given
$secret = false;
$row = false;

if ( is_string($parm) ) {
$secret = $parm;
} else if ( ! is_array($parm) ) {
$this->message = "Constructor requires a secret or database information.";
return;
} else {
//I added this line
$MY_CONNECTION = mysql_connect("localhost","adsuser","adspassword");
mysql_select_db("ads");
if ( ! $MY_CONNECTION ) {
echo("Bad connection");
die();
}
if ( $_REQUEST['dbcheck'] ) {
echo('Good Database connection');
}



$sql = 'SELECT * FROM '.$parm['table'].' WHERE '.
($parm['key_column'] ? $parm['key_column'] : 'oauth_consumer_key').
'='.
"'".mysql_real_escape_string($oauth_consumer_key)."'";
$result = mysql_query($sql);
$num_rows = mysql_num_rows($result);
if ( $num_rows != 1 ) {
$this->message = $sql."<br>Your consumer is not authorized oauth_consumer_key=".$oauth_consumer_key;
return;
} else {
while ($row = mysql_fetch_assoc($result)) {
$secret = $row[$parms['secret_column']?$parms['secret_column']:'secret'];
$context_id = $row[$parms['context_column']?$parms['context_column']:'context_id'];
if ( $context_id ) $this->context_id = $context_id;
$this->row = $row;
break;
}
if ( ! is_string($secret) ) {
$this->message = "Could not retrieve secret oauth_consumer_key=".$oauth_consumer_key;
return;
}
}
}

// Verify the message signature
$store = new TrivialOAuthDataStore();
$store->add_consumer($oauth_consumer_key, $secret);

$server = new OAuthServer($store);

$method = new OAuthSignatureMethod_HMAC_SHA1();
$server->add_signature_method($method);
$request = OAuthRequest::from_request();

$this->basestring = $request->get_signature_base_string();

try {
$server->verify_request($request);
$this->valid = true;
} catch (Exception $e) {
$this->message = $e->getMessage();
return;
}

// Store the launch information in the session for later
$newinfo = array();
foreach($_POST as $key => $value ) {
if ( $key == "basiclti_submit" ) continue;
if ( strpos($key, "oauth_") === false ) {
$newinfo[$key] = $value;
continue;
}
if ( $key == "oauth_consumer_key" ) {
$newinfo[$key] = $value;
continue;
}
}









$this->info = $newinfo;
if ( $usesession == true and strlen(session_id()) > 0 ) {
$_SESSION['_basic_lti_context'] = $this->info;
unset($_SESSION['_basiclti_lti_row']);
unset($_SESSION['_basiclti_lti_context_id']);
if ( $this->row ) $_SESSION['_basiclti_lti_row'] = $this->row;
if ( $this->context_id ) $_SESSION['_basiclti_lti_context_id'] = $this->context_id;
}

if ( $this->valid && $doredirect ) {
$this->redirect();
$this->complete = true;
}
}

function addSession($location) {
if ( ini_get('session.use_cookies') == 0 ) {
if ( strpos($location,'?') > 0 ) {
$location = $location . '&';
} else {
$location = $location . '?';
}
$location = $location . session_name() . '=' . session_id();
}
return $location;
}

function isInstructor() {
$roles = $this->info['roles'];
$roles = strtolower($roles);
if ( ! ( strpos($roles,"instructor") === false ) ) return true;
if ( ! ( strpos($roles,"administrator") === false ) ) return true;
return false;
}

function getUserEmail() {
$email = $this->info['lis_person_contact_email_primary'];
if ( strlen($email) > 0 ) return $email;
# Sakai Hack
$email = $this->info['lis_person_contact_emailprimary'];
if ( strlen($email) > 0 ) return $email;
return false;
}

function getUserShortName() {
$email = $this->getUserEmail();
$givenname = $this->info['lis_person_name_given'];
$familyname = $this->info['lis_person_name_family'];
$fullname = $this->info['lis_person_name_full'];
if ( strlen($email) > 0 ) return $email;
if ( strlen($givenname) > 0 ) return $givenname;
if ( strlen($familyname) > 0 ) return $familyname;
return $this->getUserName();
}

function getUserName() {
$givenname = $this->info['lis_person_name_given'];
$familyname = $this->info['lis_person_name_family'];
$fullname = $this->info['lis_person_name_full'];
if ( strlen($fullname) > 0 ) return $fullname;
if ( strlen($familyname) > 0 and strlen($givenname) > 0 ) return $givenname + $familyname;
if ( strlen($givenname) > 0 ) return $givenname;
if ( strlen($familyname) > 0 ) return $familyname;
return $this->getUserEmail();
}

function getUserKey() {
$oauth = $this->info['oauth_consumer_key'];
$id = $this->info['user_id'];
if ( strlen($id) > 0 and strlen($oauth) > 0 ) return $oauth . ':' . $id;
return false;
}

function getUserImage() {
$image = $this->info['user_image'];
if ( strlen($image) > 0 ) return $image;
$email = $this->getUserEmail();
if ( $email === false ) return false;
$size = 40;
$grav_url = $_SERVER['HTTPS'] ? 'https://' : '">">">"><br ..."...L...//';


]http://';
<br [/L]
]http://';
<br [/L]
]http://';
<br [/L]
$grav_url = $grav_url . "www.gravatar.com/avatar.php?gravatar_id=".md5( strtolower($email) )."&size=".$size;
return $grav_url;
}

function getResourceKey() {
$oauth = $this->info['oauth_consumer_key'];
$id = $this->info['resource_link_id'];
if ( strlen($id) > 0 and strlen($oauth) > 0 ) return $oauth . ':' . $id;
return false;
}

function getResourceTitle() {
$title = $this->info['resource_link_title'];
if ( strlen($title) > 0 ) return $title;
return false;
}

function getConsumerKey() {
$oauth = $this->info['oauth_consumer_key'];
return $oauth;
}

function getCourseKey() {
if ( $this->context_id ) return $this->context_id;
$oauth = $this->info['oauth_consumer_key'];
$id = $this->info['context_id'];
if ( strlen($id) > 0 and strlen($oauth) > 0 ) return $oauth . ':' . $id;
return false;
}

function getCourseName() {
$label = $this->info['context_label'];
$title = $this->info['context_title'];
$id = $this->info['context_id'];
if ( strlen($label) > 0 ) return $label;
if ( strlen($title) > 0 ) return $title;
if ( strlen($id) > 0 ) return $id;
return false;
}

// TODO: Add javasript version if headers are already sent
function redirect() {
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['PHP_SELF'];
$location = $_SERVER['HTTPS'] ? 'https://' : '">">">"><br ..."...L...//';


]http://';
<br [/L]
]http://';
<br [/L]
]http://';
<br [/L]
$location = $location . $host . $uri;
$location = $this->addSession($location);
header("Location: $location");
}

function dump() {
if ( ! $this->valid or $this->info == false ) return "Context not valid\n";
$ret = "";
if ( $this->isInstructor() ) {
$ret .= "isInstructor() = true\n";
} else {
$ret .= "isInstructor() = false\n";
}
$ret .= "getUserKey() = ".$this->getUserKey()."\n";
$ret .= "getUserEmail() = ".$this->getUserEmail()."\n";
$ret .= "getUserShortName() = ".$this->getUserShortName()."\n";
$ret .= "getUserName() = ".$this->getUserName()."\n";
$ret .= "getUserImage() = ".$this->getUserImage()."\n";
$ret .= "getResourceKey() = ".$this->getResourceKey()."\n";
$ret .= "getResourceTitle() = ".$this->getResourceTitle()."\n";
$ret .= "getCourseName() = ".$this->getCourseName()."\n";
$ret .= "getCourseKey() = ".$this->getCourseKey()."\n";
$ret .= "getConsumerKey() = ".$this->getConsumerKey()."\n";
return $ret;
}

}

?>

-----------------------
Since we are using mysql_func()-calls we need a connection, so we make sure we use the right one, and use $context->MYCONNECTION.
(I'm pretty sure we do not need that since PHP-executes every request as a process but we want to make sure, and I have no clue how FastPHP behaves in such a situation,so just in case)

ads.php
---------------------------------------------------

<?php



try {//this has to be the first otherwise sessions won't work
session_start();
} catch (Exception $e) {
$warning_session = true;
}

header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
ini_set('session.use_cookies', '0');


error_reporting(E_ALL & ~E_NOTICE);
ini_set("display_errors", 1);

// Load up the Basic LTI Support code
require_once '../ims-blti/blti.php';

// Establish the database connnection
require_once("DB.php");




// Establish the context
$context = new BLTI(array('table' => 'blti_keys'));

if ( $context->complete ) exit();



if ( ! $context->valid ) {
print "Could not establish context: ".$context->message."<p>\n";
exit();
}








// Start of the ad code
$self = $context->addSession($_SERVER['PHP_SELF']);
if ( strpos($self,'?') > 0 ) {
$selfp = $self . '&';
} else {
$selfp = $self . '?';
}
$action = $_REQUEST['action'];
$message = false;
$title = false;
$description = false;
$idvalue = false;


// AuthZ WHERE clause terms
$authzsql = "course_key=".
"'".mysql_real_escape_string($context->getCourseKey(),$context->MYCONNECTION)."'";
if ( ! $context->isInstructor() ) {
$authzsql = $authzsql . "AND user_key=".
"'".mysql_real_escape_string($context->getUserKey(),$context->MYCONNECTION)."'";
}




if ( $action == 'delete' ) {
$idvalue = $_REQUEST['id'];
if ( $idvalue ) {
$sql = 'DELETE FROM ads WHERE id=' .
"'".mysql_real_escape_string($idvalue,$context->MYCONNECTION)."' AND ".$authzsql;
$result = mysql_query($sql,$context->MYCONNECTION);
$retval = mysql_affected_rows($context->MYCONNECTION);
if ( $retval != 1 ) {
$message = "Error, unable to delete ad.";
$action = 'main';
} else {
$message = "Deleted record id=".$idvalue;
$action = 'main';
}
}
}

if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
$title = $_REQUEST['title'];
$description = $_REQUEST['description'];
$idvalue = $_REQUEST['id'];
if ( $title && $description ) {
if ( $idvalue ) {
$sql = 'UPDATE ads SET ' .
"title='".mysql_real_escape_string($title,$context->MYCONNECTION)."', " .
"description='".mysql_real_escape_string($description,$context->MYCONNECTION)."', " .
"updated_at= NOW() " .
"WHERE id=".
"'".mysql_real_escape_string($idvalue,$context->MYCONNECTION)."' AND ".$authzsql;
$result = mysql_query($sql,$context->MYCONNECTION);
$retval = mysql_affected_rows($context->MYCONNECTION);
if ( $retval != 1 ) {
$message = "Error, unable to update ad.";
$action = 'edit';
} else {
$message = "Updated record for '".$title."' id=".$idvalue;
$action = 'main';
}
} else {
$sql = 'INSERT INTO ads ' .
'( title, description, course_key, user_key, user_name, user_image, created_at, updated_at ) ' .
' VALUES ( ' .
"'".mysql_real_escape_string($title,$context->MYCONNECTION)."', " .
"'".mysql_real_escape_string($description,$context->MYCONNECTION)."', " .
"'".mysql_real_escape_string($context->getCourseKey())."', " .
"'".mysql_real_escape_string($context->getUserKey())."', " .
"'".mysql_real_escape_string($context->getUserName())."', " .
"'".mysql_real_escape_string($context->getUserImage())."', " .
" NOW(), NOW() ) ";
$result = mysql_query($sql,$context->MYCONNECTION);
$retval = mysql_affected_rows($context->MYCONNECTION);
if ( $retval != 1 ) {
$message = "Error, unable to insert ad.";
$action = 'add';
} else {
$idvalue = mysql_insert_id($context->MYCONNECTION);
$message = "Inserted ad '".$name."' id=".$idvalue;
$action = 'main';
$context->redirect();
}
}
} else {
$message = "Error, please specify all data.";
$action = 'add';
if ( $idvalue ) $action = 'edit';
}
}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"">"><br ">">"><br "><br "><br ">&l......./DT...ct.dtd">



]http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd---->
<br [/L]
<html>
<head>
<title>Basic LTI Classified Ad System</title>
<link href="glike.css" rel="stylesheet" type="text/css" />
</head>
<body>
<?php

if ( $action == 'edit' || $action == 'view' ) {
$idvalue = $_REQUEST['id'];
if ( $idvalue ) {
$sql = 'SELECT * FROM ads WHERE id=' .
"'".mysql_real_escape_string($idvalue,$context->MYCONNECTION)."' AND ".$authzsql;
$result = mysql_query($sql,$context->MYCONNECTION);
$num_rows = mysql_num_rows($result);
if ( $num_rows != 1 ) {
$message = "Error, could not locate ad.";
$action = 'main';
} else {
while ($row = mysql_fetch_assoc($result)) {
$title = $row['title'];
$description = $row['description'];
$user_name = $row['user_name'];
$user_image = $row['user_image'];
$updated_at = $row['updated_at'];
}
}
}
}

if ( $action == 'view' ) {
$image = $context->getUserImage();
if ( strlen($image) > 0 ) {
echo('<img src="'.$user_image.'" align="right" width="40" height="40">'."\n");
}
if ( $message ) {
echo('<p style="color:red;">'.$message."</p>\n");
}
echo("<p><b>$title</b><br/>\n");
echo($description."</p>\n");
echo("<p>$user_name ($updated_at) </p>\n");
?>
<input type="submit" value="Back To List"
onclick="window.location='<?=$self?>'; return false;"/>
<?php
exit();
}

if ( $action == 'add' || $action == 'edit') {
if ( $message ) {
echo('<p style="color:red;">'.$message."</p>\n");
}
$enabled="";
if ( $action == 'add' ) {
echo("<p>Add New Classified Ad</p>\n");
} else {
echo("<p>Edit Classified Ad</p>\n");
}
?>
<form method="post">
<?php
if ( $idvalue ) echo('<input type="hidden" value="'.$idvalue.'">'."\n");
?>
<p>Title<br/>
<input type="text" name="title" size="70" value="<?=$title?>"></p>
<p>Description<br/>
<textarea id="description" name="description" rows="12" cols="70"><?=$description?></textarea></p>
<p><input type='submit'>
<input type="submit" value="Cancel"
onclick="window.location='<?=$self?>'; return false;"/>
</p>
</form>
<?php
exit();
}

$sql = "SELECT * FROM ads WHERE course_key=".
"'".mysql_real_escape_string($context->getCourseKey(),$context->MYCONNECTION)."' " .
"ORDER BY created_at DESC";

$result = mysql_query($sql,$context->MYCONNECTION);
$num_rows = mysql_num_rows($result);

if ( $message ) {
echo('<p style="color:red;">'.$message."</p>\n");
}

if( mysql_num_rows( $result ) == 0 ) {
echo "<p>No Ads available for '".$context->getCourseName()."'";
echo(' (<a title="New Ad" href="'.$selfp.'action=add">Create New Ad</a>'."\n");
} else {
?>
<table style="width: 100%">
<tr><th style="width: 70%">
<?php
$title = $context->getResourceTitle();
if ( $title === false ) {
echo('Title');
} else {
echo($title);
}
?>

(<a title="New Ad" href="<?=$selfp?>action=add">Create New Ad</a>
</th><th>Date</th><th>Action</th></tr>
<?php
while( $row = mysql_fetch_array( $result ) ) {
?>
<tr>
<td>
<a title="View" href="<?=$selfp?>action=view&id=<?=$row[id]?>"><?=$row['title']?></a></td>
<td><?=$row['updated_at']?></td>
<td>
<?php
if ( $context->isInstructor() || $row['user_key'] == $context->getUserKey() ) {
?>
<a title="Edit" href="<?=$selfp?>action=edit&id=<?=$row[id]?>">edit</a>
<a title="Delete" href="<?=$selfp?>action=delete&id=<?=$row[id]?>">delete</a>
<?php
}
?>
</td>
</tr>
<?php
}
?>
</table>
<?php
}

/*
echo("<pre>\n");
echo("Debug Output:\n");
echo($context->dump());
echo("</pre>\n");
*/

?>
</body>
</html>

--------------------------------------------------------

Edited: 07/12/2011 at 08:44 AM by olive
 07/20/2011 07:27 AM
User is offline View Users Profile Print this message

Author Icon
foryougautam

Posts: 4
Joined: 07/05/2011

Dear OLIVE

Thanks for your quick response.
I have implemented LTI provider in my product with the help of your code. I am using Basic LTI tool consumer in Moodle2.x & found that everytime i want to expose a resource from a LTI Tool producer I need to add it in Basic LTI administration panel with a shared key pair. This resource can then be utilised from within the interface of Moodle in an embedded iframe. When I started using LTI I was of the idea that we register repositories and then use assets / resources from these repositories in our LTI tool consumer. However now I find a shift here. We need add resources with the relevant key/pairs in the Basic LTI Administration panel in Moodle. This is very limiting by the fact that we have a huge number of assets(videos, resources, documents, experiences) that needs to be exposed.

My question is, is there a way to make only one repository per producer and still identify all of the resources in that repository with different contexts in different areas / courses? Following what is happening currently we get a huge list in the "Add an activity" dropdown which doesn't suit the user experience and is also much of a constraint. If I have not understood correctly kindly guide me how this can be done if this can be done.

Awaiting your response.

Rgds,

Gautam Bishwas
 08/01/2011 06:55 AM
User is offline View Users Profile Print this message

Author Icon
olive

Posts: 5
Joined: 06/15/2011

Dear foryougautam,

IMHO , defining a repository or defining a ressource should look all the same to Moodle.
Just add a script managing the repository to Moodle, identify it using LTI and provide additional parameters, if you want, or allow browsing through the repository.
Just keep in mind that you will need to add the LTI-part every time you make a call to the serversidescripts.

You can further protect the resources by additional scripts or temporary files/directories.

sincerly

Olive
Statistics
2986 users are registered to the IMS GLC Public Forums and Resources forum.
There are currently 0 users logged in.

FuseTalk Standard Edition v3.2 - © 1999-2013 FuseTalk Inc. All rights reserved.

By participating in the forum, you agree to the abide by forum rules. You can view the IMS GLC Privacy Statement