Browse Source

Update from 1.11.X

Julio 6 years ago
parent
commit
777314a500

+ 8 - 0
main/inc/lib/javascript/chat/css/chat.css

@@ -171,3 +171,11 @@
 .chatboxoptions a:hover {
 	background-color: #aaa;
 }
+
+.chatbox_checks {
+	float:right;
+}
+
+.chatbox_checked {
+	color: #13A7F0;
+}

+ 496 - 288
main/inc/lib/javascript/chat/js/chat.js

@@ -33,35 +33,37 @@ var chatboxFocus = new Array();
 var newMessages = new Array();
 var newMessagesWin = new Array();
 var chatBoxes = new Array();
+var intervals = new Array();
 var timer;
 var user_status = 0;
 var widthBox = 320; // see css class .chatbox
 //var ajax_url = 'chat.php'; // This variable is loaded in the template/layout/head.tpl file
+var doubleCheck = '<span class="chatbox_checked"><i class="fa fa-check"></i><i class="fa fa-check"></i></span>';
 
 function set_user_status(status)
 {
-    if (status == 1) {
-        stopChatHeartBeat();
-        startChatHeartBeat();
-        $('.user_status_main').html(online_button);
-        $('#chatboxtitlemain').html(connect_lang);
-    } else {
-        stopChatHeartBeat();
-        $('.user_status_main').html(offline_button);
-        $('#chatboxtitlemain').html(disconnect_lang);
-    }
-
-    $.ajax({
-        url: ajax_url+"?action=set_status",
-        data: "status="+status,
-        cache: false,
-        success: function(data) {
-        }
-    });
-    user_status = status;
+	if (status == 1) {
+		stopChatHeartBeat();
+		startChatHeartBeat();
+		$('.user_status_main').html(online_button);
+		$('#chatboxtitlemain').html(connect_lang);
+	} else {
+		stopChatHeartBeat();
+		$('.user_status_main').html(offline_button);
+		$('#chatboxtitlemain').html(disconnect_lang);
+	}
+
+	$.ajax({
+		url: ajax_url+"?action=set_status",
+		data: "status="+status,
+		cache: false,
+		success: function(data) {
+		}
+	});
+	user_status = status;
 }
 
-$(document).ready(function() {
+$(function() {
 	originalTitle = document.title;
 	startChatSession();
 	$([window, document]).blur(function() {
@@ -72,13 +74,10 @@ $(document).ready(function() {
 	});
 
 	/* "On" conditions, divs are created dynamically */
-    // User name header toggle
+	// User name header toggle
 	$('body').on('click', '#chatboxtitlemain', function() {
-	    if (user_status == 1) {
-            set_user_status(0);
-        } else {
-	        set_user_status(1);
-        }
+		createMyContactsWindow();
+        set_user_status(1);
 	});
 
 	// User name header toogle
@@ -98,23 +97,28 @@ $(document).ready(function() {
 	// Close button
 	$('body').on('click', '.chatboxhead .closelink', function(){
 		var chat_id =  $(this).attr('rel');
-		closeChatBox(chat_id);
+		closeWindow(chat_id);
+	});
+
+	// Close main chat
+	$('body').on('click', '.chatboxhead .close_chat', function(){
+		closeChat();
 	});
 });
 
 function showChatConnect()
 {
-    if (user_status == 1) {
-        button = online_button;
-        label = connect_lang;
-    } else {
-        button = offline_button;
-        label = disconnect_lang;
-    }
-    $("<div />").attr("id","chatmain")
-	.addClass("chatboxmain")
-	.html('<div class="chatboxheadmain"><div class="user_status_main">'+button+'</div><div id="chatboxtitlemain">'+label+'</div><div class="chatboxoptions"></div></div>')
-	.appendTo($( "body" ));
+	if (user_status == 1) {
+		button = online_button;
+		label = connect_lang;
+	} else {
+		button = offline_button;
+		label = disconnect_lang;
+	}
+	$("<div />").attr("id","chatmain")
+		.addClass("chatboxmain")
+		.html('<div class="chatboxheadmain"><div class="user_status_main">'+button+'</div><div id="chatboxtitlemain">'+label+'</div><div class="chatboxoptions"></div></div>')
+		.appendTo($( "body" ));
 }
 
 /**
@@ -122,70 +126,72 @@ function showChatConnect()
  */
 function startChatSession()
 {
-    /* fix bug BT#5728 whereby users cannot move to the next question in IE9 */
-    if (typeof ajax_url != 'undefined') {
-        $.ajax({
-          url: ajax_url+"?action=startchatsession",
-          cache: false,
-          dataType: "json",
-          success: function(data) {
-            if (data) {
-                username = data.me;
-                currentUserId = data.user_id;
-                user_status = data.user_status;
-                showChatConnect();
-                if (user_status == 1) {
-                    startChatHeartBeat();
-                } else {
-                    stopChatHeartBeat();
-                }
+	/* fix bug BT#5728 whereby users cannot move to the next question in IE9 */
+	if (typeof ajax_url != 'undefined') {
+		$.ajax({
+			url: ajax_url+"?action=startchatsession",
+			cache: false,
+			dataType: "json",
+			success: function(data) {
+				if (data) {
+					username = data.me;
+					currentUserId = data.user_id;
+					user_status = data.user_status;
+					showChatConnect();
+					if (user_status == 1) {
+						startChatHeartBeat();
+					} else {
+						stopChatHeartBeat();
+					}
 
-                $.each(data.items, function(my_user_id, user_items) {
-                    my_items = user_items['items'];
-                    $.each(my_items, function(i, item) {
-                        if (item) {
-                            // fix strange ie bug
-                            if ($("#chatbox_"+my_user_id).length <= 0) {
-                                createChatBox(
-                                    my_user_id,
-                                    item.username,
-                                    1,
-                                    item.user_info.online,
-                                    item.user_info.avatar
-                                );
-                            }
-
-                            if (item.s == 2) {
-                                // info message
-                                //$("#chatbox_"+my_user_id+" .chatboxcontent").append('<div class="'+messageLogMe+'"><span class="chatboxinfo">'+item.m+'</span></div>');
-                            } else {
-                                var chatBubble = createChatBubble(my_user_id, item);
-                                $("#chatbox_"+my_user_id+" .chatboxcontent").append(chatBubble);
-                            }
-                        }
-                    });
-                });
-
-                for (i = 0; i < chatBoxes.length; i++) {
-                    my_user_id = chatBoxes[i];
-                    $("#chatbox_"+my_user_id+" .chatboxcontent").scrollTop(
-                        $("#chatbox_"+my_user_id+" .chatboxcontent")[0].scrollHeight
-                    );
-                }
-            }
-        }});
-    }
+					$.each(data.items, function(my_user_id, user_items) {
+						if (currentUserId == my_user_id) {
+							// show contact list
+							createMyContactsWindow();
+							return true;
+						}
+
+						my_items = user_items['items'];
+						window_user_info = user_items['window_user_info'];
+						$.each(my_items, function(i, item) {
+							if (item) {
+								// fix strange ie bug
+								if ($("#chatbox_"+my_user_id).length <= 0) {
+									createChatBox(
+										my_user_id,
+										window_user_info.complete_name,
+										1,
+										window_user_info.online,
+										window_user_info.avatar_small
+									);
+								}
+
+								createChatBubble(my_user_id, item);
+							}
+						});
+					});
+
+					for (i = 0; i < chatBoxes.length; i++) {
+						my_user_id = chatBoxes[i];
+						$("#chatbox_"+my_user_id+" .chatboxcontent").scrollTop(
+							$("#chatbox_"+my_user_id+" .chatboxcontent")[0].scrollHeight
+						);
+					}
+				}
+			}
+		});
+	}
 }
 
 function stopChatHeartBeat()
 {
-    clearInterval(timer);
-    timer = null;
+	clearInterval(timer);
+	timer = null;
 }
 
 function startChatHeartBeat()
 {
-    timer = setInterval(chatHeartbeat, chatHeartbeatTime);
+	timer = setInterval(chatHeartbeat, chatHeartbeatTime);
 }
 
 /*
@@ -194,7 +200,6 @@ function startChatHeartBeat()
  * Item array structure :
  *
  * item.s = type of message: 1 = message, 2 = "sent at" string
- * item.m = message
  * item.f = from_user
  *
  **/
@@ -209,8 +214,8 @@ function chatHeartbeat()
 			if (newMessagesWin[x].status == true) {
 				++blinkNumber;
 				if (blinkNumber >= blinkOrder) {
-					document.title = newMessagesWin[x].username+' says...';
-					titleChanged = 1;
+					//document.title = newMessagesWin[x].username+' says...';
+					//titleChanged = 1;
 					break;
 				}
 			}
@@ -222,7 +227,6 @@ function chatHeartbeat()
 		} else {
 			++blinkOrder;
 		}
-
 	} else {
 		for (x in newMessagesWin) {
 			newMessagesWin[x].status = false;
@@ -244,44 +248,46 @@ function chatHeartbeat()
 		dataType: "json",
 		success: function(data) {
 			$.each(data.items, function(my_user_id, user_items) {
-                my_items = user_items['items'];
+				// Each window
+				my_items = user_items['items'];
+				userInfo = user_items['window_user_info'];
+
+				update_online_user(
+					my_user_id,
+					userInfo.user_is_online
+				);
+
 				$.each(my_items, function(i, item) {
 					if (item) {
-                        // fix strange ie bug
+						// fix strange ie bug
 						if ($("#chatbox_"+my_user_id).length <= 0) {
 							createChatBox(
-							    my_user_id,
-                                item.username,
-                                0,
-                                item.user_info.online,
-                                item.user_info.avatar
-                            );
+								my_user_id,
+								userInfo.complete_name,
+								0,
+								userInfo.online,
+								userInfo.avatar_small
+							);
 						}
+
 						if ($("#chatbox_"+my_user_id).css('display') == 'none') {
 							$("#chatbox_"+my_user_id).css('display','block');
 							restructureChatBoxes();
 						}
-						update_online_user(
-						    my_user_id,
-                            user_items.user_info.online
-                        );
-
-						if (item.s == 2) {
-							//$("#chatbox_"+my_user_id+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxinfo">'+item.m+'</span></div>');
-						} else {
-							newMessages[my_user_id] = {'status':true, 'username':item.username};
-							newMessagesWin[my_user_id]= {'status':true, 'username':item.username};
-							var chatBubble = createChatBubble(my_user_id, item);
-							$("#chatbox_"+my_user_id+" .chatboxcontent").append(chatBubble);
-						}
+
+						newMessages[my_user_id] = {'status':true, 'username':item.username};
+						newMessagesWin[my_user_id]= {'status':true, 'username':item.username};
+
+						var chatBubble = createChatBubble(my_user_id, item);
+						//$("#chatbox_"+my_user_id+" .chatboxcontent").append(chatBubble);
 
 						$("#chatbox_"+my_user_id+" .chatboxcontent").scrollTop(
-						    $("#chatbox_"+my_user_id+" .chatboxcontent")[0].scrollHeight
-                        );
+							$("#chatbox_"+my_user_id+" .chatboxcontent")[0].scrollHeight
+						);
 
-                        if ($('#chatbox_'+my_user_id+' .chatboxcontent').css('display') == 'none') {
-                            $('#chatbox_'+my_user_id+' .chatboxhead').toggleClass('chatboxblink');
-                        }
+						if ($('#chatbox_'+my_user_id+' .chatboxcontent').css('display') == 'none') {
+							$('#chatbox_'+my_user_id+' .chatboxhead').toggleClass('chatboxblink');
+						}
 						itemsfound += 1;
 					}
 				});
@@ -299,38 +305,100 @@ function chatHeartbeat()
 					chatHeartbeatTime = maxChatHeartbeat;
 				}
 			}
-			//timer = setTimeout('chatHeartbeat();',chatHeartbeatTime);
 		}
 	}); //ajax
 }
 
 /**
- * Draws a message buble
+ * Draws a message bubble
  * @param my_user_id
  * @param item
  * @returns {string}
  */
-function createChatBubble(my_user_id, item)
+function createChatBubble(my_user_id, item, appendType = 'append')
+{
+	var myDiv = 'chatboxmessage_me';
+	if (my_user_id == item.from_user_info.id) {
+		myDiv = 'chatboxmessage';
+	}
+	var sentDate = '';
+	if (moment.unix(item.date).isValid()) {
+		sentDate = moment.unix(item.date).format('LLL');
+	}
+
+	var check = '';
+	var unCheckClass = ' check_status';
+	if (my_user_id != item.from_user_info.id) {
+		check = '<i class="fa fa-check"></i><i class="fa fa-check"></i>';
+		if (item.recd == 1) {
+			unCheckClass = '';
+			check = doubleCheck;
+		}
+	}
+
+	var messageObject = $("#chatbox_"+my_user_id+" .chatboxcontent").find('#message_id_' + item.id);
+	var exists = messageObject.length !== 0;
+	var messageHeader = '<div id="message_id_'+item.id+'" class="chatbox-common boot-tooltip well '+myDiv+'" title="'+sentDate+'" >';
+	var messageEnd = '</div>';
+
+	var message = '';
+	if (my_user_id == item.from_user_info.id) {
+		message += '<span class="chatboxmessagefrom">'+item.from_user_info.complete_name+':&nbsp;&nbsp;</span>';
+	}
+	message += '<div class="chatboxmessagecontent">'+item.message+'</div>';
+	message += '<div class="chatbox_checks' + unCheckClass + '">'+check+'</div>';
+
+	if (exists) {
+		messageObject.html(message);
+	} else {
+		message = messageHeader + message + messageEnd;
+		if (appendType == 'append') {
+			$("#chatbox_"+my_user_id+" .chatboxcontent").append(message);
+		} else {
+			$("#chatbox_"+my_user_id+" .chatboxcontent").prepend(message);
+		}
+
+	}
+
+	return message;
+}
+
+/**
+ * Disconnect user from chat
+ */
+function closeChat()
 {
-    var myDiv = 'chatboxmessage_me';
-    if (my_user_id == item.f) {
-        myDiv = 'chatboxmessage';
-    }
-    var sentDate = '';
-    if (moment.unix(item.date).isValid()) {
-        sentDate = moment.unix(item.date).format('LLL');
-    }
-
-    return '<div class="boot-tooltip well '+myDiv+'" title="'+sentDate+'" >' +
-        '<span class="chatboxmessagefrom">'+item.username+':&nbsp;&nbsp;</span>' +
-        '<span class="chatboxmessagecontent">'+item.m+'</span></div>';
+	$.post(
+		ajax_url + "?action=close",
+		{
+		},
+		function (data) {
+			// Disconnects from chat
+			set_user_status(0);
+			// Clean cookies
+			Cookies.set('chatbox_minimized', new Array());
+			// Delete all windows
+			$('.chatbox ').remove();
+
+			// Reset variables
+            chatBoxes = new Array();
+            intervals = new Array();
+		}
+	);
 }
 
-function closeChatBox(user_id) {
+function closeWindow(user_id)
+{
 	$('#chatbox_'+user_id).css('display','none');
-        restructureChatBoxes();
-        $.post(ajax_url+"?action=closechat", {chatbox: user_id} , function(data){
-	});
+	restructureChatBoxes();
+	$.post(
+		ajax_url + "?action=close_window",
+		{
+			chatbox: user_id
+		},
+		function (data) {
+		}
+	);
 }
 
 function restructureChatBoxes()
@@ -359,18 +427,163 @@ function restructureChatBoxes()
  **/
 function chatWith(user_id, user_name, status, userImage)
 {
-    set_user_status(1);
+	set_user_status(1);
 	createChatBox(user_id, user_name, 0, status, userImage);
 	$("#chatbox_"+user_id+" .chatboxtextarea").focus();
 	getMoreItems(user_id, 'last');
 }
 
+/**
+ * Creates a div
+ */
+function createMyContactsWindow()
+{
+	var user_id = 'contacts';
+	var oldChatBox = $("#chatbox_"+user_id);
+	if (oldChatBox.length > 0) {
+		// reload contact list
+		if (oldChatBox.css('display') == 'none') {
+			oldChatBox.css('display','block');
+			restructureChatBoxes();
+		}
+
+		chatboxContent = oldChatBox.find('.chatboxcontent');
+
+		$.post(ajax_url + "?action=get_contacts", {
+			to: 'user_id'
+		}, function (data) {
+			chatboxContent.html(data);
+		});
+
+		$("#chatbox_"+user_id+" .chatboxtextarea").focus();
+
+		return;
+	}
+
+	var chatbox = $('<div>')
+		.attr({
+			id: 'chatbox_' + user_id
+		})
+		.addClass('chatbox')
+		.css('bottom', 0);
+
+	var chatboxHead = $('<div>')
+		.addClass('chatboxhead')
+		.append('');
+
+	$('<div>')
+		.addClass('chatboxtitle')
+		.append(chatLang)
+		.appendTo(chatboxHead);
+
+	var chatboxoptions = $('<div>')
+		.addClass('chatboxoptions')
+		.appendTo(chatboxHead);
+
+	$('<a>')
+		.addClass('btn btn-xs togglelink')
+		.attr({
+			href: 'javascript:void(0)',
+			rel: user_id
+		})
+		.html('<em class="fa fa-toggle-down"></em>')
+		.appendTo(chatboxoptions);
+
+	$('<a>')
+		.addClass('btn btn-xs close_chat')
+		.attr({
+			href: 'javascript:void(0)',
+			rel: user_id
+		})
+		.html('<em class="fa fa-close"></em>')
+		.appendTo(chatboxoptions);
+
+	$('<br>')
+		.attr('clear', 'all')
+		.appendTo(chatboxHead);
+
+	var chatboxContent = $('<div>').addClass('chatboxcontent');
+	var chatboxInput = $('<div>').addClass('chatboxinput');
+
+	$.post(ajax_url + "?action=get_contacts", {
+		to: 'user_id'
+	}, function (data) {
+		$('<div>').html(data).appendTo(chatboxContent);
+	});
+
+	chatbox
+		.append(chatboxHead)
+		.append(chatboxContent)
+		.append(chatboxInput)
+		.appendTo('body');
+
+	var chatBoxeslength = 0;
+	for (x in chatBoxes) {
+		if ($("#chatbox_"+chatBoxes[x]).css('display') != 'none') {
+			chatBoxeslength++;
+		}
+	}
+
+	if (chatBoxeslength == 0) {
+		$("#chatbox_"+user_id).css('right', '10px');
+	} else {
+		width = (chatBoxeslength)*(widthBox+7) + 5 + 5;
+		$("#chatbox_"+user_id).css('right', width+'px');
+	}
+
+	chatBoxes.push(user_id);
+	chatboxFocus[user_id] = false;
+
+	$("#chatbox_"+user_id+" .chatboxtextarea").blur(function(){
+		chatboxFocus[user_id] = false;
+		$("#chatbox_"+user_id+" .chatboxtextarea").removeClass('chatboxtextareaselected');
+	}).focus(function(){
+		chatboxFocus[user_id] = true;
+		newMessages[user_id] = false;
+		$('#chatbox_'+user_id+' .chatboxhead').removeClass('chatboxblink');
+		$("#chatbox_"+user_id+" .chatboxtextarea").addClass('chatboxtextareaselected');
+	});
+
+	$("#chatbox_"+user_id).click(function() {
+		if ($('#chatbox_'+user_id+' .chatboxcontent').css('display') != 'none') {
+			$("#chatbox_"+user_id+" .chatboxtextarea").focus();
+		}
+	});
+
+	$("#chatbox_"+user_id).show();
+	$("#chatbox_"+user_id+" .chatboxcontent").scroll(function () {
+		var iCurScrollPos = $(this).scrollTop();
+		if (iCurScrollPos == 0) {
+			getMoreItems(user_id);
+			return false;
+		}
+	});
+
+	minimizedChatBoxes = new Array();
+	if (Cookies.get('chatbox_minimized')) {
+		minimizedChatBoxes = Cookies.getJSON('chatbox_minimized');
+
+		minimize = 0;
+		for (j = 0; j < minimizedChatBoxes.length; j++) {
+			if (minimizedChatBoxes[j] == user_id) {
+				minimize = 1;
+			}
+		}
+
+		if (minimize == 1) {
+			$('.togglelink').html('<em class="fa fa-toggle-up"></em>');
+			$('#chatbox_'+user_id+' .chatboxcontent').css('display','none');
+			$('#chatbox_'+user_id+' .chatboxinput').css('display','none');
+		}
+	}
+}
+
 /**
  * Creates a div
  */
 function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage)
 {
-    var oldChatBox = $("#chatbox_"+user_id);
+	var oldChatBox = $("#chatbox_"+user_id);
 	if (oldChatBox.length > 0) {
 		if (oldChatBox.css('display') == 'none') {
 			oldChatBox.css('display','block');
@@ -378,10 +591,11 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage
 		}
 
 		$("#chatbox_"+user_id+" .chatboxtextarea").focus();
+
 		return;
 	}
 
-	user_is_online = return_online_user(user_id, online, userImage);
+	var user_is_online = return_online_user(user_id, online, userImage);
 
 	var chatbox = $('<div>')
 		.attr({
@@ -394,10 +608,10 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage
 		.addClass('chatboxhead')
 		.append(user_is_online);
 
-    $('<div>')
-        .addClass('chatimage')
-        .append('<img src="'+userImage+'"/>')
-        .appendTo(chatboxHead);
+	$('<div>')
+		.addClass('chatimage')
+		.append('<img src="'+userImage+'"/>')
+		.appendTo(chatboxHead);
 
 	$('<div>')
 		.addClass('chatboxtitle')
@@ -408,23 +622,25 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage
 		.addClass('chatboxoptions')
 		.appendTo(chatboxHead);
 
- 	if (!!Modernizr.prefixed('RTCPeerConnection', window) &&
-        (online === '1' || online === 1)
-    ) {
-		$('<a>')
-			.addClass('btn btn-xs ajax')
-			.attr({
-				href: ajax_url + '?action=create_room&to=' + user_id
-			})
-            .data({
-                title: '<em class="fa fa-video-camera"></em>',
-                size: 'sm'
-            })
-            .on('click', function () {
-                $(this).data('title', $('.chatboxtitle').text());
-            })
-			.html('<em class="fa fa-video-camera"></em>')
-			.appendTo(chatboxoptions);
+	if (!hide_chat_video) {
+		if (!!Modernizr.prefixed('RTCPeerConnection', window) &&
+			(online === '1' || online === 1)
+		) {
+			/*$('<a>')
+				.addClass('btn btn-xs ajax')
+				.attr({
+					href: ajax_url + '?action=create_room&to=' + user_id
+				})
+				.data({
+					title: '<em class="fa fa-video-camera"></em>',
+					size: 'sm'
+				})
+				.on('click', function () {
+					$(this).data('title', $('.chatboxtitle').text());
+				})
+				.html('<em class="fa fa-video-camera"></em>')
+				.appendTo(chatboxoptions);*/
+		}
 	}
 
 	$('<a>')
@@ -483,19 +699,18 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage
 
 	if (minimizeChatBox == 1) {
 		minimizedChatBoxes = new Array();
-
-		if ($.cookie('chatbox_minimized')) {
-			minimizedChatBoxes = $.cookie('chatbox_minimized').split(/\|/);
+		if (Cookies.get('chatbox_minimized')) {
+			minimizedChatBoxes = Cookies.getJSON('chatbox_minimized');
 		}
 		minimize = 0;
-		for (j=0;j<minimizedChatBoxes.length;j++) {
+		for (j = 0; j < minimizedChatBoxes.length; j++) {
 			if (minimizedChatBoxes[j] == user_id) {
 				minimize = 1;
 			}
 		}
 
 		if (minimize == 1) {
-                        $('.togglelink').html('<em class="fa fa-toggle-up"></em>');
+			$('.togglelink').html('<em class="fa fa-toggle-up"></em>');
 			$('#chatbox_'+user_id+' .chatboxcontent').css('display','none');
 			$('#chatbox_'+user_id+' .chatboxinput').css('display','none');
 		}
@@ -518,15 +733,15 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage
 			$("#chatbox_"+user_id+" .chatboxtextarea").focus();
 		}
 	});
-	$("#chatbox_"+user_id).show();
 
+	$("#chatbox_"+user_id).show();
 	$("#chatbox_"+user_id+" .chatboxcontent").scroll(function () {
-        var iCurScrollPos = $(this).scrollTop();
-        if (iCurScrollPos == 0) {
-            getMoreItems(user_id);
-            return false;
-        }
-    });
+		var iCurScrollPos = $(this).scrollTop();
+		if (iCurScrollPos == 0) {
+			getMoreItems(user_id);
+			return false;
+		}
+	});
 }
 
 /**
@@ -535,38 +750,40 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online, userImage
  */
 function getMoreItems(userId, scrollType)
 {
-    var visibleMessages = $("#chatbox_"+userId+" .chatboxcontent").find('div').length;
-    $.ajax({
+	var visibleMessages = $("#chatbox_"+userId+" .chatboxcontent").find('.chatbox-common').length;
+	$.ajax({
 		url: ajax_url+"?action=get_previous_messages&user_id="+userId+"&visible_messages="+visibleMessages,
 		cache: false,
 		dataType: "json",
 		success: function(items) {
-            $.each(items, function(i, item) {
-                if (item) {
-                    if ($("#chatbox_"+userId).css('display') == 'none') {
-                        $("#chatbox_"+userId).css('display','block');
-                        restructureChatBoxes();
-                    }
-                    var chatBubble = createChatBubble(userId, item);
-                    $("#chatbox_"+userId+" .chatboxcontent").prepend(chatBubble);
-
-                    if ($('#chatbox_'+userId+' .chatboxcontent').css('display') == 'none') {
-                        $('#chatbox_'+userId+' .chatboxhead').toggleClass('chatboxblink');
-                    }
+			console.log(items);
+			items = items.reverse();
+			$.each(items, function(i, item) {
+				console.log(i);
+				if (item) {
+					if ($("#chatbox_"+userId).css('display') == 'none') {
+						$("#chatbox_"+userId).css('display','block');
+						restructureChatBoxes();
+					}
+					var chatBubble = createChatBubble(userId, item, 'prepend');
+					//$("#chatbox_"+userId+" .chatboxcontent").prepend(chatBubble);
 
-                    // When using scroll set the scroll window to the first
-                    var scrollValue = 10;
-                    if (scrollType === 'last') {
-                        // When loading for the first time show the last msg
-                        scrollValue = $("#chatbox_"+userId+" .chatboxcontent").height();
-                    }
+					if ($('#chatbox_'+userId+' .chatboxcontent').css('display') == 'none') {
+						$('#chatbox_'+userId+' .chatboxhead').toggleClass('chatboxblink');
+					}
 
-                    $("#chatbox_"+userId+" .chatboxcontent").scrollTop(
-                        scrollValue
-                    );
+					// When using scroll set the scroll window to the first
+					var scrollValue = 10;
+					if (scrollType === 'last') {
+						// When loading for the first time show the last msg
+						//scrollValue = $("#chatbox_"+userId+" .chatboxcontent").height();
+					}
 
-                }
-            });
+					/*$("#chatbox_"+userId+" .chatboxcontent").scrollTop(
+						scrollValue
+					);*/
+				}
+			});
 		}
 	}); //ajax
 }
@@ -590,6 +807,7 @@ function return_online_user(user_id, status, userImage)
 		new_div.html(offline_button);
 	}
 	div_wrapper.append(new_div);
+
 	return div_wrapper.html();
 }
 
@@ -607,39 +825,75 @@ function update_online_user(user_id, status)
 	}
 }
 
+/**
+ * @param user_id
+ */
 function toggleChatBoxGrowth(user_id)
 {
 	if ($('#chatbox_'+user_id+' .chatboxcontent').css('display') == 'none') {
+		// Show box
 		var minimizedChatBoxes = new Array();
-		if ($.cookie('chatbox_minimized')) {
-			minimizedChatBoxes = $.cookie('chatbox_minimized').split(/\|/);
+		if (Cookies.get('chatbox_minimized')) {
+			minimizedChatBoxes = Cookies.getJSON('chatbox_minimized');
 		}
 
-		var newCookie = '';
-		for (i=0;i<minimizedChatBoxes.length;i++) {
+		var newCookie = new Array();
+		for (var i = 0; i < minimizedChatBoxes.length; i++) {
 			if (minimizedChatBoxes[i] != user_id) {
-				newCookie += user_id+'|';
+				newCookie.push(minimizedChatBoxes[i]);
 			}
 		}
 
-		newCookie = newCookie.slice(0, -1);
-		$.cookie('chatbox_minimized', newCookie);
+		Cookies.set('chatbox_minimized', newCookie);
 		$('#chatbox_'+user_id+' .chatboxcontent').css('display','block');
 		$('#chatbox_'+user_id+' .chatboxinput').css('display','block');
-		$("#chatbox_"+user_id+" .chatboxcontent").scrollTop($("#chatbox_"+user_id+" .chatboxcontent")[0].scrollHeight);
-        $('.togglelink').html('<em class="fa fa-toggle-down"></em>');
+		//$("#chatbox_"+user_id+" .chatboxcontent").scrollTop($("#chatbox_"+user_id+" .chatboxcontent")[0].scrollHeight);
+		$('.togglelink').html('<em class="fa fa-toggle-down"></em>');
 	} else {
-		var newCookie = user_id;
-		if ($.cookie('chatbox_minimized')) {
-			newCookie += '|'+$.cookie('chatbox_minimized');
+		// hide box
+		if (Cookies.get('chatbox_minimized')) {
+			newCookie = Cookies.getJSON('chatbox_minimized');
+            if ($.isArray(newCookie)) {
+                for (i = 0; i < newCookie.length; i++) {
+                    if (newCookie[i] == user_id) {
+                        newCookie.splice(i, 1);
+                    }
+                }
+                newCookie.push(user_id);
+            } else {
+                newCookie = new Array();
+                newCookie.push(user_id);
+            }
+
+			Cookies.set('chatbox_minimized', newCookie);
 		}
-		$.cookie('chatbox_minimized',newCookie);
+
 		$('#chatbox_'+user_id+' .chatboxcontent').css('display','none');
 		$('#chatbox_'+user_id+' .chatboxinput').css('display','none');
-        $('.togglelink').html('<em class="fa fa-toggle-up"></em>');
+		$('.togglelink').html('<em class="fa fa-toggle-up"></em>');
 	}
 }
 
+function checkMessageStatus(messageId, chatBox)
+{
+	$.ajax({
+		type: 'GET',
+		dataType: 'json',
+		url: ajax_url + "?action=get_message_status",
+		data: {
+			message_id: messageId
+		},
+		success: function (messageInfo) {
+			if (messageInfo) {
+				if (messageInfo.recd == 1) {
+					$('#message_id_' + messageId + ' .chatbox_checks ').html(doubleCheck);
+					clearInterval(intervals[messageId]);
+				}
+			}
+		}
+	});
+}
+
 /**
  * Sending message
  * @param event
@@ -658,26 +912,31 @@ function checkChatBoxInputKey(event, chatboxtextarea, user_id)
 		$(chatboxtextarea).css('height','44px');
 
 		if (message != '') {
-            $.post(ajax_url + "?action=sendchat", {
-                to: user_id,
-                message: message
-            }, function (data) {
-                if (data == 1) {
-                    message = message.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;");
-                    var item = {
-                        username: username,
-                        date: moment().unix(),
-                        f: currentUserId,
-                        m: message
-                    };
-                    var bubble = createChatBubble(user_id, item);
-                    $("#chatbox_" + user_id + " .chatboxcontent").append(bubble);
-                    $("#chatbox_" + user_id + " .chatboxcontent").scrollTop(
-                        $("#chatbox_" + user_id + " .chatboxcontent")[0].scrollHeight
-                    );
-                } else {
-                    $("#chatbox_" + user_id + " .chatboxcontent").append('<i class="fa fa-exclamation-triangle" aria-hidden="true"></i><br />');
-                }
+			$.post(ajax_url + "?action=sendchat", {
+				to: user_id,
+				message: message
+			}, function (messageId) {
+				if (messageId > 0) {
+					message = message.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;");
+					var item = {
+						from_user_info : {id: currentUserId, complete_name: 'me'},
+						username: username,
+						date: moment().unix(),
+						f: currentUserId,
+						message: message,
+						id: messageId
+					};
+					var bubble = createChatBubble(user_id, item);
+					//$("#chatbox_" + user_id + " .chatboxcontent").append(bubble);
+					$("#chatbox_" + user_id + " .chatboxcontent").scrollTop(
+						$("#chatbox_" + user_id + " .chatboxcontent")[0].scrollHeight
+					);
+
+					intervals[messageId] = setInterval(checkMessageStatus, chatHeartbeatTime, messageId);
+				} else {
+					$("#chatbox_" + user_id + " .chatboxcontent").
+                    append('<i class="fa fa-exclamation-triangle" aria-hidden="true"></i><br />');
+				}
 			});
 		}
 		chatHeartbeatTime = minChatHeartbeat;
@@ -699,54 +958,3 @@ function checkChatBoxInputKey(event, chatboxtextarea, user_id)
 		$(chatboxtextarea).css('overflow','auto');
 	}
 }
-
-/**
- * Cookie plugin
- *
- * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- *
- */
-jQuery.cookie = function(name, value, options) {
-    if (typeof value != 'undefined') { // name and value given, set cookie
-        options = options || {};
-        if (value === null) {
-            value = '';
-            options.expires = -1;
-        }
-        var expires = '';
-        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
-            var date;
-            if (typeof options.expires == 'number') {
-                date = new Date();
-                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
-            } else {
-                date = options.expires;
-            }
-            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
-        }
-        // CAUTION: Needed to parenthesize options.path and options.domain
-        // in the following expressions, otherwise they evaluate to undefined
-        // in the packed version for some reason...
-        var path = options.path ? '; path=' + (options.path) : '';
-        var domain = options.domain ? '; domain=' + (options.domain) : '';
-        var secure = options.secure ? '; secure' : '';
-        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
-    } else { // only name given, get cookie
-        var cookieValue = null;
-        if (document.cookie && document.cookie != '') {
-            var cookies = document.cookie.split(';');
-            for (var i = 0; i < cookies.length; i++) {
-                var cookie = jQuery.trim(cookies[i]);
-                // Does this cookie string begin with the name we want?
-                if (cookie.substring(0, name.length + 1) == (name + '=')) {
-                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
-                    break;
-                }
-            }
-        }
-        return cookieValue;
-    }
-};

+ 4 - 0
main/inc/lib/javascript/chat/video.php

@@ -40,6 +40,10 @@ $htmlHeadXtra[] = '<script type="text/javascript" src="'
 
 $navigator = api_get_navigator();
 
+Display::addFlash(
+    Display::return_message(get_lang('FeatureDisabledBecauseOfUnmaintainedThirdPartyLibraries'), 'error')
+);
+
 $template = new Template();
 $template->assign('room_name', $chatVideo->getRoomName());
 $template->assign('chat_user', $chatUser);

+ 5 - 8
main/inc/lib/javascript/hotspot/js/hotspot.js

@@ -4,6 +4,7 @@ window.HotspotQuestion = (function () {
             this.attributes = attributes;
             this.id = 0;
             this.name = '';
+
             this.changeEvent = null;
         };
         HotspotModel.prototype.set = function (key, value) {
@@ -576,7 +577,6 @@ window.HotspotQuestion = (function () {
                         currentHotspot.set('centerY', 0);
                         currentHotspot.set('radiusX', 0);
                         currentHotspot.set('radiusY', 0);
-
                         return;
                     }
                 })
@@ -764,11 +764,9 @@ window.HotspotQuestion = (function () {
                         default:
                             hotspot = SquareModel.decode(hotspotInfo);
                             break;
-
                         case 'circle':
                             hotspot = EllipseModel.decode(hotspotInfo);
                             break;
-
                         case 'poly':
                             hotspot = PolygonModel.decode(hotspotInfo);
                             break;
@@ -891,9 +889,7 @@ window.HotspotQuestion = (function () {
                 })
                 .on('mousedown', 'circle, text', function (e) {
                     e.preventDefault();
-
                     isMoving = true;
-
                     if (e.target.tagName === 'circle') {
                         //Hack to move correctly the hot spots if there are more than one HS question in same page
                         answerIndex = $(e.target).next().html();
@@ -1141,16 +1137,14 @@ window.HotspotQuestion = (function () {
                     modifyAnswers: parseInt(config.questionId)
                 });
                 break;
-
             case 'user':
                 xhrQuestion = $.getJSON(config.relPath + 'exercise/hotspot_actionscript.as.php?' + webCidReq, {
                     modifyAnswers: parseInt(config.questionId),
                     exe_id: parseInt(config.exerciseId)
                 });
                 break;
-
             case 'solution':
-            //no break
+                //no break
             case 'preview':
                 xhrQuestion = $.getJSON(config.relPath + 'exercise/hotspot_answers.as.php?' + webCidReq, {
                     modifyAnswers: parseInt(config.questionId),
@@ -1560,7 +1554,9 @@ window.DelineationQuestion = (function () {
             this.el.appendChild(imageSvg);
 
             this.renderDelineation();
+
             var isDrawing = false;
+
             var contextMenu = new ContextMenu();
             contextMenu.onHide(function () {
                 var answerInput = $('hotspot[' + config.questionId + '][1]'),
@@ -1698,6 +1694,7 @@ window.DelineationQuestion = (function () {
         var image = new Image();
         image.onload = function () {
             $(config.selector).html('');
+
             var polygonCollection = new PolygonCollection(),
                 previewSvg = new AdminSvg(polygonCollection, image);
 

+ 25 - 0
main/inc/lib/javascript/jquery.nocopypaste.js

@@ -0,0 +1,25 @@
+/**
+ * When included, this snippet prevents contextual menus and keystrokes that
+ * make it possible to cut/paste/copy text from the page.
+ * This is useful for very secure exams.
+ * @author Alberto Torreblanca
+ */
+$(document).ready(function(){
+    $(document).on("cut copy paste contextmenu",function(e) {
+        e.preventDefault();
+    });
+    $(document).keydown(function(e) {
+        var forbiddenKeys = new Array('c', 'x', 'v', 'p', 's');
+        var keyCode = (e.keyCode) ? e.keyCode : e.which;
+        var isCtrl;
+        isCtrl = e.ctrlKey
+        if (isCtrl) {
+            for (i = 0; i < forbiddenKeys.length; i++) {
+                if (forbiddenKeys[i] == String.fromCharCode(keyCode).toLowerCase()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    });
+});

+ 1128 - 1128
main/inc/lib/nusoap/class.soap_server.php

@@ -1,1128 +1,1128 @@
-<?php
-
-/**
-*
-* nusoap_server allows the user to create a SOAP server
-* that is capable of receiving messages and returning responses
-*
-* @author   Dietrich Ayala <dietrich@ganx4.com>
-* @author   Scott Nichol <snichol@users.sourceforge.net>
-* @version  $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $
-* @access   public
-*/
-class nusoap_server extends nusoap_base
-{
-	/**
-	 * HTTP headers of request
-	 * @var array
-	 * @access private
-	 */
-	var $headers = array();
-	/**
-	 * HTTP request
-	 * @var string
-	 * @access private
-	 */
-	var $request = '';
-	/**
-	 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
-	 * @var string
-	 * @access public
-	 */
-	var $requestHeaders = '';
-	/**
-	 * SOAP Headers from request (parsed)
-	 * @var mixed
-	 * @access public
-	 */
-	var $requestHeader = NULL;
-	/**
-	 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
-	 * @var string
-	 * @access public
-	 */
-	var $document = '';
-	/**
-	 * SOAP payload for request (text)
-	 * @var string
-	 * @access public
-	 */
-	var $requestSOAP = '';
-	/**
-	 * requested method namespace URI
-	 * @var string
-	 * @access private
-	 */
-	var $methodURI = '';
-	/**
-	 * name of method requested
-	 * @var string
-	 * @access private
-	 */
-	var $methodname = '';
-	/**
-	 * method parameters from request
-	 * @var array
-	 * @access private
-	 */
-	var $methodparams = array();
-	/**
-	 * SOAP Action from request
-	 * @var string
-	 * @access private
-	 */
-	var $SOAPAction = '';
-	/**
-	 * character set encoding of incoming (request) messages
-	 * @var string
-	 * @access public
-	 */
-	var $xml_encoding = '';
-	/**
-	 * toggles whether the parser decodes element content w/ utf8_decode()
-	 * @var boolean
-	 * @access public
-	 */
-    var $decode_utf8 = true;
-
-	/**
-	 * HTTP headers of response
-	 * @var array
-	 * @access public
-	 */
-	var $outgoing_headers = array();
-	/**
-	 * HTTP response
-	 * @var string
-	 * @access private
-	 */
-	var $response = '';
-	/**
-	 * SOAP headers for response (text or array of soapval or associative array)
-	 * @var mixed
-	 * @access public
-	 */
-	var $responseHeaders = '';
-	/**
-	 * SOAP payload for response (text)
-	 * @var string
-	 * @access private
-	 */
-	var $responseSOAP = '';
-	/**
-	 * method return value to place in response
-	 * @var mixed
-	 * @access private
-	 */
-	var $methodreturn = false;
-	/**
-	 * whether $methodreturn is a string of literal XML
-	 * @var boolean
-	 * @access public
-	 */
-	var $methodreturnisliteralxml = false;
-	/**
-	 * SOAP fault for response (or false)
-	 * @var mixed
-	 * @access private
-	 */
-	var $fault = false;
-	/**
-	 * text indication of result (for debugging)
-	 * @var string
-	 * @access private
-	 */
-	var $result = 'successful';
-
-	/**
-	 * assoc array of operations => opData; operations are added by the register()
-	 * method or by parsing an external WSDL definition
-	 * @var array
-	 * @access private
-	 */
-	var $operations = array();
-	/**
-	 * wsdl instance (if one)
-	 * @var mixed
-	 * @access private
-	 */
-	var $wsdl = false;
-	/**
-	 * URL for WSDL (if one)
-	 * @var mixed
-	 * @access private
-	 */
-	var $externalWSDLURL = false;
-	/**
-	 * whether to append debug to response as XML comment
-	 * @var boolean
-	 * @access public
-	 */
-	var $debug_flag = false;
-
-
-	/**
-	* constructor
-    * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
-	*
-    * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
-	* @access   public
-	*/
-	function __construct($wsdl=false)
-    {
-		parent::__construct();
-		// turn on debugging?
-		global $debug;
-		global $HTTP_SERVER_VARS;
-
-		if (isset($_SERVER)) {
-			$this->debug("_SERVER is defined:");
-			$this->appendDebug($this->varDump($_SERVER));
-		} elseif (isset($HTTP_SERVER_VARS)) {
-			$this->debug("HTTP_SERVER_VARS is defined:");
-			$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
-		} else {
-			$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
-		}
-
-		if (isset($debug)) {
-			$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
-			$this->debug_flag = $debug;
-		} elseif (isset($_SERVER['QUERY_STRING'])) {
-			$qs = explode('&', $_SERVER['QUERY_STRING']);
-			foreach ($qs as $v) {
-				if (substr($v, 0, 6) == 'debug=') {
-					$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
-					$this->debug_flag = substr($v, 6);
-				}
-			}
-		} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
-			$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
-			foreach ($qs as $v) {
-				if (substr($v, 0, 6) == 'debug=') {
-					$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
-					$this->debug_flag = substr($v, 6);
-				}
-			}
-		}
-
-		// wsdl
-		if($wsdl){
-			$this->debug("In nusoap_server, WSDL is specified");
-			if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
-				$this->wsdl = $wsdl;
-                $this->wsdl->soap_defencoding = $this->soap_defencoding;
-				$this->externalWSDLURL = $this->wsdl->wsdl;
-				$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
-			} else {
-				$this->debug('Create wsdl from ' . $wsdl);
-				$this->wsdl = new wsdl($wsdl);
-                $this->wsdl->soap_defencoding = $this->soap_defencoding;
-				$this->externalWSDLURL = $wsdl;
-			}
-			$this->appendDebug($this->wsdl->getDebug());
-			$this->wsdl->clearDebug();
-			if($err = $this->wsdl->getError()){
-				die('WSDL ERROR: '.$err);
-			}
-		}
-	}
-
-	/**
-	* processes request and returns response
-	*
-	* @param    string $data usually is the value of $HTTP_RAW_POST_DATA
-	* @access   public
-	*/
-	function service($data){
-		global $HTTP_SERVER_VARS;
-
-		if (isset($_SERVER['REQUEST_METHOD'])) {
-			$rm = $_SERVER['REQUEST_METHOD'];
-		} elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
-			$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
-		} else {
-			$rm = '';
-		}
-
-		if (isset($_SERVER['QUERY_STRING'])) {
-			$qs = $_SERVER['QUERY_STRING'];
-		} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
-			$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
-		} else {
-			$qs = '';
-		}
-		$this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
-
-		if ($rm == 'POST') {
-			$this->debug("In service, invoke the request");
-			$this->parse_request($data);
-			if (! $this->fault) {
-				$this->invoke_method();
-			}
-			if (! $this->fault) {
-				$this->serialize_return();
-			}
-			$this->send_response();
-		} elseif (preg_match('/wsdl/', $qs) ){
-			$this->debug("In service, this is a request for WSDL");
-			if ($this->externalWSDLURL){
-              if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
-				$this->debug("In service, re-direct for WSDL");
-				header('Location: '.$this->externalWSDLURL);
-              } else { // assume file
-				$this->debug("In service, use file passthru for WSDL");
-                header("Content-Type: text/xml\r\n");
-				$pos = strpos($this->externalWSDLURL, "file://");
-				if ($pos === false) {
-					$filename = $this->externalWSDLURL;
-				} else {
-					$filename = substr($this->externalWSDLURL, $pos + 7);
-				}
-                $fp = fopen($this->externalWSDLURL, 'r');
-                fpassthru($fp);
-              }
-			} elseif ($this->wsdl) {
-				$this->debug("In service, serialize WSDL");
-                header("Content-Type: text/xml; charset=".$this->soap_defencoding."\r\n");
-				print $this->wsdl->serialize($this->debug_flag);
-				if ($this->debug_flag) {
-					$this->debug('wsdl:');
-					$this->appendDebug($this->varDump($this->wsdl));
-					print $this->getDebugAsXMLComment();
-				}
-			} else {
-				$this->debug("In service, there is no WSDL");
-                header("Content-Type: text/html; charset=".$this->soap_defencoding."\r\n");
-				print "This service does not provide WSDL";
-			}
-		} elseif ($this->wsdl) {
-			$this->debug("In service, return Web description");
-			print $this->wsdl->webDescription();
-		} else {
-			$this->debug("In service, no Web description");
-			header("Content-Type: text/html; charset=ISO-8859-1\r\n");
-			print "This service does not provide a Web description";
-		}
-	}
-
-	/**
-	* parses HTTP request headers.
-	*
-	* The following fields are set by this function (when successful)
-	*
-	* headers
-	* request
-	* xml_encoding
-	* SOAPAction
-	*
-	* @access   private
-	*/
-	function parse_http_headers() {
-		global $HTTP_SERVER_VARS;
-
-		$this->request = '';
-		$this->SOAPAction = '';
-		if(function_exists('getallheaders')){
-			$this->debug("In parse_http_headers, use getallheaders");
-			$headers = getallheaders();
-			foreach($headers as $k=>$v){
-				$k = strtolower($k);
-				$this->headers[$k] = $v;
-				$this->request .= "$k: $v\r\n";
-				$this->debug("$k: $v");
-			}
-			// get SOAPAction header
-			if(isset($this->headers['soapaction'])){
-				$this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
-			}
-			// get the character encoding of the incoming request
-			if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
-				$enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
-				if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
-					$this->xml_encoding = strtoupper($enc);
-				} else {
-					$this->xml_encoding = 'US-ASCII';
-				}
-			} else {
-				// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
-				$this->xml_encoding = 'ISO-8859-1';
-			}
-		} elseif(isset($_SERVER) && is_array($_SERVER)){
-			$this->debug("In parse_http_headers, use _SERVER");
-			foreach ($_SERVER as $k => $v) {
-				if (substr($k, 0, 5) == 'HTTP_') {
-					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
-				} else {
-					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
-				}
-				if ($k == 'soapaction') {
-					// get SOAPAction header
-					$k = 'SOAPAction';
-					$v = str_replace('"', '', $v);
-					$v = str_replace('\\', '', $v);
-					$this->SOAPAction = $v;
-				} else if ($k == 'content-type') {
-					// get the character encoding of the incoming request
-					if (strpos($v, '=')) {
-						$enc = substr(strstr($v, '='), 1);
-						$enc = str_replace('"', '', $enc);
-						$enc = str_replace('\\', '', $enc);
-						if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
-							$this->xml_encoding = strtoupper($enc);
-						} else {
-							$this->xml_encoding = 'US-ASCII';
-						}
-					} else {
-						// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
-						$this->xml_encoding = 'ISO-8859-1';
-					}
-				}
-				$this->headers[$k] = $v;
-				$this->request .= "$k: $v\r\n";
-				$this->debug("$k: $v");
-			}
-		} elseif (is_array($HTTP_SERVER_VARS)) {
-			$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
-			foreach ($HTTP_SERVER_VARS as $k => $v) {
-				if (substr($k, 0, 5) == 'HTTP_') {
-					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); 	                                         $k = strtolower(substr($k, 5));
-				} else {
-					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); 	                                         $k = strtolower($k);
-				}
-				if ($k == 'soapaction') {
-					// get SOAPAction header
-					$k = 'SOAPAction';
-					$v = str_replace('"', '', $v);
-					$v = str_replace('\\', '', $v);
-					$this->SOAPAction = $v;
-				} else if ($k == 'content-type') {
-					// get the character encoding of the incoming request
-					if (strpos($v, '=')) {
-						$enc = substr(strstr($v, '='), 1);
-						$enc = str_replace('"', '', $enc);
-						$enc = str_replace('\\', '', $enc);
-						if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
-							$this->xml_encoding = strtoupper($enc);
-						} else {
-							$this->xml_encoding = 'US-ASCII';
-						}
-					} else {
-						// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
-						$this->xml_encoding = 'ISO-8859-1';
-					}
-				}
-				$this->headers[$k] = $v;
-				$this->request .= "$k: $v\r\n";
-				$this->debug("$k: $v");
-			}
-		} else {
-			$this->debug("In parse_http_headers, HTTP headers not accessible");
-			$this->setError("HTTP headers not accessible");
-		}
-	}
-
-	/**
-	* parses a request
-	*
-	* The following fields are set by this function (when successful)
-	*
-	* headers
-	* request
-	* xml_encoding
-	* SOAPAction
-	* request
-	* requestSOAP
-	* methodURI
-	* methodname
-	* methodparams
-	* requestHeaders
-	* document
-	*
-	* This sets the fault field on error
-	*
-	* @param    string $data XML string
-	* @access   private
-	*/
-	function parse_request($data='') {
-		$this->debug('entering parse_request()');
-		$this->parse_http_headers();
-		$this->debug('got character encoding: '.$this->xml_encoding);
-		// uncompress if necessary
-		if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
-			$this->debug('got content encoding: ' . $this->headers['content-encoding']);
-			if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
-		    	// if decoding works, use it. else assume data wasn't gzencoded
-				if (function_exists('gzuncompress')) {
-					if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
-						$data = $degzdata;
-					} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
-						$data = $degzdata;
-					} else {
-						$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
-						return;
-					}
-				} else {
-					$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
-					return;
-				}
-			}
-		}
-		$this->request .= "\r\n".$data;
-		$data = $this->parseRequest($this->headers, $data);
-		$this->requestSOAP = $data;
-		$this->debug('leaving parse_request');
-	}
-
-	/**
-	* invokes a PHP function for the requested SOAP method
-	*
-	* The following fields are set by this function (when successful)
-	*
-	* methodreturn
-	*
-	* Note that the PHP function that is called may also set the following
-	* fields to affect the response sent to the client
-	*
-	* responseHeaders
-	* outgoing_headers
-	*
-	* This sets the fault field on error
-	*
-	* @access   private
-	*/
-	function invoke_method() {
-		$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
-
-		//
-		// if you are debugging in this area of the code, your service uses a class to implement methods,
-		// you use SOAP RPC, and the client is .NET, please be aware of the following...
-		// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
-		// method name.  that is fine for naming the .NET methods.  it is not fine for properly constructing
-		// the XML request and reading the XML response.  you need to add the RequestElementName and
-		// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
-		// generates for the method.  these parameters are used to specify the correct XML element names
-		// for .NET to use, i.e. the names with the '.' in them.
-		//
-		$orig_methodname = $this->methodname;
-		if ($this->wsdl) {
-			if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
-				$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
-				$this->appendDebug('opData=' . $this->varDump($this->opData));
-			} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
-				// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
-				$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
-				$this->appendDebug('opData=' . $this->varDump($this->opData));
-				$this->methodname = $this->opData['name'];
-			} else {
-				$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
-				$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
-				return;
-			}
-		} else {
-			$this->debug('in invoke_method, no WSDL to validate method');
-		}
-
-		// if a . is present in $this->methodname, we see if there is a class in scope,
-		// which could be referred to. We will also distinguish between two deliminators,
-		// to allow methods to be called a the class or an instance
-		if (strpos($this->methodname, '..') > 0) {
-			$delim = '..';
-		} else if (strpos($this->methodname, '.') > 0) {
-			$delim = '.';
-		} else {
-			$delim = '';
-		}
-		$this->debug("in invoke_method, delim=$delim");
-
-		$class = '';
-		$method = '';
-		if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
-			$try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
-			if (class_exists($try_class)) {
-				// get the class and method name
-				$class = $try_class;
-				$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
-				$this->debug("in invoke_method, class=$class method=$method delim=$delim");
-			} else {
-				$this->debug("in invoke_method, class=$try_class not found");
-			}
-		} else {
-			$try_class = '';
-			$this->debug("in invoke_method, no class to try");
-		}
-
-		// does method exist?
-		if ($class == '') {
-			if (!function_exists($this->methodname)) {
-				$this->debug("in invoke_method, function '$this->methodname' not found!");
-				$this->result = 'fault: method not found';
-				$this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
-				return;
-			}
-		} else {
-			$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
-			if (!in_array($method_to_compare, get_class_methods($class))) {
-				$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
-				$this->result = 'fault: method not found';
-				$this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
-				return;
-			}
-		}
-
-		// evaluate message, getting back parameters
-		// verify that request parameters match the method's signature
-		if(! $this->verify_method($this->methodname,$this->methodparams)){
-			// debug
-			$this->debug('ERROR: request not verified against method signature');
-			$this->result = 'fault: request failed validation against method signature';
-			// return fault
-			$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
-			return;
-		}
-
-		// if there are parameters to pass
-		$this->debug('in invoke_method, params:');
-		$this->appendDebug($this->varDump($this->methodparams));
-		$this->debug("in invoke_method, calling '$this->methodname'");
-		if (!function_exists('call_user_func_array')) {
-			if ($class == '') {
-				$this->debug('in invoke_method, calling function using eval()');
-				$funcCall = "\$this->methodreturn = $this->methodname(";
-			} else {
-				if ($delim == '..') {
-					$this->debug('in invoke_method, calling class method using eval()');
-					$funcCall = "\$this->methodreturn = ".$class."::".$method."(";
-				} else {
-					$this->debug('in invoke_method, calling instance method using eval()');
-					// generate unique instance name
-					$instname = "\$inst_".time();
-					$funcCall = $instname." = new ".$class."(); ";
-					$funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
-				}
-			}
-			if ($this->methodparams) {
-				foreach ($this->methodparams as $param) {
-					if (is_array($param) || is_object($param)) {
-						$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
-						return;
-					}
-					$funcCall .= "\"$param\",";
-				}
-				$funcCall = substr($funcCall, 0, -1);
-			}
-			$funcCall .= ');';
-			$this->debug('in invoke_method, function call: '.$funcCall);
-			@eval($funcCall);
-		} else {
-			if ($class == '') {
-				$this->debug('in invoke_method, calling function using call_user_func_array()');
-				$call_arg = "$this->methodname";	// straight assignment changes $this->methodname to lower case after call_user_func_array()
-			} elseif ($delim == '..') {
-				$this->debug('in invoke_method, calling class method using call_user_func_array()');
-				$call_arg = array ($class, $method);
-			} else {
-				$this->debug('in invoke_method, calling instance method using call_user_func_array()');
-				$instance = new $class ();
-				$call_arg = array(&$instance, $method);
-			}
-			if (is_array($this->methodparams)) {
-				$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
-			} else {
-				$this->methodreturn = call_user_func_array($call_arg, array());
-			}
-		}
-        $this->debug('in invoke_method, methodreturn:');
-        $this->appendDebug($this->varDump($this->methodreturn));
-		$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
-	}
-
-	/**
-	* serializes the return value from a PHP function into a full SOAP Envelope
-	*
-	* The following fields are set by this function (when successful)
-	*
-	* responseSOAP
-	*
-	* This sets the fault field on error
-	*
-	* @access   private
-	*/
-	function serialize_return() {
-		$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
-		// if fault
-		if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
-			$this->debug('got a fault object from method');
-			$this->fault = $this->methodreturn;
-			return;
-		} elseif ($this->methodreturnisliteralxml) {
-			$return_val = $this->methodreturn;
-		// returned value(s)
-		} else {
-			$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
-			$this->debug('serializing return value');
-			if($this->wsdl){
-				$opParams = "";
-				if (sizeof($this->opData['output']['parts']) > 1) {
-					$this->debug('more than one output part, so use the method return unchanged');
-			    	$opParams = $this->methodreturn;
-			    } elseif (sizeof($this->opData['output']['parts']) == 1) {
-					$this->debug('exactly one output part, so wrap the method return in a simple array');
-					// TODO: verify that it is not already wrapped!
-			    	//foreach ($this->opData['output']['parts'] as $name => $type) {
-					//	$this->debug('wrap in element named ' . $name);
-			    	//}
-			    	$opParams = array($this->methodreturn);
-			    }
-			    $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
-			    $this->appendDebug($this->wsdl->getDebug());
-			    $this->wsdl->clearDebug();
-				if($errstr = $this->wsdl->getError()){
-					$this->debug('got wsdl error: '.$errstr);
-					$this->fault('SOAP-ENV:Server', 'unable to serialize result');
-					return;
-				}
-			} else {
-				if (isset($this->methodreturn)) {
-					$return_val = $this->serialize_val($this->methodreturn, 'return');
-				} else {
-					$return_val = '';
-					$this->debug('in absence of WSDL, assume void return for backward compatibility');
-				}
-			}
-		}
-		$this->debug('return value:');
-		$this->appendDebug($this->varDump($return_val));
-
-		$this->debug('serializing response');
-		if ($this->wsdl) {
-			$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
-			if ($this->opData['style'] == 'rpc') {
-				$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
-				if ($this->opData['output']['use'] == 'literal') {
-					// http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
-					if ($this->methodURI) {
-						$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
-					} else {
-						$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
-					}
-				} else {
-					if ($this->methodURI) {
-						$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
-					} else {
-						$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
-					}
-				}
-			} else {
-				$this->debug('style is not rpc for serialization: assume document');
-				$payload = $return_val;
-			}
-		} else {
-			$this->debug('do not have WSDL for serialization: assume rpc/encoded');
-			$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
-		}
-		$this->result = 'successful';
-		if($this->wsdl){
-			//if($this->debug_flag){
-            	$this->appendDebug($this->wsdl->getDebug());
-            //	}
-			if (isset($this->opData['output']['encodingStyle'])) {
-				$encodingStyle = $this->opData['output']['encodingStyle'];
-			} else {
-				$encodingStyle = '';
-			}
-			// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
-			$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
-		} else {
-			$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
-		}
-		$this->debug("Leaving serialize_return");
-	}
-
-	/**
-	* sends an HTTP response
-	*
-	* The following fields are set by this function (when successful)
-	*
-	* outgoing_headers
-	* response
-	*
-	* @access   private
-	*/
-	function send_response() {
-		$this->debug('Enter send_response');
-		if ($this->fault) {
-			$payload = $this->fault->serialize();
-			$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
-			$this->outgoing_headers[] = "Status: 500 Internal Server Error";
-		} else {
-			$payload = $this->responseSOAP;
-			// Some combinations of PHP+Web server allow the Status
-			// to come through as a header.  Since OK is the default
-			// just do nothing.
-			// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
-			// $this->outgoing_headers[] = "Status: 200 OK";
-		}
-        // add debug data if in debug mode
-		if(isset($this->debug_flag) && $this->debug_flag){
-        	$payload .= $this->getDebugAsXMLComment();
-        }
-		$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
-		preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
-		$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
-		// Let the Web server decide about this
-		//$this->outgoing_headers[] = "Connection: Close\r\n";
-		$payload = $this->getHTTPBody($payload);
-		$type = $this->getHTTPContentType();
-		$charset = $this->getHTTPContentTypeCharset();
-		$this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
-		//begin code to compress payload - by John
-		// NOTE: there is no way to know whether the Web server will also compress
-		// this data.
-		if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
-			if (strstr($this->headers['accept-encoding'], 'gzip')) {
-				if (function_exists('gzencode')) {
-					if (isset($this->debug_flag) && $this->debug_flag) {
-						$payload .= "<!-- Content being gzipped -->";
-					}
-					$this->outgoing_headers[] = "Content-Encoding: gzip";
-					$payload = gzencode($payload);
-				} else {
-					if (isset($this->debug_flag) && $this->debug_flag) {
-						$payload .= "<!-- Content will not be gzipped: no gzencode -->";
-					}
-				}
-			} elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
-				// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
-				// instead of gzcompress output,
-				// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
-				if (function_exists('gzdeflate')) {
-					if (isset($this->debug_flag) && $this->debug_flag) {
-						$payload .= "<!-- Content being deflated -->";
-					}
-					$this->outgoing_headers[] = "Content-Encoding: deflate";
-					$payload = gzdeflate($payload);
-				} else {
-					if (isset($this->debug_flag) && $this->debug_flag) {
-						$payload .= "<!-- Content will not be deflated: no gzcompress -->";
-					}
-				}
-			}
-		}
-		//end code
-		$this->outgoing_headers[] = "Content-Length: ".strlen($payload);
-		reset($this->outgoing_headers);
-		foreach($this->outgoing_headers as $hdr){
-			header($hdr, false);
-		}
-		print $payload;
-		$this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
-	}
-
-	/**
-	* takes the value that was created by parsing the request
-	* and compares to the method's signature, if available.
-	*
-	* @param	string	$operation	The operation to be invoked
-	* @param	array	$request	The array of parameter values
-	* @return	boolean	Whether the operation was found
-	* @access   private
-	*/
-	function verify_method($operation,$request){
-		if(isset($this->wsdl) && is_object($this->wsdl)){
-			if($this->wsdl->getOperationData($operation)){
-				return true;
-			}
-	    } elseif(isset($this->operations[$operation])){
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	* processes SOAP message received from client
-	*
-	* @param	array	$headers	The HTTP headers
-	* @param	string	$data		unprocessed request data from client
-	* @return	mixed	value of the message, decoded into a PHP type
-	* @access   private
-	*/
-    function parseRequest($headers, $data) {
-		$this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
-		$this->appendDebug($this->varDump($headers));
-    	if (!isset($headers['content-type'])) {
-			$this->setError('Request not of type text/xml (no content-type header)');
-			return false;
-    	}
-		if (!strstr($headers['content-type'], 'text/xml')) {
-			$this->setError('Request not of type text/xml');
-			return false;
-		}
-		if (strpos($headers['content-type'], '=')) {
-			$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
-			$this->debug('Got response encoding: ' . $enc);
-			if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
-				$this->xml_encoding = strtoupper($enc);
-			} else {
-				$this->xml_encoding = 'US-ASCII';
-			}
-		} else {
-			// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
-			$this->xml_encoding = 'ISO-8859-1';
-		}
-		$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
-		// parse response, get soap parser obj
-		$parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
-
-		// parser debug
-		$this->debug("parser debug: \n".$parser->getDebug());
-		// if fault occurred during message parsing
-		if($err = $parser->getError()){
-			$this->result = 'fault: error in msg parsing: '.$err;
-			$this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
-		// else successfully parsed request into soapval object
-		} else {
-			// get/set methodname
-			$this->methodURI = $parser->root_struct_namespace;
-			$this->methodname = $parser->root_struct_name;
-			$this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
-			$this->debug('calling parser->get_soapbody()');
-			$this->methodparams = $parser->get_soapbody();
-			// get SOAP headers
-			$this->requestHeaders = $parser->getHeaders();
-			// get SOAP Header
-			$this->requestHeader = $parser->get_soapheader();
-            // add document for doclit support
-            $this->document = $parser->document;
-		}
-	 }
-
-	/**
-	* gets the HTTP body for the current response.
-	*
-	* @param string $soapmsg The SOAP payload
-	* @return string The HTTP body, which includes the SOAP payload
-	* @access private
-	*/
-	function getHTTPBody($soapmsg) {
-		return $soapmsg;
-	}
-
-	/**
-	* gets the HTTP content type for the current response.
-	*
-	* Note: getHTTPBody must be called before this.
-	*
-	* @return string the HTTP content type for the current response.
-	* @access private
-	*/
-	function getHTTPContentType() {
-		return 'text/xml';
-	}
-
-	/**
-	* gets the HTTP content type charset for the current response.
-	* returns false for non-text content types.
-	*
-	* Note: getHTTPBody must be called before this.
-	*
-	* @return string the HTTP content type charset for the current response.
-	* @access private
-	*/
-	function getHTTPContentTypeCharset() {
-		return $this->soap_defencoding;
-	}
-
-	/**
-	* add a method to the dispatch map (this has been replaced by the register method)
-	*
-	* @param    string $methodname
-	* @param    string $in array of input values
-	* @param    string $out array of output values
-	* @access   public
-	* @deprecated
-	*/
-	function add_to_map($methodname,$in,$out){
-			$this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
-	}
-
-	/**
-	* register a service function with the server
-	*
-	* @param    string $name the name of the PHP function, class.method or class..method
-	* @param    array $in assoc array of input values: key = param name, value = param type
-	* @param    array $out assoc array of output values: key = param name, value = param type
-	* @param	mixed $namespace the element namespace for the method or false
-	* @param	mixed $soapaction the soapaction for the method or false
-	* @param	mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
-	* @param	mixed $use optional (encoded|literal) or false
-	* @param	string $documentation optional Description to include in WSDL
-	* @param	string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
-	* @access   public
-	*/
-	function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
-		global $HTTP_SERVER_VARS;
-
-		if($this->externalWSDLURL){
-			die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
-		}
-		if (! $name) {
-			die('You must specify a name when you register an operation');
-		}
-		if (!is_array($in)) {
-			die('You must provide an array for operation inputs');
-		}
-		if (!is_array($out)) {
-			die('You must provide an array for operation outputs');
-		}
-		if(false == $namespace) {
-		}
-		if(false == $soapaction) {
-			if (isset($_SERVER)) {
-				$SERVER_NAME = $_SERVER['SERVER_NAME'];
-				$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
-				$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
-			} elseif (isset($HTTP_SERVER_VARS)) {
-				$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
-				$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
-				$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
-			} else {
-				$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
-			}
-        	if ($HTTPS == '1' || $HTTPS == 'on') {
-        		$SCHEME = 'https';
-        	} else {
-        		$SCHEME = 'http';
-        	}
-			$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
-		}
-		if(false == $style) {
-			$style = "rpc";
-		}
-		if(false == $use) {
-			$use = "encoded";
-		}
-		if ($use == 'encoded' && $encodingStyle == '') {
-			$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
-		}
-
-		$this->operations[$name] = array(
-	    'name' => $name,
-	    'in' => $in,
-	    'out' => $out,
-	    'namespace' => $namespace,
-	    'soapaction' => $soapaction,
-	    'style' => $style);
-        if($this->wsdl){
-        	$this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
-	    }
-		return true;
-	}
-
-	/**
-	* Specify a fault to be returned to the client.
-	* This also acts as a flag to the server that a fault has occured.
-	*
-	* @param	string $faultcode
-	* @param	string $faultstring
-	* @param	string $faultactor
-	* @param	string $faultdetail
-	* @access   public
-	*/
-	function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
-		if ($faultdetail == '' && $this->debug_flag) {
-			$faultdetail = $this->getDebug();
-		}
-		$this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
-		$this->fault->soap_defencoding = $this->soap_defencoding;
-	}
-
-    /**
-    * Sets up wsdl object.
-    * Acts as a flag to enable internal WSDL generation
-    *
-    * @param string $serviceName, name of the service
-    * @param mixed $namespace optional 'tns' service namespace or false
-    * @param mixed $endpoint optional URL of service endpoint or false
-    * @param string $style optional (rpc|document) WSDL style (also specified by operation)
-    * @param string $transport optional SOAP transport
-    * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
-    */
-    function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
-    {
-    	global $HTTP_SERVER_VARS;
-
-		if (isset($_SERVER)) {
-			$SERVER_NAME = $_SERVER['SERVER_NAME'];
-			$SERVER_PORT = $_SERVER['SERVER_PORT'];
-			$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
-			$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
-		} elseif (isset($HTTP_SERVER_VARS)) {
-			$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
-			$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
-			$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
-			$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
-		} else {
-			$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
-		}
-		// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
-		$colon = strpos($SERVER_NAME,":");
-		if ($colon) {
-		    $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
-		}
-		if ($SERVER_PORT == 80) {
-			$SERVER_PORT = '';
-		} else {
-			$SERVER_PORT = ':' . $SERVER_PORT;
-		}
-        if(false == $namespace) {
-            $namespace = "http://$SERVER_NAME/soap/$serviceName";
-        }
-
-        if(false == $endpoint) {
-        	if ($HTTPS == '1' || $HTTPS == 'on') {
-        		$SCHEME = 'https';
-        	} else {
-        		$SCHEME = 'http';
-        	}
-            $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
-        }
-
-        if(false == $schemaTargetNamespace) {
-            $schemaTargetNamespace = $namespace;
-        }
-
-        $this->wsdl = new wsdl();
-        $this->wsdl->soap_defencoding = $this->soap_defencoding;
-		$this->wsdl->serviceName = $serviceName;
-        $this->wsdl->endpoint = $endpoint;
-		$this->wsdl->namespaces['tns'] = $namespace;
-		$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
-		$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
-		if ($schemaTargetNamespace != $namespace) {
-			$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
-		}
-        $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
-        if ($style == 'document') {
-	        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
-        }
-        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
-        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
-        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
-        $this->wsdl->bindings[$serviceName.'Binding'] = array(
-        	'name'=>$serviceName.'Binding',
-            'style'=>$style,
-            'transport'=>$transport,
-            'portType'=>$serviceName.'PortType');
-        $this->wsdl->ports[$serviceName.'Port'] = array(
-        	'binding'=>$serviceName.'Binding',
-            'location'=>$endpoint,
-            'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
-    }
-}
-
-/**
- * Backward compatibility
- */
-class soap_server extends nusoap_server {
-}
+<?php
+
+/**
+*
+* nusoap_server allows the user to create a SOAP server
+* that is capable of receiving messages and returning responses
+*
+* @author   Dietrich Ayala <dietrich@ganx4.com>
+* @author   Scott Nichol <snichol@users.sourceforge.net>
+* @version  $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $
+* @access   public
+*/
+class nusoap_server extends nusoap_base
+{
+	/**
+	 * HTTP headers of request
+	 * @var array
+	 * @access private
+	 */
+	var $headers = array();
+	/**
+	 * HTTP request
+	 * @var string
+	 * @access private
+	 */
+	var $request = '';
+	/**
+	 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
+	 * @var string
+	 * @access public
+	 */
+	var $requestHeaders = '';
+	/**
+	 * SOAP Headers from request (parsed)
+	 * @var mixed
+	 * @access public
+	 */
+	var $requestHeader = NULL;
+	/**
+	 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
+	 * @var string
+	 * @access public
+	 */
+	var $document = '';
+	/**
+	 * SOAP payload for request (text)
+	 * @var string
+	 * @access public
+	 */
+	var $requestSOAP = '';
+	/**
+	 * requested method namespace URI
+	 * @var string
+	 * @access private
+	 */
+	var $methodURI = '';
+	/**
+	 * name of method requested
+	 * @var string
+	 * @access private
+	 */
+	var $methodname = '';
+	/**
+	 * method parameters from request
+	 * @var array
+	 * @access private
+	 */
+	var $methodparams = array();
+	/**
+	 * SOAP Action from request
+	 * @var string
+	 * @access private
+	 */
+	var $SOAPAction = '';
+	/**
+	 * character set encoding of incoming (request) messages
+	 * @var string
+	 * @access public
+	 */
+	var $xml_encoding = '';
+	/**
+	 * toggles whether the parser decodes element content w/ utf8_decode()
+	 * @var boolean
+	 * @access public
+	 */
+    var $decode_utf8 = true;
+
+	/**
+	 * HTTP headers of response
+	 * @var array
+	 * @access public
+	 */
+	var $outgoing_headers = array();
+	/**
+	 * HTTP response
+	 * @var string
+	 * @access private
+	 */
+	var $response = '';
+	/**
+	 * SOAP headers for response (text or array of soapval or associative array)
+	 * @var mixed
+	 * @access public
+	 */
+	var $responseHeaders = '';
+	/**
+	 * SOAP payload for response (text)
+	 * @var string
+	 * @access private
+	 */
+	var $responseSOAP = '';
+	/**
+	 * method return value to place in response
+	 * @var mixed
+	 * @access private
+	 */
+	var $methodreturn = false;
+	/**
+	 * whether $methodreturn is a string of literal XML
+	 * @var boolean
+	 * @access public
+	 */
+	var $methodreturnisliteralxml = false;
+	/**
+	 * SOAP fault for response (or false)
+	 * @var mixed
+	 * @access private
+	 */
+	var $fault = false;
+	/**
+	 * text indication of result (for debugging)
+	 * @var string
+	 * @access private
+	 */
+	var $result = 'successful';
+
+	/**
+	 * assoc array of operations => opData; operations are added by the register()
+	 * method or by parsing an external WSDL definition
+	 * @var array
+	 * @access private
+	 */
+	var $operations = array();
+	/**
+	 * wsdl instance (if one)
+	 * @var mixed
+	 * @access private
+	 */
+	var $wsdl = false;
+	/**
+	 * URL for WSDL (if one)
+	 * @var mixed
+	 * @access private
+	 */
+	var $externalWSDLURL = false;
+	/**
+	 * whether to append debug to response as XML comment
+	 * @var boolean
+	 * @access public
+	 */
+	var $debug_flag = false;
+
+
+	/**
+	* constructor
+    * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
+	*
+    * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
+	* @access   public
+	*/
+	function __construct($wsdl=false)
+    {
+		parent::__construct();
+		// turn on debugging?
+		global $debug;
+		global $HTTP_SERVER_VARS;
+
+		if (isset($_SERVER)) {
+			$this->debug("_SERVER is defined:");
+			$this->appendDebug($this->varDump($_SERVER));
+		} elseif (isset($HTTP_SERVER_VARS)) {
+			$this->debug("HTTP_SERVER_VARS is defined:");
+			$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
+		} else {
+			$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
+		}
+
+		if (isset($debug)) {
+			$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
+			$this->debug_flag = $debug;
+		} elseif (isset($_SERVER['QUERY_STRING'])) {
+			$qs = explode('&', $_SERVER['QUERY_STRING']);
+			foreach ($qs as $v) {
+				if (substr($v, 0, 6) == 'debug=') {
+					$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
+					$this->debug_flag = substr($v, 6);
+				}
+			}
+		} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
+			$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
+			foreach ($qs as $v) {
+				if (substr($v, 0, 6) == 'debug=') {
+					$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
+					$this->debug_flag = substr($v, 6);
+				}
+			}
+		}
+
+		// wsdl
+		if ($wsdl){
+			$this->debug("In nusoap_server, WSDL is specified");
+			if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
+				$this->wsdl = $wsdl;
+                $this->wsdl->soap_defencoding = $this->soap_defencoding;
+				$this->externalWSDLURL = $this->wsdl->wsdl;
+				$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
+			} else {
+				$this->debug('Create wsdl from ' . $wsdl);
+				$this->wsdl = new wsdl($wsdl);
+                $this->wsdl->soap_defencoding = $this->soap_defencoding;
+				$this->externalWSDLURL = $wsdl;
+			}
+			$this->appendDebug($this->wsdl->getDebug());
+			$this->wsdl->clearDebug();
+			if($err = $this->wsdl->getError()){
+				die('WSDL ERROR: '.$err);
+			}
+		}
+	}
+
+	/**
+	* processes request and returns response
+	*
+	* @param    string $data usually is the value of $HTTP_RAW_POST_DATA
+	* @access   public
+	*/
+	function service($data){
+		global $HTTP_SERVER_VARS;
+
+		if (isset($_SERVER['REQUEST_METHOD'])) {
+			$rm = $_SERVER['REQUEST_METHOD'];
+		} elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
+			$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
+		} else {
+			$rm = '';
+		}
+
+		if (isset($_SERVER['QUERY_STRING'])) {
+			$qs = $_SERVER['QUERY_STRING'];
+		} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
+			$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
+		} else {
+			$qs = '';
+		}
+		$this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
+
+		if ($rm == 'POST') {
+			$this->debug("In service, invoke the request");
+			$this->parse_request($data);
+			if (! $this->fault) {
+				$this->invoke_method();
+			}
+			if (! $this->fault) {
+				$this->serialize_return();
+			}
+			$this->send_response();
+		} elseif (preg_match('/wsdl/', $qs) ){
+			$this->debug("In service, this is a request for WSDL");
+			if ($this->externalWSDLURL){
+              if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
+				$this->debug("In service, re-direct for WSDL");
+				header('Location: '.$this->externalWSDLURL);
+              } else { // assume file
+				$this->debug("In service, use file passthru for WSDL");
+                header("Content-Type: text/xml\r\n");
+				$pos = strpos($this->externalWSDLURL, "file://");
+				if ($pos === false) {
+					$filename = $this->externalWSDLURL;
+				} else {
+					$filename = substr($this->externalWSDLURL, $pos + 7);
+				}
+                $fp = fopen($this->externalWSDLURL, 'r');
+                fpassthru($fp);
+              }
+			} elseif ($this->wsdl) {
+				$this->debug("In service, serialize WSDL");
+                header("Content-Type: text/xml; charset=".$this->soap_defencoding."\r\n");
+				print $this->wsdl->serialize($this->debug_flag);
+				if ($this->debug_flag) {
+					$this->debug('wsdl:');
+					$this->appendDebug($this->varDump($this->wsdl));
+					print $this->getDebugAsXMLComment();
+				}
+			} else {
+				$this->debug("In service, there is no WSDL");
+                header("Content-Type: text/html; charset=".$this->soap_defencoding."\r\n");
+				print "This service does not provide WSDL";
+			}
+		} elseif ($this->wsdl) {
+			$this->debug("In service, return Web description");
+			print $this->wsdl->webDescription();
+		} else {
+			$this->debug("In service, no Web description");
+			header("Content-Type: text/html; charset=ISO-8859-1\r\n");
+			print "This service does not provide a Web description";
+		}
+	}
+
+	/**
+	* parses HTTP request headers.
+	*
+	* The following fields are set by this function (when successful)
+	*
+	* headers
+	* request
+	* xml_encoding
+	* SOAPAction
+	*
+	* @access   private
+	*/
+	function parse_http_headers() {
+		global $HTTP_SERVER_VARS;
+
+		$this->request = '';
+		$this->SOAPAction = '';
+		if(function_exists('getallheaders')){
+			$this->debug("In parse_http_headers, use getallheaders");
+			$headers = getallheaders();
+			foreach($headers as $k=>$v){
+				$k = strtolower($k);
+				$this->headers[$k] = $v;
+				$this->request .= "$k: $v\r\n";
+				$this->debug("$k: $v");
+			}
+			// get SOAPAction header
+			if(isset($this->headers['soapaction'])){
+				$this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
+			}
+			// get the character encoding of the incoming request
+			if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
+				$enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
+				if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
+					$this->xml_encoding = strtoupper($enc);
+				} else {
+					$this->xml_encoding = 'US-ASCII';
+				}
+			} else {
+				// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
+				$this->xml_encoding = 'ISO-8859-1';
+			}
+		} elseif(isset($_SERVER) && is_array($_SERVER)){
+			$this->debug("In parse_http_headers, use _SERVER");
+			foreach ($_SERVER as $k => $v) {
+				if (substr($k, 0, 5) == 'HTTP_') {
+					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
+				} else {
+					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
+				}
+				if ($k == 'soapaction') {
+					// get SOAPAction header
+					$k = 'SOAPAction';
+					$v = str_replace('"', '', $v);
+					$v = str_replace('\\', '', $v);
+					$this->SOAPAction = $v;
+				} else if ($k == 'content-type') {
+					// get the character encoding of the incoming request
+					if (strpos($v, '=')) {
+						$enc = substr(strstr($v, '='), 1);
+						$enc = str_replace('"', '', $enc);
+						$enc = str_replace('\\', '', $enc);
+						if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
+							$this->xml_encoding = strtoupper($enc);
+						} else {
+							$this->xml_encoding = 'US-ASCII';
+						}
+					} else {
+						// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
+						$this->xml_encoding = 'ISO-8859-1';
+					}
+				}
+				$this->headers[$k] = $v;
+				$this->request .= "$k: $v\r\n";
+				$this->debug("$k: $v");
+			}
+		} elseif (is_array($HTTP_SERVER_VARS)) {
+			$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
+			foreach ($HTTP_SERVER_VARS as $k => $v) {
+				if (substr($k, 0, 5) == 'HTTP_') {
+					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); 	                                         $k = strtolower(substr($k, 5));
+				} else {
+					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); 	                                         $k = strtolower($k);
+				}
+				if ($k == 'soapaction') {
+					// get SOAPAction header
+					$k = 'SOAPAction';
+					$v = str_replace('"', '', $v);
+					$v = str_replace('\\', '', $v);
+					$this->SOAPAction = $v;
+				} else if ($k == 'content-type') {
+					// get the character encoding of the incoming request
+					if (strpos($v, '=')) {
+						$enc = substr(strstr($v, '='), 1);
+						$enc = str_replace('"', '', $enc);
+						$enc = str_replace('\\', '', $enc);
+						if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
+							$this->xml_encoding = strtoupper($enc);
+						} else {
+							$this->xml_encoding = 'US-ASCII';
+						}
+					} else {
+						// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
+						$this->xml_encoding = 'ISO-8859-1';
+					}
+				}
+				$this->headers[$k] = $v;
+				$this->request .= "$k: $v\r\n";
+				$this->debug("$k: $v");
+			}
+		} else {
+			$this->debug("In parse_http_headers, HTTP headers not accessible");
+			$this->setError("HTTP headers not accessible");
+		}
+	}
+
+	/**
+	* parses a request
+	*
+	* The following fields are set by this function (when successful)
+	*
+	* headers
+	* request
+	* xml_encoding
+	* SOAPAction
+	* request
+	* requestSOAP
+	* methodURI
+	* methodname
+	* methodparams
+	* requestHeaders
+	* document
+	*
+	* This sets the fault field on error
+	*
+	* @param    string $data XML string
+	* @access   private
+	*/
+	function parse_request($data='') {
+		$this->debug('entering parse_request()');
+		$this->parse_http_headers();
+		$this->debug('got character encoding: '.$this->xml_encoding);
+		// uncompress if necessary
+		if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
+			$this->debug('got content encoding: ' . $this->headers['content-encoding']);
+			if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
+		    	// if decoding works, use it. else assume data wasn't gzencoded
+				if (function_exists('gzuncompress')) {
+					if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
+						$data = $degzdata;
+					} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
+						$data = $degzdata;
+					} else {
+						$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
+						return;
+					}
+				} else {
+					$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
+					return;
+				}
+			}
+		}
+		$this->request .= "\r\n".$data;
+		$data = $this->parseRequest($this->headers, $data);
+		$this->requestSOAP = $data;
+		$this->debug('leaving parse_request');
+	}
+
+	/**
+	* invokes a PHP function for the requested SOAP method
+	*
+	* The following fields are set by this function (when successful)
+	*
+	* methodreturn
+	*
+	* Note that the PHP function that is called may also set the following
+	* fields to affect the response sent to the client
+	*
+	* responseHeaders
+	* outgoing_headers
+	*
+	* This sets the fault field on error
+	*
+	* @access   private
+	*/
+	function invoke_method() {
+		$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
+
+		//
+		// if you are debugging in this area of the code, your service uses a class to implement methods,
+		// you use SOAP RPC, and the client is .NET, please be aware of the following...
+		// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
+		// method name.  that is fine for naming the .NET methods.  it is not fine for properly constructing
+		// the XML request and reading the XML response.  you need to add the RequestElementName and
+		// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
+		// generates for the method.  these parameters are used to specify the correct XML element names
+		// for .NET to use, i.e. the names with the '.' in them.
+		//
+		$orig_methodname = $this->methodname;
+		if ($this->wsdl) {
+			if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
+				$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
+				$this->appendDebug('opData=' . $this->varDump($this->opData));
+			} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
+				// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
+				$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
+				$this->appendDebug('opData=' . $this->varDump($this->opData));
+				$this->methodname = $this->opData['name'];
+			} else {
+				$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
+				$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
+				return;
+			}
+		} else {
+			$this->debug('in invoke_method, no WSDL to validate method');
+		}
+
+		// if a . is present in $this->methodname, we see if there is a class in scope,
+		// which could be referred to. We will also distinguish between two deliminators,
+		// to allow methods to be called a the class or an instance
+		if (strpos($this->methodname, '..') > 0) {
+			$delim = '..';
+		} else if (strpos($this->methodname, '.') > 0) {
+			$delim = '.';
+		} else {
+			$delim = '';
+		}
+		$this->debug("in invoke_method, delim=$delim");
+
+		$class = '';
+		$method = '';
+		if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
+			$try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
+			if (class_exists($try_class)) {
+				// get the class and method name
+				$class = $try_class;
+				$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
+				$this->debug("in invoke_method, class=$class method=$method delim=$delim");
+			} else {
+				$this->debug("in invoke_method, class=$try_class not found");
+			}
+		} else {
+			$try_class = '';
+			$this->debug("in invoke_method, no class to try");
+		}
+
+		// does method exist?
+		if ($class == '') {
+			if (!function_exists($this->methodname)) {
+				$this->debug("in invoke_method, function '$this->methodname' not found!");
+				$this->result = 'fault: method not found';
+				$this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
+				return;
+			}
+		} else {
+			$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
+			if (!in_array($method_to_compare, get_class_methods($class))) {
+				$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
+				$this->result = 'fault: method not found';
+				$this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
+				return;
+			}
+		}
+
+		// evaluate message, getting back parameters
+		// verify that request parameters match the method's signature
+		if(! $this->verify_method($this->methodname,$this->methodparams)){
+			// debug
+			$this->debug('ERROR: request not verified against method signature');
+			$this->result = 'fault: request failed validation against method signature';
+			// return fault
+			$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
+			return;
+		}
+
+		// if there are parameters to pass
+		$this->debug('in invoke_method, params:');
+		$this->appendDebug($this->varDump($this->methodparams));
+		$this->debug("in invoke_method, calling '$this->methodname'");
+		if (!function_exists('call_user_func_array')) {
+			if ($class == '') {
+				$this->debug('in invoke_method, calling function using eval()');
+				$funcCall = "\$this->methodreturn = $this->methodname(";
+			} else {
+				if ($delim == '..') {
+					$this->debug('in invoke_method, calling class method using eval()');
+					$funcCall = "\$this->methodreturn = ".$class."::".$method."(";
+				} else {
+					$this->debug('in invoke_method, calling instance method using eval()');
+					// generate unique instance name
+					$instname = "\$inst_".time();
+					$funcCall = $instname." = new ".$class."(); ";
+					$funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
+				}
+			}
+			if ($this->methodparams) {
+				foreach ($this->methodparams as $param) {
+					if (is_array($param) || is_object($param)) {
+						$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
+						return;
+					}
+					$funcCall .= "\"$param\",";
+				}
+				$funcCall = substr($funcCall, 0, -1);
+			}
+			$funcCall .= ');';
+			$this->debug('in invoke_method, function call: '.$funcCall);
+			@eval($funcCall);
+		} else {
+			if ($class == '') {
+				$this->debug('in invoke_method, calling function using call_user_func_array()');
+				$call_arg = "$this->methodname";	// straight assignment changes $this->methodname to lower case after call_user_func_array()
+			} elseif ($delim == '..') {
+				$this->debug('in invoke_method, calling class method using call_user_func_array()');
+				$call_arg = array ($class, $method);
+			} else {
+				$this->debug('in invoke_method, calling instance method using call_user_func_array()');
+				$instance = new $class ();
+				$call_arg = array(&$instance, $method);
+			}
+			if (is_array($this->methodparams)) {
+				$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
+			} else {
+				$this->methodreturn = call_user_func_array($call_arg, array());
+			}
+		}
+        $this->debug('in invoke_method, methodreturn:');
+        $this->appendDebug($this->varDump($this->methodreturn));
+		$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
+	}
+
+	/**
+	* serializes the return value from a PHP function into a full SOAP Envelope
+	*
+	* The following fields are set by this function (when successful)
+	*
+	* responseSOAP
+	*
+	* This sets the fault field on error
+	*
+	* @access   private
+	*/
+	function serialize_return() {
+		$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
+		// if fault
+		if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
+			$this->debug('got a fault object from method');
+			$this->fault = $this->methodreturn;
+			return;
+		} elseif ($this->methodreturnisliteralxml) {
+			$return_val = $this->methodreturn;
+		// returned value(s)
+		} else {
+			$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
+			$this->debug('serializing return value');
+			if($this->wsdl){
+				$opParams = "";
+				if (sizeof($this->opData['output']['parts']) > 1) {
+					$this->debug('more than one output part, so use the method return unchanged');
+			    	$opParams = $this->methodreturn;
+			    } elseif (sizeof($this->opData['output']['parts']) == 1) {
+					$this->debug('exactly one output part, so wrap the method return in a simple array');
+					// TODO: verify that it is not already wrapped!
+			    	//foreach ($this->opData['output']['parts'] as $name => $type) {
+					//	$this->debug('wrap in element named ' . $name);
+			    	//}
+			    	$opParams = array($this->methodreturn);
+			    }
+			    $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
+			    $this->appendDebug($this->wsdl->getDebug());
+			    $this->wsdl->clearDebug();
+				if($errstr = $this->wsdl->getError()){
+					$this->debug('got wsdl error: '.$errstr);
+					$this->fault('SOAP-ENV:Server', 'unable to serialize result');
+					return;
+				}
+			} else {
+				if (isset($this->methodreturn)) {
+					$return_val = $this->serialize_val($this->methodreturn, 'return');
+				} else {
+					$return_val = '';
+					$this->debug('in absence of WSDL, assume void return for backward compatibility');
+				}
+			}
+		}
+		$this->debug('return value:');
+		$this->appendDebug($this->varDump($return_val));
+
+		$this->debug('serializing response');
+		if ($this->wsdl) {
+			$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
+			if ($this->opData['style'] == 'rpc') {
+				$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
+				if ($this->opData['output']['use'] == 'literal') {
+					// http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
+					if ($this->methodURI) {
+						$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
+					} else {
+						$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
+					}
+				} else {
+					if ($this->methodURI) {
+						$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
+					} else {
+						$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
+					}
+				}
+			} else {
+				$this->debug('style is not rpc for serialization: assume document');
+				$payload = $return_val;
+			}
+		} else {
+			$this->debug('do not have WSDL for serialization: assume rpc/encoded');
+			$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
+		}
+		$this->result = 'successful';
+		if($this->wsdl){
+			//if($this->debug_flag){
+            	$this->appendDebug($this->wsdl->getDebug());
+            //	}
+			if (isset($this->opData['output']['encodingStyle'])) {
+				$encodingStyle = $this->opData['output']['encodingStyle'];
+			} else {
+				$encodingStyle = '';
+			}
+			// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
+			$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
+		} else {
+			$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
+		}
+		$this->debug("Leaving serialize_return");
+	}
+
+	/**
+	* sends an HTTP response
+	*
+	* The following fields are set by this function (when successful)
+	*
+	* outgoing_headers
+	* response
+	*
+	* @access   private
+	*/
+	function send_response() {
+		$this->debug('Enter send_response');
+		if ($this->fault) {
+			$payload = $this->fault->serialize();
+			$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
+			$this->outgoing_headers[] = "Status: 500 Internal Server Error";
+		} else {
+			$payload = $this->responseSOAP;
+			// Some combinations of PHP+Web server allow the Status
+			// to come through as a header.  Since OK is the default
+			// just do nothing.
+			// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
+			// $this->outgoing_headers[] = "Status: 200 OK";
+		}
+        // add debug data if in debug mode
+		if(isset($this->debug_flag) && $this->debug_flag){
+        	$payload .= $this->getDebugAsXMLComment();
+        }
+		$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
+		preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
+		$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
+		// Let the Web server decide about this
+		//$this->outgoing_headers[] = "Connection: Close\r\n";
+		$payload = $this->getHTTPBody($payload);
+		$type = $this->getHTTPContentType();
+		$charset = $this->getHTTPContentTypeCharset();
+		$this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
+		//begin code to compress payload - by John
+		// NOTE: there is no way to know whether the Web server will also compress
+		// this data.
+		if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
+			if (strstr($this->headers['accept-encoding'], 'gzip')) {
+				if (function_exists('gzencode')) {
+					if (isset($this->debug_flag) && $this->debug_flag) {
+						$payload .= "<!-- Content being gzipped -->";
+					}
+					$this->outgoing_headers[] = "Content-Encoding: gzip";
+					$payload = gzencode($payload);
+				} else {
+					if (isset($this->debug_flag) && $this->debug_flag) {
+						$payload .= "<!-- Content will not be gzipped: no gzencode -->";
+					}
+				}
+			} elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
+				// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
+				// instead of gzcompress output,
+				// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
+				if (function_exists('gzdeflate')) {
+					if (isset($this->debug_flag) && $this->debug_flag) {
+						$payload .= "<!-- Content being deflated -->";
+					}
+					$this->outgoing_headers[] = "Content-Encoding: deflate";
+					$payload = gzdeflate($payload);
+				} else {
+					if (isset($this->debug_flag) && $this->debug_flag) {
+						$payload .= "<!-- Content will not be deflated: no gzcompress -->";
+					}
+				}
+			}
+		}
+		//end code
+		$this->outgoing_headers[] = "Content-Length: ".strlen($payload);
+		reset($this->outgoing_headers);
+		foreach($this->outgoing_headers as $hdr){
+			header($hdr, false);
+		}
+		print $payload;
+		$this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
+	}
+
+	/**
+	* takes the value that was created by parsing the request
+	* and compares to the method's signature, if available.
+	*
+	* @param	string	$operation	The operation to be invoked
+	* @param	array	$request	The array of parameter values
+	* @return	boolean	Whether the operation was found
+	* @access   private
+	*/
+	function verify_method($operation,$request){
+		if(isset($this->wsdl) && is_object($this->wsdl)){
+			if($this->wsdl->getOperationData($operation)){
+				return true;
+			}
+	    } elseif(isset($this->operations[$operation])){
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	* processes SOAP message received from client
+	*
+	* @param	array	$headers	The HTTP headers
+	* @param	string	$data		unprocessed request data from client
+	* @return	mixed	value of the message, decoded into a PHP type
+	* @access   private
+	*/
+    function parseRequest($headers, $data) {
+		$this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
+		$this->appendDebug($this->varDump($headers));
+    	if (!isset($headers['content-type'])) {
+			$this->setError('Request not of type text/xml (no content-type header)');
+			return false;
+    	}
+		if (!strstr($headers['content-type'], 'text/xml')) {
+			$this->setError('Request not of type text/xml');
+			return false;
+		}
+		if (strpos($headers['content-type'], '=')) {
+			$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
+			$this->debug('Got response encoding: ' . $enc);
+			if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
+				$this->xml_encoding = strtoupper($enc);
+			} else {
+				$this->xml_encoding = 'US-ASCII';
+			}
+		} else {
+			// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
+			$this->xml_encoding = 'ISO-8859-1';
+		}
+		$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
+		// parse response, get soap parser obj
+		$parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
+
+		// parser debug
+		$this->debug("parser debug: \n".$parser->getDebug());
+		// if fault occurred during message parsing
+		if($err = $parser->getError()){
+			$this->result = 'fault: error in msg parsing: '.$err;
+			$this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
+		// else successfully parsed request into soapval object
+		} else {
+			// get/set methodname
+			$this->methodURI = $parser->root_struct_namespace;
+			$this->methodname = $parser->root_struct_name;
+			$this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
+			$this->debug('calling parser->get_soapbody()');
+			$this->methodparams = $parser->get_soapbody();
+			// get SOAP headers
+			$this->requestHeaders = $parser->getHeaders();
+			// get SOAP Header
+			$this->requestHeader = $parser->get_soapheader();
+            // add document for doclit support
+            $this->document = $parser->document;
+		}
+	 }
+
+	/**
+	* gets the HTTP body for the current response.
+	*
+	* @param string $soapmsg The SOAP payload
+	* @return string The HTTP body, which includes the SOAP payload
+	* @access private
+	*/
+	function getHTTPBody($soapmsg) {
+		return $soapmsg;
+	}
+
+	/**
+	* gets the HTTP content type for the current response.
+	*
+	* Note: getHTTPBody must be called before this.
+	*
+	* @return string the HTTP content type for the current response.
+	* @access private
+	*/
+	function getHTTPContentType() {
+		return 'text/xml';
+	}
+
+	/**
+	* gets the HTTP content type charset for the current response.
+	* returns false for non-text content types.
+	*
+	* Note: getHTTPBody must be called before this.
+	*
+	* @return string the HTTP content type charset for the current response.
+	* @access private
+	*/
+	function getHTTPContentTypeCharset() {
+		return $this->soap_defencoding;
+	}
+
+	/**
+	* add a method to the dispatch map (this has been replaced by the register method)
+	*
+	* @param    string $methodname
+	* @param    string $in array of input values
+	* @param    string $out array of output values
+	* @access   public
+	* @deprecated
+	*/
+	function add_to_map($methodname,$in,$out){
+			$this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
+	}
+
+	/**
+	* register a service function with the server
+	*
+	* @param    string $name the name of the PHP function, class.method or class..method
+	* @param    array $in assoc array of input values: key = param name, value = param type
+	* @param    array $out assoc array of output values: key = param name, value = param type
+	* @param	mixed $namespace the element namespace for the method or false
+	* @param	mixed $soapaction the soapaction for the method or false
+	* @param	mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
+	* @param	mixed $use optional (encoded|literal) or false
+	* @param	string $documentation optional Description to include in WSDL
+	* @param	string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
+	* @access   public
+	*/
+	function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
+		global $HTTP_SERVER_VARS;
+
+		if($this->externalWSDLURL){
+			die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
+		}
+		if (! $name) {
+			die('You must specify a name when you register an operation');
+		}
+		if (!is_array($in)) {
+			die('You must provide an array for operation inputs');
+		}
+		if (!is_array($out)) {
+			die('You must provide an array for operation outputs');
+		}
+		if(false == $namespace) {
+		}
+		if(false == $soapaction) {
+			if (isset($_SERVER)) {
+				$SERVER_NAME = $_SERVER['SERVER_NAME'];
+				$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
+				$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
+			} elseif (isset($HTTP_SERVER_VARS)) {
+				$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
+				$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
+				$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
+			} else {
+				$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
+			}
+        	if ($HTTPS == '1' || $HTTPS == 'on') {
+        		$SCHEME = 'https';
+        	} else {
+        		$SCHEME = 'http';
+        	}
+			$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
+		}
+		if(false == $style) {
+			$style = "rpc";
+		}
+		if(false == $use) {
+			$use = "encoded";
+		}
+		if ($use == 'encoded' && $encodingStyle == '') {
+			$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
+		}
+
+		$this->operations[$name] = array(
+	    'name' => $name,
+	    'in' => $in,
+	    'out' => $out,
+	    'namespace' => $namespace,
+	    'soapaction' => $soapaction,
+	    'style' => $style);
+        if($this->wsdl){
+        	$this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
+	    }
+		return true;
+	}
+
+	/**
+	* Specify a fault to be returned to the client.
+	* This also acts as a flag to the server that a fault has occured.
+	*
+	* @param	string $faultcode
+	* @param	string $faultstring
+	* @param	string $faultactor
+	* @param	string $faultdetail
+	* @access   public
+	*/
+	function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
+		if ($faultdetail == '' && $this->debug_flag) {
+			$faultdetail = $this->getDebug();
+		}
+		$this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
+		$this->fault->soap_defencoding = $this->soap_defencoding;
+	}
+
+    /**
+    * Sets up wsdl object.
+    * Acts as a flag to enable internal WSDL generation
+    *
+    * @param string $serviceName, name of the service
+    * @param mixed $namespace optional 'tns' service namespace or false
+    * @param mixed $endpoint optional URL of service endpoint or false
+    * @param string $style optional (rpc|document) WSDL style (also specified by operation)
+    * @param string $transport optional SOAP transport
+    * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
+    */
+    function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
+    {
+    	global $HTTP_SERVER_VARS;
+
+		if (isset($_SERVER)) {
+			$SERVER_NAME = $_SERVER['SERVER_NAME'];
+			$SERVER_PORT = $_SERVER['SERVER_PORT'];
+			$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
+			$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
+		} elseif (isset($HTTP_SERVER_VARS)) {
+			$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
+			$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
+			$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
+			$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
+		} else {
+			$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
+		}
+		// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
+		$colon = strpos($SERVER_NAME,":");
+		if ($colon) {
+		    $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
+		}
+		if ($SERVER_PORT == 80) {
+			$SERVER_PORT = '';
+		} else {
+			$SERVER_PORT = ':' . $SERVER_PORT;
+		}
+        if(false == $namespace) {
+            $namespace = "http://$SERVER_NAME/soap/$serviceName";
+        }
+
+        if(false == $endpoint) {
+        	if ($HTTPS == '1' || $HTTPS == 'on') {
+        		$SCHEME = 'https';
+        	} else {
+        		$SCHEME = 'http';
+        	}
+            $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
+        }
+
+        if(false == $schemaTargetNamespace) {
+            $schemaTargetNamespace = $namespace;
+        }
+
+        $this->wsdl = new wsdl();
+        $this->wsdl->soap_defencoding = $this->soap_defencoding;
+		$this->wsdl->serviceName = $serviceName;
+        $this->wsdl->endpoint = $endpoint;
+		$this->wsdl->namespaces['tns'] = $namespace;
+		$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
+		$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
+		if ($schemaTargetNamespace != $namespace) {
+			$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
+		}
+        $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
+        if ($style == 'document') {
+	        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
+        }
+        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
+        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
+        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
+        $this->wsdl->bindings[$serviceName.'Binding'] = array(
+        	'name'=>$serviceName.'Binding',
+            'style'=>$style,
+            'transport'=>$transport,
+            'portType'=>$serviceName.'PortType');
+        $this->wsdl->ports[$serviceName.'Port'] = array(
+        	'binding'=>$serviceName.'Binding',
+            'location'=>$endpoint,
+            'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
+    }
+}
+
+/**
+ * Backward compatibility
+ */
+class soap_server extends nusoap_server {
+}