Moved programs into the Programs folder

git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1958 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
John Hurliman
2008-07-22 23:00:32 +00:00
parent c1f3d6a3c2
commit 660db80eb5
82 changed files with 0 additions and 667 deletions

View File

@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SLImageUpload")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Metaverse Industries LLC")]
[assembly: AssemblyProduct("SLImageUpload")]
[assembly: AssemblyCopyright("Copyright © Metaverse Industries LLC 2007")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d8a0ec17-daf9-4a17-b72f-d32ed7f6962a")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SLImageUpload.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SLImageUpload.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SLImageUpload.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0"?>
<project name="libsecondlife" default="build">
<!-- global framework settings -->
<property name="target.framework" value="${framework::get-target-framework()}" />
<property name="assembly.dir" value="${framework::get-assembly-directory(target.framework)}" />
<!-- global project settings -->
<xmlpeek
file="../libsecondlife.build"
xpath="/project/property[@name = 'project.version']/@value"
property="project.version" />
<property name="build.number"
value="${math::abs(math::floor(timespan::get-total-days(datetime::now()
- datetime::parse('01/01/2002'))))}" />
<property name="assembly" value="SLImageUpload"/>
<property name="bin_dir" value="../bin" />
<!-- default configuration -->
<property name="project.config" value="debug" /> <!-- debug|release -->
<!-- named configurations -->
<target name="init" description="Initializes build properties">
<call target="${project.config}" />
</target>
<target name="debug" description="configures a debug build">
<property name="build.debug" value="true" />
<property name="package.name"
value="${project::get-name()}-${project.version}-${project.config}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()} [${project.config}]" />
</target>
<target name="release" description="configures a release build">
<property name="project.config" value="release" />
<property name="build.debug" value="false" />
<property name="package.name"
value="${project::get-name()}-${project.version}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()}" />
</target>
<!-- build tasks -->
<target name="build" depends="build-main"
description="Main build target">
</target>
<target name="build-main" depends="init"
description="Builds the binaries for the current configuration">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="exe"
debug="${build.debug}"
output="${bin_dir}/SLImageUpload.exe">
<sources failonempty="true">
<include name="*.cs" />
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
<include name="System.Data.dll" />
<include name="System.Drawing.dll" />
<include name="System.Windows.Forms.dll" />
</references>
</csc>
</target>
<target name="clean" depends="init"
description="Deletes the current configuration">
<delete failonerror="false">
<fileset basedir="${bin_dir}/">
<include name="SLImageUpload.exe" />
</fileset>
</delete>
</target>
<target
name="*"
description="Handles unknown targets">
<echo message="skipping unknown target" />
</target>
</project>

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace SLImageUpload
{
static class SLImageUpload
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmSLImageUpload());
}
}
}

View File

@@ -0,0 +1,95 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F3BDC0BC-74EB-451E-8FFE-AA162474F2F2}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SLImageUpload</RootNamespace>
<AssemblyName>SLImageUpload</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-docs|AnyCPU' ">
<OutputPath>bin\Release-docs\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="frmSLImageUpload.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmSLImageUpload.Designer.cs">
<DependentUpon>frmSLImageUpload.cs</DependentUpon>
</Compile>
<Compile Include="SLImageUpload.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="frmSLImageUpload.resx">
<SubType>Designer</SubType>
<DependentUpon>frmSLImageUpload.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libsecondlife\OpenMetaverse.csproj">
<Project>{D9CDEDFB-8169-4B03-B57F-0DF638F044EC}</Project>
<Name>OpenMetaverse</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,279 @@
namespace SLImageUpload
{
partial class frmSLImageUpload
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.grpLogin = new System.Windows.Forms.GroupBox();
this.cmdConnect = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtLastName = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.txtFirstName = new System.Windows.Forms.TextBox();
this.grpUpload = new System.Windows.Forms.GroupBox();
this.txtAssetID = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.lblSize = new System.Windows.Forms.Label();
this.prgUpload = new System.Windows.Forms.ProgressBar();
this.picPreview = new System.Windows.Forms.PictureBox();
this.cmdLoad = new System.Windows.Forms.Button();
this.txtSendtoName = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.chkLossless = new System.Windows.Forms.CheckBox();
this.cmdUpload = new System.Windows.Forms.Button();
this.grpLogin.SuspendLayout();
this.grpUpload.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picPreview)).BeginInit();
this.SuspendLayout();
//
// grpLogin
//
this.grpLogin.Controls.Add(this.cmdConnect);
this.grpLogin.Controls.Add(this.label3);
this.grpLogin.Controls.Add(this.txtPassword);
this.grpLogin.Controls.Add(this.label2);
this.grpLogin.Controls.Add(this.txtLastName);
this.grpLogin.Controls.Add(this.label1);
this.grpLogin.Controls.Add(this.txtFirstName);
this.grpLogin.Location = new System.Drawing.Point(11, 260);
this.grpLogin.Name = "grpLogin";
this.grpLogin.Size = new System.Drawing.Size(379, 101);
this.grpLogin.TabIndex = 67;
this.grpLogin.TabStop = false;
//
// cmdConnect
//
this.cmdConnect.Location = new System.Drawing.Point(251, 62);
this.cmdConnect.Name = "cmdConnect";
this.cmdConnect.Size = new System.Drawing.Size(120, 24);
this.cmdConnect.TabIndex = 3;
this.cmdConnect.Text = "Connect";
this.cmdConnect.Click += new System.EventHandler(this.cmdConnect_Click);
//
// label3
//
this.label3.Location = new System.Drawing.Point(251, 20);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(120, 16);
this.label3.TabIndex = 72;
this.label3.Text = "Password";
//
// txtPassword
//
this.txtPassword.Location = new System.Drawing.Point(251, 36);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '*';
this.txtPassword.Size = new System.Drawing.Size(120, 20);
this.txtPassword.TabIndex = 2;
//
// label2
//
this.label2.Location = new System.Drawing.Point(132, 20);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(120, 16);
this.label2.TabIndex = 70;
this.label2.Text = "Last Name";
//
// txtLastName
//
this.txtLastName.Location = new System.Drawing.Point(132, 36);
this.txtLastName.Name = "txtLastName";
this.txtLastName.Size = new System.Drawing.Size(112, 20);
this.txtLastName.TabIndex = 1;
//
// label1
//
this.label1.Location = new System.Drawing.Point(6, 20);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(120, 16);
this.label1.TabIndex = 68;
this.label1.Text = "First Name";
//
// txtFirstName
//
this.txtFirstName.Location = new System.Drawing.Point(6, 36);
this.txtFirstName.Name = "txtFirstName";
this.txtFirstName.Size = new System.Drawing.Size(120, 20);
this.txtFirstName.TabIndex = 0;
//
// grpUpload
//
this.grpUpload.Controls.Add(this.txtAssetID);
this.grpUpload.Controls.Add(this.label4);
this.grpUpload.Controls.Add(this.lblSize);
this.grpUpload.Controls.Add(this.prgUpload);
this.grpUpload.Controls.Add(this.picPreview);
this.grpUpload.Controls.Add(this.cmdLoad);
this.grpUpload.Controls.Add(this.txtSendtoName);
this.grpUpload.Controls.Add(this.label6);
this.grpUpload.Controls.Add(this.chkLossless);
this.grpUpload.Controls.Add(this.cmdUpload);
this.grpUpload.Location = new System.Drawing.Point(12, 12);
this.grpUpload.Name = "grpUpload";
this.grpUpload.Size = new System.Drawing.Size(379, 242);
this.grpUpload.TabIndex = 68;
this.grpUpload.TabStop = false;
//
// txtAssetID
//
this.txtAssetID.Location = new System.Drawing.Point(90, 204);
this.txtAssetID.Name = "txtAssetID";
this.txtAssetID.ReadOnly = true;
this.txtAssetID.Size = new System.Drawing.Size(280, 20);
this.txtAssetID.TabIndex = 8;
this.txtAssetID.TabStop = false;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(6, 207);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(66, 13);
this.label4.TabIndex = 79;
this.label4.Text = "Asset UUID:";
//
// lblSize
//
this.lblSize.AutoSize = true;
this.lblSize.Location = new System.Drawing.Point(79, 96);
this.lblSize.Name = "lblSize";
this.lblSize.Size = new System.Drawing.Size(0, 13);
this.lblSize.TabIndex = 77;
//
// prgUpload
//
this.prgUpload.Location = new System.Drawing.Point(9, 175);
this.prgUpload.Name = "prgUpload";
this.prgUpload.Size = new System.Drawing.Size(362, 23);
this.prgUpload.TabIndex = 76;
//
// picPreview
//
this.picPreview.Location = new System.Drawing.Point(9, 96);
this.picPreview.Name = "picPreview";
this.picPreview.Size = new System.Drawing.Size(64, 64);
this.picPreview.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.picPreview.TabIndex = 75;
this.picPreview.TabStop = false;
//
// cmdLoad
//
this.cmdLoad.Location = new System.Drawing.Point(160, 136);
this.cmdLoad.Name = "cmdLoad";
this.cmdLoad.Size = new System.Drawing.Size(102, 24);
this.cmdLoad.TabIndex = 6;
this.cmdLoad.Text = "Load Texture";
this.cmdLoad.UseVisualStyleBackColor = true;
this.cmdLoad.Click += new System.EventHandler(this.cmdLoad_Click);
//
// txtSendtoName
//
this.txtSendtoName.Location = new System.Drawing.Point(131, 64);
this.txtSendtoName.Name = "txtSendtoName";
this.txtSendtoName.Size = new System.Drawing.Size(239, 20);
this.txtSendtoName.TabIndex = 5;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(6, 67);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(112, 13);
this.label6.TabIndex = 71;
this.label6.Text = "Send Copy To Avatar:";
//
// chkLossless
//
this.chkLossless.Location = new System.Drawing.Point(9, 19);
this.chkLossless.Name = "chkLossless";
this.chkLossless.Size = new System.Drawing.Size(362, 37);
this.chkLossless.TabIndex = 4;
this.chkLossless.Text = "Single Layer Lossless (only useful for pixel perfect reproductions of small image" +
"s, such as sculpt maps)";
this.chkLossless.UseVisualStyleBackColor = true;
this.chkLossless.CheckedChanged += new System.EventHandler(this.chkLossless_CheckedChanged);
//
// cmdUpload
//
this.cmdUpload.Enabled = false;
this.cmdUpload.Location = new System.Drawing.Point(268, 136);
this.cmdUpload.Name = "cmdUpload";
this.cmdUpload.Size = new System.Drawing.Size(103, 24);
this.cmdUpload.TabIndex = 7;
this.cmdUpload.Text = "Upload Texture";
this.cmdUpload.UseVisualStyleBackColor = true;
this.cmdUpload.Click += new System.EventHandler(this.cmdUpload_Click);
//
// frmSLImageUpload
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(402, 373);
this.Controls.Add(this.grpUpload);
this.Controls.Add(this.grpLogin);
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(410, 400);
this.MinimumSize = new System.Drawing.Size(410, 400);
this.Name = "frmSLImageUpload";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.Text = "SL Image Upload";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmSLImageUpload_FormClosed);
this.grpLogin.ResumeLayout(false);
this.grpLogin.PerformLayout();
this.grpUpload.ResumeLayout(false);
this.grpUpload.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picPreview)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox grpLogin;
private System.Windows.Forms.Button cmdConnect;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtLastName;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtFirstName;
private System.Windows.Forms.GroupBox grpUpload;
private System.Windows.Forms.Button cmdUpload;
private System.Windows.Forms.CheckBox chkLossless;
private System.Windows.Forms.TextBox txtSendtoName;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.PictureBox picPreview;
private System.Windows.Forms.Button cmdLoad;
private System.Windows.Forms.ProgressBar prgUpload;
private System.Windows.Forms.Label lblSize;
private System.Windows.Forms.TextBox txtAssetID;
private System.Windows.Forms.Label label4;
}
}

View File

@@ -0,0 +1,390 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Capabilities;
using OpenMetaverse.Imaging;
namespace SLImageUpload
{
public partial class frmSLImageUpload : Form
{
private GridClient Client;
private byte[] UploadData = null;
private int Transferred = 0;
private string FileName = String.Empty;
private LLUUID SendToID;
private LLUUID AssetID;
public frmSLImageUpload()
{
InitializeComponent();
InitClient();
}
private void InitClient()
{
Client = new GridClient();
Client.Network.OnEventQueueRunning += new NetworkManager.EventQueueRunningCallback(Network_OnEventQueueRunning);
Client.Network.OnLogin += new NetworkManager.LoginCallback(Network_OnLogin);
// Turn almost everything off since we are only interested in uploading textures
Settings.LOG_LEVEL = Helpers.LogLevel.None;
Client.Settings.ALWAYS_DECODE_OBJECTS = false;
Client.Settings.ALWAYS_REQUEST_OBJECTS = false;
Client.Settings.SEND_AGENT_UPDATES = true;
Client.Settings.OBJECT_TRACKING = false;
Client.Settings.STORE_LAND_PATCHES = false;
Client.Settings.MULTIPLE_SIMS = false;
Client.Self.Movement.Camera.Far = 32.0f;
Client.Throttle.Cloud = 0.0f;
Client.Throttle.Land = 0.0f;
Client.Throttle.Wind = 0.0f;
Client.Throttle.Texture = 446000.0f;
}
private void EnableUpload()
{
if (UploadData != null)
{
if (this.InvokeRequired)
BeginInvoke(new MethodInvoker(EnableUpload));
else
cmdUpload.Enabled = true;
}
}
private void DisableUpload()
{
if (this.InvokeRequired)
BeginInvoke(new MethodInvoker(DisableUpload));
else
cmdUpload.Enabled = false;
}
private void UpdateAssetID()
{
if (this.InvokeRequired)
BeginInvoke(new MethodInvoker(UpdateAssetID));
else
txtAssetID.Text = AssetID.ToString();
}
private void LoadImage()
{
if (FileName == null || FileName == "")
return;
string lowfilename = FileName.ToLower();
Bitmap bitmap = null;
try
{
if (lowfilename.EndsWith(".jp2") || lowfilename.EndsWith(".j2c"))
{
Image image;
ManagedImage managedImage;
// Upload JPEG2000 images untouched
UploadData = System.IO.File.ReadAllBytes(FileName);
OpenJPEG.DecodeToImage(UploadData, out managedImage, out image);
bitmap = (Bitmap)image;
Logger.Log("Loaded raw JPEG2000 data " + FileName, Helpers.LogLevel.Info, Client);
}
else
{
if (lowfilename.EndsWith(".tga"))
bitmap = LoadTGAClass.LoadTGA(FileName);
else
bitmap = (Bitmap)System.Drawing.Image.FromFile(FileName);
Logger.Log("Loaded image " + FileName, Helpers.LogLevel.Info, Client);
int oldwidth = bitmap.Width;
int oldheight = bitmap.Height;
if (!IsPowerOfTwo((uint)oldwidth) || !IsPowerOfTwo((uint)oldheight))
{
Logger.Log("Image has irregular dimensions " + oldwidth + "x" + oldheight + ", resizing to 256x256",
Helpers.LogLevel.Info, Client);
Bitmap resized = new Bitmap(256, 256, bitmap.PixelFormat);
Graphics graphics = Graphics.FromImage(resized);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(bitmap, 0, 0, 256, 256);
bitmap.Dispose();
bitmap = resized;
oldwidth = 256;
oldheight = 256;
}
// Handle resizing to prevent excessively large images
if (oldwidth > 1024 || oldheight > 1024)
{
int newwidth = (oldwidth > 1024) ? 1024 : oldwidth;
int newheight = (oldheight > 1024) ? 1024 : oldheight;
Logger.Log("Image has oversized dimensions " + oldwidth + "x" + oldheight + ", resizing to " +
newwidth + "x" + newheight, Helpers.LogLevel.Info, Client);
Bitmap resized = new Bitmap(newwidth, newheight, bitmap.PixelFormat);
Graphics graphics = Graphics.FromImage(resized);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(bitmap, 0, 0, newwidth, newheight);
bitmap.Dispose();
bitmap = resized;
}
Logger.Log("Encoding image...", Helpers.LogLevel.Info, Client);
UploadData = OpenJPEG.EncodeFromImage(bitmap, chkLossless.Checked);
Logger.Log("Finished encoding", Helpers.LogLevel.Info, Client);
}
}
catch (Exception ex)
{
UploadData = null;
cmdUpload.Enabled = false;
MessageBox.Show(ex.ToString(), "SL Image Upload", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
picPreview.Image = bitmap;
lblSize.Text = Math.Round((double)UploadData.Length / 1024.0d, 2) + "KB";
prgUpload.Maximum = UploadData.Length;
if (Client.Network.Connected) cmdUpload.Enabled = true;
}
private void cmdConnect_Click(object sender, EventArgs e)
{
if (cmdConnect.Text == "Connect") {
cmdConnect.Text = "Disconnect";
txtFirstName.Enabled = txtLastName.Enabled = txtPassword.Enabled = false;
LoginParams lp = new LoginParams();
lp.FirstName = txtFirstName.Text;
lp.LastName = txtLastName.Text;
lp.Password = txtPassword.Text;
lp.URI = Client.Settings.LOGIN_SERVER;
lp.Start = "last";
cmdConnect.Enabled = false;
Client.Network.BeginLogin(lp);
return;
} else {
Client.Network.Logout();
cmdConnect.Text = "Connect";
txtFirstName.Enabled = txtLastName.Enabled = txtPassword.Enabled = true;
DisableUpload();
InitClient();
}
}
void Network_OnLogin(LoginStatus login, string message)
{
if (InvokeRequired) {
BeginInvoke(new MethodInvoker(
delegate()
{
Network_OnLogin(login, message);
}
));
return;
}
if (login == LoginStatus.Success) {
MessageBox.Show("Connected: " + message);
cmdConnect.Enabled = true;
} else if (login == LoginStatus.Failed) {
MessageBox.Show(this, String.Format("Error logging in ({0}): {1}", Client.Network.LoginErrorKey,
Client.Network.LoginMessage));
cmdConnect.Text = "Connect";
cmdConnect.Enabled = true;
txtFirstName.Enabled = txtLastName.Enabled = txtPassword.Enabled = true;
DisableUpload();
}
}
private void cmdLoad_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter =
"Image Files (*.jp2,*.j2c,*.jpg,*.jpeg,*.gif,*.png,*.bmp,*.tga,*.tif,*.tiff,*.ico,*.wmf,*.emf)|" +
"*.jp2;*.j2c;*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.tga;*.tif;*.tiff;*.ico;*.wmf;*.emf;";
if (dialog.ShowDialog() == DialogResult.OK)
{
FileName = dialog.FileName;
LoadImage();
}
}
private void cmdUpload_Click(object sender, EventArgs e)
{
SendToID = LLUUID.Zero;
string sendTo = txtSendtoName.Text.Trim();
if (sendTo.Length > 0)
{
AutoResetEvent lookupEvent = new AutoResetEvent(false);
LLUUID thisQueryID = LLUUID.Random();
bool lookupSuccess = false;
DirectoryManager.DirPeopleReplyCallback callback =
delegate(LLUUID queryID, List<DirectoryManager.AgentSearchData> matchedPeople)
{
if (queryID == thisQueryID)
{
if (matchedPeople.Count > 0)
{
SendToID = matchedPeople[0].AgentID;
lookupSuccess = true;
}
lookupEvent.Set();
}
};
Client.Directory.OnDirPeopleReply += callback;
Client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, sendTo, 0, thisQueryID);
bool eventSuccess = lookupEvent.WaitOne(10 * 1000, false);
Client.Directory.OnDirPeopleReply -= callback;
if (eventSuccess && lookupSuccess)
{
Logger.Log("Will send uploaded image to avatar " + SendToID.ToString(), Helpers.LogLevel.Info, Client);
}
else
{
MessageBox.Show("Could not find avatar \"" + sendTo + "\", upload cancelled");
return;
}
}
if (UploadData != null)
{
prgUpload.Value = 0;
cmdLoad.Enabled = false;
cmdUpload.Enabled = false;
grpLogin.Enabled = false;
string name = System.IO.Path.GetFileNameWithoutExtension(FileName);
Client.Inventory.RequestCreateItemFromAsset(UploadData, name, "Uploaded with SL Image Upload", AssetType.Texture,
InventoryType.Texture, Client.Inventory.FindFolderForType(AssetType.Texture),
delegate(CapsClient client, long bytesReceived, long bytesSent, long totalBytesToReceive, long totalBytesToSend)
{
if (bytesSent > 0)
{
Transferred = (int)bytesSent;
BeginInvoke((MethodInvoker)delegate() { SetProgress(); });
}
},
delegate(bool success, string status, LLUUID itemID, LLUUID assetID)
{
if (this.InvokeRequired)
BeginInvoke(new MethodInvoker(EnableControls));
else
EnableControls();
if (success)
{
AssetID = assetID;
UpdateAssetID();
// Fix the permissions on the new upload since they are fscked by default
InventoryItem item = Client.Inventory.FetchItem(itemID, Client.Self.AgentID, 1000 * 15);
Transferred = UploadData.Length;
BeginInvoke((MethodInvoker)delegate() { SetProgress(); });
if (item != null)
{
item.Permissions.EveryoneMask = PermissionMask.All;
item.Permissions.NextOwnerMask = PermissionMask.All;
Client.Inventory.RequestUpdateItem(item);
Logger.Log("Created inventory item " + itemID.ToString(), Helpers.LogLevel.Info, Client);
MessageBox.Show("Created inventory item " + itemID.ToString());
// FIXME: We should be watching the callback for RequestUpdateItem instead of a dumb sleep
System.Threading.Thread.Sleep(2000);
if (SendToID != LLUUID.Zero)
{
Logger.Log("Sending item to " + SendToID.ToString(), Helpers.LogLevel.Info, Client);
Client.Inventory.GiveItem(itemID, name, AssetType.Texture, SendToID, true);
MessageBox.Show("Sent item to " + SendToID.ToString());
}
}
else
{
Logger.DebugLog("Created inventory item " + itemID.ToString() + " but failed to fetch it," +
" cannot update permissions or send to another avatar", Client);
MessageBox.Show("Created inventory item " + itemID.ToString() + " but failed to fetch it," +
" cannot update permissions or send to another avatar");
}
}
else
{
MessageBox.Show("Asset upload failed: " + status);
}
}
);
}
}
private void SetProgress()
{
prgUpload.Value = Transferred;
}
private void Network_OnEventQueueRunning(Simulator simulator)
{
Logger.DebugLog("Event queue is running for " + simulator.ToString() + ", enabling uploads", Client);
EnableUpload();
}
private void EnableControls()
{
cmdLoad.Enabled = true;
cmdUpload.Enabled = true;
grpLogin.Enabled = true;
}
private void frmSLImageUpload_FormClosed(object sender, FormClosedEventArgs e)
{
if (Client.Network.Connected)
Client.Network.Logout();
}
private void chkLossless_CheckedChanged(object sender, EventArgs e)
{
LoadImage();
}
private bool IsPowerOfTwo(uint n)
{
return (n & (n - 1)) == 0 && n != 0;
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

732
Programs/SLProxy/Analyst.cs Normal file
View File

@@ -0,0 +1,732 @@
/*
* Analyst.cs: proxy that makes packet inspection and modifcation interactive
* See the README for usage instructions.
*
* Copyright (c) 2006 Austin Jennings
* Modified by "qode" and "mcortez" on December 21st, 2006 to work with the new
* pregen
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using SLProxy;
using OpenMetaverse;
using Nwc.XmlRpc;
using OpenMetaverse.Packets;
using System.Reflection;
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
public class Analyst : ProxyPlugin
{
private ProxyFrame frame;
private Proxy proxy;
private Hashtable loggedPackets = new Hashtable();
private string logGrep = null;
private Hashtable modifiedPackets = new Hashtable();
private Assembly openmvAssembly;
public Analyst(ProxyFrame frame)
{
this.frame = frame;
this.proxy = frame.proxy;
}
public override void Init()
{
openmvAssembly = Assembly.Load("OpenMetaverse");
if (openmvAssembly == null) throw new Exception("Assembly load exception");
// build the table of /command delegates
InitializeCommandDelegates();
// handle command line arguments
foreach (string arg in frame.Args)
if (arg == "--log-all")
LogAll();
Console.WriteLine("Analyst loaded");
}
// InitializeCommandDelegates: configure Analyst's commands
private void InitializeCommandDelegates()
{
frame.AddCommand("/log", new ProxyFrame.CommandDelegate(CmdLog));
frame.AddCommand("/-log", new ProxyFrame.CommandDelegate(CmdNoLog));
frame.AddCommand("/grep", new ProxyFrame.CommandDelegate(CmdGrep));
frame.AddCommand("/set", new ProxyFrame.CommandDelegate(CmdSet));
frame.AddCommand("/-set", new ProxyFrame.CommandDelegate(CmdNoSet));
frame.AddCommand("/inject", new ProxyFrame.CommandDelegate(CmdInject));
frame.AddCommand("/in", new ProxyFrame.CommandDelegate(CmdInject));
}
private static PacketType packetTypeFromName(string name)
{
Type packetTypeType = typeof(PacketType);
System.Reflection.FieldInfo f = packetTypeType.GetField(name);
if (f == null) throw new ArgumentException("Bad packet type");
return (PacketType)Enum.ToObject(packetTypeType, (int)f.GetValue(packetTypeType));
}
// CmdLog: handle a /log command
private void CmdLog(string[] words)
{
if (words.Length != 2)
SayToUser("Usage: /log <packet name>");
else if (words[1] == "*")
{
LogAll();
SayToUser("logging all packets");
}
else
{
PacketType pType;
try
{
pType = packetTypeFromName(words[1]);
}
catch (ArgumentException)
{
SayToUser("Bad packet name: " + words[1]);
return;
}
loggedPackets[pType] = null;
proxy.AddDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn));
proxy.AddDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut));
SayToUser("logging " + words[1]);
}
}
// CmdNoLog: handle a /-log command
private void CmdNoLog(string[] words)
{
if (words.Length != 2)
SayToUser("Usage: /-log <packet name>");
else if (words[1] == "*")
{
NoLogAll();
SayToUser("stopped logging all packets");
}
else
{
PacketType pType = packetTypeFromName(words[1]);
loggedPackets.Remove(pType);
proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn));
proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut));
SayToUser("stopped logging " + words[1]);
}
}
// CmdGrep: handle a /grep command
private void CmdGrep(string[] words) {
if (words.Length == 1) {
logGrep = null;
SayToUser("stopped filtering logs");
} else {
string[] regexArray = new string[words.Length - 1];
Array.Copy(words, 1, regexArray, 0, words.Length - 1);
logGrep = String.Join(" ", regexArray);
SayToUser("filtering log with " + logGrep);
}
}
// CmdSet: handle a /set command
private void CmdSet(string[] words)
{
if (words.Length < 5)
SayToUser("Usage: /set <packet name> <block> <field> <value>");
else
{
PacketType pType;
try
{
pType = packetTypeFromName(words[1]);
}
catch (ArgumentException)
{
SayToUser("Bad packet name: " + words[1]);
return;
}
string[] valueArray = new string[words.Length - 4];
Array.Copy(words, 4, valueArray, 0, words.Length - 4);
string valueString = String.Join(" ", valueArray);
object value;
try
{
value = MagicCast(words[1], words[2], words[3], valueString);
}
catch (Exception e)
{
SayToUser(e.Message);
return;
}
Hashtable fields;
if (modifiedPackets.Contains(pType))
fields = (Hashtable)modifiedPackets[pType];
else
fields = new Hashtable();
fields[new BlockField(words[2], words[3])] = value;
modifiedPackets[pType] = fields;
proxy.AddDelegate(pType, Direction.Incoming, new PacketDelegate(ModifyIn));
proxy.AddDelegate(pType, Direction.Outgoing, new PacketDelegate(ModifyOut));
SayToUser("setting " + words[1] + "." + words[2] + "." + words[3] + " = " + valueString);
}
}
// CmdNoSet: handle a /-set command
private void CmdNoSet(string[] words)
{
if (words.Length == 2 && words[1] == "*")
{
foreach (PacketType pType in modifiedPackets.Keys)
{
proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(ModifyIn));
proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(ModifyOut));
}
modifiedPackets = new Hashtable();
SayToUser("stopped setting all fields");
}
else if (words.Length == 4)
{
PacketType pType;
try
{
pType = packetTypeFromName(words[1]);
}
catch (ArgumentException)
{
SayToUser("Bad packet name: " + words[1]);
return;
}
if (modifiedPackets.Contains(pType))
{
Hashtable fields = (Hashtable)modifiedPackets[pType];
fields.Remove(new BlockField(words[2], words[3]));
if (fields.Count == 0)
{
modifiedPackets.Remove(pType);
proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(ModifyIn));
proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(ModifyOut));
}
}
SayToUser("stopped setting " + words[1] + "." + words[2] + "." + words[3]);
}
else
SayToUser("Usage: /-set <packet name> <block> <field>");
}
// CmdInject: handle an /inject command
private void CmdInject(string[] words)
{
if (words.Length < 2)
SayToUser("Usage: /inject <packet file> [value]");
else
{
string[] valueArray = new string[words.Length - 2];
Array.Copy(words, 2, valueArray, 0, words.Length - 2);
string value = String.Join(" ", valueArray);
FileStream fs = null;
StreamReader sr = null;
Direction direction = Direction.Incoming;
string name = null;
string block = null;
object blockObj = null;
Type packetClass = null;
Packet packet = null;
try
{
fs = File.OpenRead(words[1] + ".packet");
sr = new StreamReader(fs);
string line;
while ((line = sr.ReadLine()) != null)
{
Match match;
if (name == null)
{
match = (new Regex(@"^\s*(in|out)\s+(\w+)\s*$")).Match(line);
if (!match.Success)
{
SayToUser("expecting direction and packet name, got: " + line);
return;
}
string lineDir = match.Groups[1].Captures[0].ToString();
string lineName = match.Groups[2].Captures[0].ToString();
if (lineDir == "in")
direction = Direction.Incoming;
else if (lineDir == "out")
direction = Direction.Outgoing;
else
{
SayToUser("expecting 'in' or 'out', got: " + line);
return;
}
name = lineName;
packetClass = openmvAssembly.GetType("OpenMetaverse.Packets." + name + "Packet");
if (packetClass == null) throw new Exception("Couldn't get class " + name + "Packet");
ConstructorInfo ctr = packetClass.GetConstructor(new Type[] { });
if (ctr == null) throw new Exception("Couldn't get suitable constructor for " + name + "Packet");
packet = (Packet)ctr.Invoke(new object[] { });
//Console.WriteLine("Created new " + name + "Packet");
}
else
{
match = (new Regex(@"^\s*\[(\w+)\]\s*$")).Match(line);
if (match.Success)
{
block = match.Groups[1].Captures[0].ToString();
FieldInfo blockField = packetClass.GetField(block);
if (blockField == null) throw new Exception("Couldn't get " + name + "Packet." + block);
Type blockClass = blockField.FieldType;
if (blockClass.IsArray)
{
blockClass = blockClass.GetElementType();
ConstructorInfo ctr = blockClass.GetConstructor(new Type[] { });
if (ctr == null) throw new Exception("Couldn't get suitable constructor for " + blockClass.Name);
blockObj = ctr.Invoke(new object[] { });
object[] arr = (object[])blockField.GetValue(packet);
object[] narr = (object[])Array.CreateInstance(blockClass, arr.Length + 1);
Array.Copy(arr, narr, arr.Length);
narr[arr.Length] = blockObj;
blockField.SetValue(packet, narr);
//Console.WriteLine("Added block "+block);
}
else
{
blockObj = blockField.GetValue(packet);
}
if (blockObj == null) throw new Exception("Got " + name + "Packet." + block + " == null");
//Console.WriteLine("Got block " + name + "Packet." + block);
continue;
}
if (block == null)
{
SayToUser("expecting block name, got: " + line);
return;
}
match = (new Regex(@"^\s*(\w+)\s*=\s*(.*)$")).Match(line);
if (match.Success)
{
string lineField = match.Groups[1].Captures[0].ToString();
string lineValue = match.Groups[2].Captures[0].ToString();
object fval;
//FIXME: use of MagicCast inefficient
if (lineValue == "$Value")
fval = MagicCast(name, block, lineField, value);
else if (lineValue == "$UUID")
fval = LLUUID.Random();
else if (lineValue == "$AgentID")
fval = frame.AgentID;
else if (lineValue == "$SessionID")
fval = frame.SessionID;
else
fval = MagicCast(name, block, lineField, lineValue);
MagicSetField(blockObj, lineField, fval);
continue;
}
SayToUser("expecting block name or field, got: " + line);
return;
}
}
if (name == null)
{
SayToUser("expecting direction and packet name, got EOF");
return;
}
packet.Header.Flags |= Helpers.MSG_RELIABLE;
//if (protocolManager.Command(name).Encoded)
// packet.Header.Flags |= Helpers.MSG_ZEROCODED;
proxy.InjectPacket(packet, direction);
SayToUser("injected " + words[1]);
}
catch (Exception e)
{
SayToUser("failed to inject " + words[1] + ": " + e.Message);
Console.WriteLine("failed to inject " + words[1] + ": " + e.Message + "\n" + e.StackTrace);
}
finally
{
if (fs != null)
fs.Close();
if (sr != null)
sr.Close();
}
}
}
// SayToUser: send a message to the user as in-world chat
private void SayToUser(string message)
{
ChatFromSimulatorPacket packet = new ChatFromSimulatorPacket();
packet.ChatData.FromName = Helpers.StringToField("Analyst");
packet.ChatData.SourceID = LLUUID.Random();
packet.ChatData.OwnerID = frame.AgentID;
packet.ChatData.SourceType = (byte)2;
packet.ChatData.ChatType = (byte)1;
packet.ChatData.Audible = (byte)1;
packet.ChatData.Position = new LLVector3(0, 0, 0);
packet.ChatData.Message = Helpers.StringToField(message);
proxy.InjectPacket(packet, Direction.Incoming);
}
// BlockField: product type for a block name and field name
private struct BlockField
{
public string block;
public string field;
public BlockField(string block, string field)
{
this.block = block;
this.field = field;
}
}
private static void MagicSetField(object obj, string field, object val)
{
Type cls = obj.GetType();
FieldInfo fieldInf = cls.GetField(field);
if (fieldInf == null)
{
PropertyInfo prop = cls.GetProperty(field);
if (prop == null) throw new Exception("Couldn't find field " + cls.Name + "." + field);
prop.SetValue(obj, val, null);
//throw new Exception("FIXME: can't set properties");
}
else
{
fieldInf.SetValue(obj, val);
}
}
// MagicCast: given a packet/block/field name and a string, convert the string to a value of the appropriate type
private object MagicCast(string name, string block, string field, string value)
{
Type packetClass = openmvAssembly.GetType("OpenMetaverse.Packets." + name + "Packet");
if (packetClass == null) throw new Exception("Couldn't get class " + name + "Packet");
FieldInfo blockField = packetClass.GetField(block);
if (blockField == null) throw new Exception("Couldn't get " + name + "Packet." + block);
Type blockClass = blockField.FieldType;
if (blockClass.IsArray) blockClass = blockClass.GetElementType();
// Console.WriteLine("DEBUG: " + blockClass.Name);
FieldInfo fieldField = blockClass.GetField(field); PropertyInfo fieldProp = null;
Type fieldClass = null;
if (fieldField == null)
{
fieldProp = blockClass.GetProperty(field);
if (fieldProp == null) throw new Exception("Couldn't get " + name + "Packet." + block + "." + field);
fieldClass = fieldProp.PropertyType;
}
else
{
fieldClass = fieldField.FieldType;
}
try
{
if (fieldClass == typeof(byte))
{
return Convert.ToByte(value);
}
else if (fieldClass == typeof(ushort))
{
return Convert.ToUInt16(value);
}
else if (fieldClass == typeof(uint))
{
return Convert.ToUInt32(value);
}
else if (fieldClass == typeof(ulong))
{
return Convert.ToUInt64(value);
}
else if (fieldClass == typeof(sbyte))
{
return Convert.ToSByte(value);
}
else if (fieldClass == typeof(short))
{
return Convert.ToInt16(value);
}
else if (fieldClass == typeof(int))
{
return Convert.ToInt32(value);
}
else if (fieldClass == typeof(long))
{
return Convert.ToInt64(value);
}
else if (fieldClass == typeof(float))
{
return Convert.ToSingle(value);
}
else if (fieldClass == typeof(double))
{
return Convert.ToDouble(value);
}
else if (fieldClass == typeof(LLUUID))
{
return new LLUUID(value);
}
else if (fieldClass == typeof(bool))
{
if (value.ToLower() == "true")
return true;
else if (value.ToLower() == "false")
return false;
else
throw new Exception();
}
else if (fieldClass == typeof(byte[]))
{
return Helpers.StringToField(value);
}
else if (fieldClass == typeof(LLVector3))
{
LLVector3 result;
if(LLVector3.TryParse(value, out result))
return result;
else
throw new Exception();
}
else if (fieldClass == typeof(LLVector3d))
{
LLVector3d result;
if (LLVector3d.TryParse(value, out result))
return result;
else
throw new Exception();
}
else if (fieldClass == typeof(LLVector4))
{
LLVector4 result;
if (LLVector4.TryParse(value, out result))
return result;
else
throw new Exception();
}
else if (fieldClass == typeof(LLQuaternion))
{
LLQuaternion result;
if (LLQuaternion.TryParse(value, out result))
return result;
else
throw new Exception();
}
else
{
throw new Exception("unsupported field type " + fieldClass);
}
}
catch
{
throw new Exception("unable to interpret " + value + " as " + fieldClass);
}
}
// ModifyIn: modify an incoming packet
private Packet ModifyIn(Packet packet, IPEndPoint endPoint)
{
return Modify(packet, endPoint, Direction.Incoming);
}
// ModifyOut: modify an outgoing packet
private Packet ModifyOut(Packet packet, IPEndPoint endPoint)
{
return Modify(packet, endPoint, Direction.Outgoing);
}
// Modify: modify a packet
private Packet Modify(Packet packet, IPEndPoint endPoint, Direction direction)
{
if (modifiedPackets.Contains(packet.Type))
{
try
{
Hashtable changes = (Hashtable)modifiedPackets[packet.Type];
Type packetClass = packet.GetType();
foreach (BlockField bf in changes.Keys)
{
//FIXME: support variable blocks
FieldInfo blockField = packetClass.GetField(bf.block);
//Type blockClass = blockField.FieldType;
object blockObject = blockField.GetValue(packet);
MagicSetField(blockObject, bf.field, changes[blockField]);
}
}
catch (Exception e)
{
Console.WriteLine("failed to modify " + packet.Type + ": " + e.Message);
Console.WriteLine(e.StackTrace);
}
}
return packet;
}
// LogPacketIn: log an incoming packet
private Packet LogPacketIn(Packet packet, IPEndPoint endPoint)
{
LogPacket(packet, endPoint, Direction.Incoming);
return packet;
}
// LogPacketOut: log an outgoing packet
private Packet LogPacketOut(Packet packet, IPEndPoint endPoint)
{
LogPacket(packet, endPoint, Direction.Outgoing);
return packet;
}
// LogAll: register logging delegates for all packets
private void LogAll()
{
Type packetTypeType = typeof(PacketType);
System.Reflection.MemberInfo[] packetTypes = packetTypeType.GetMembers();
for (int i = 0; i < packetTypes.Length; i++)
{
if (packetTypes[i].MemberType == System.Reflection.MemberTypes.Field && packetTypes[i].DeclaringType == packetTypeType)
{
string name = packetTypes[i].Name;
PacketType pType;
try
{
pType = packetTypeFromName(name);
}
catch (Exception)
{
continue;
}
loggedPackets[pType] = null;
proxy.AddDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn));
proxy.AddDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut));
}
}
}
// NoLogAll: unregister logging delegates for all packets
private void NoLogAll()
{
Type packetTypeType = typeof(PacketType);
System.Reflection.MemberInfo[] packetTypes = packetTypeType.GetMembers();
for (int i = 0; i < packetTypes.Length; i++)
{
if (packetTypes[i].MemberType == System.Reflection.MemberTypes.Field && packetTypes[i].DeclaringType == packetTypeType)
{
string name = packetTypes[i].Name;
PacketType pType;
try
{
pType = packetTypeFromName(name);
}
catch (Exception)
{
continue;
}
loggedPackets.Remove(pType);
proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn));
proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut));
}
}
}
// LogPacket: dump a packet to the console
private void LogPacket(Packet packet, IPEndPoint endPoint, Direction direction)
{
string packetText = packet.ToString();
if (logGrep == null || (logGrep != null && Regex.IsMatch(packetText, logGrep)))
{
Console.WriteLine("{0} {1,21} {2,5} {3}{4}{5}"
, direction == Direction.Incoming ? "<--" : "-->"
, endPoint
, packet.Header.Sequence
, InterpretOptions(packet.Header.Flags)
, Environment.NewLine
, packetText
);
}
}
// InterpretOptions: produce a string representing a packet's header options
private static string InterpretOptions(byte options)
{
return "["
+ ((options & Helpers.MSG_APPENDED_ACKS) != 0 ? "Ack" : " ")
+ " "
+ ((options & Helpers.MSG_RESENT) != 0 ? "Res" : " ")
+ " "
+ ((options & Helpers.MSG_RELIABLE) != 0 ? "Rel" : " ")
+ " "
+ ((options & Helpers.MSG_ZEROCODED) != 0 ? "Zer" : " ")
+ "]"
;
}
}

View File

@@ -0,0 +1,107 @@
/*
* ChatConsole.cs: sample SLProxy appliation that writes chat to the console.
* Typing on the console will send chat to the grid.
*
* Copyright (c) 2006 Austin Jennings
* Modified by Andrew Ortman ("qode") on Decemeber 21, 2006 to work with the new pregen proxy.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using SLProxy;
using OpenMetaverse;
using OpenMetaverse.Packets;
using Nwc.XmlRpc;
using System;
using System.Collections;
using System.Net;
using System.Threading;
public class ChatConsole {
private static Proxy proxy;
private static LLUUID agentID;
private static LLUUID sessionID;
public static void Main(string[] args) {
// configure the proxy
ProxyConfig proxyConfig = new ProxyConfig("ChatConsole V2", "Austin Jennings / Andrew Ortman", args);
proxy = new Proxy(proxyConfig);
// set a delegate for when the client logs in
proxy.SetLoginResponseDelegate(new XmlRpcResponseDelegate(Login));
// add a delegate for incoming chat
proxy.AddDelegate(PacketType.ChatFromSimulator, Direction.Incoming, new PacketDelegate(ChatFromSimulator));
// start the proxy
proxy.Start();
}
private static void Login(XmlRpcResponse response) {
Hashtable values = (Hashtable)response.Value;
if (values.Contains("agent_id") && values.Contains("session_id")) {
// remember our agentID and sessionID
agentID = new LLUUID((string)values["agent_id"]);
sessionID = new LLUUID((string)values["session_id"]);
// start a new thread that reads lines from the console
(new Thread(new ThreadStart(ReadFromConsole))).Start();
}
}
private static void ReadFromConsole() {
// send text from the console in an infinite loop
for (;;) {
// read a line from the console
string message = Console.ReadLine();
// construct a ChatFromViewer packet
ChatFromViewerPacket chat = new ChatFromViewerPacket();
chat.ChatData.Channel = 0;
chat.ChatData.Message = Helpers.StringToField(message);
chat.ChatData.Type = (byte)1;
chat.AgentData.AgentID = agentID;
chat.AgentData.SessionID = sessionID;
// inject the packet
proxy.InjectPacket((Packet)chat, Direction.Outgoing);
}
}
private static Packet ChatFromSimulator(Packet packet, IPEndPoint sim) {
// deconstruct the packet
ChatFromSimulatorPacket chat = (ChatFromSimulatorPacket)packet;
string message = Helpers.FieldToUTF8String(chat.ChatData.Message);
string name = Helpers.FieldToUTF8String(chat.ChatData.FromName);
byte audible = chat.ChatData.Audible;
byte type = chat.ChatData.ChatType;
// if this was a normal, audible message, write it to the console
if (audible != 0 && (type == 0 || type == 1 || type == 2))
Console.WriteLine(name + ": " + message);
// return the packet unmodified
return packet;
}
}

View File

@@ -0,0 +1,121 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D8ECCBE1-AC71-4054-AAA6-2D50E5629504}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>ChatConsole</AssemblyName>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>Exe</OutputType>
<RootNamespace>ChatConsole</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>
</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>..\bin\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>..\..\bin\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-docs|AnyCPU' ">
<OutputPath>bin\Release-docs\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<Optimize>true</Optimize>
<DebugType>
</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
<ProjectReference Include="..\libsecondlife\OpenMetaverse.csproj">
<Project>{D9CDEDFB-8169-4B03-B57F-0DF638F044EC}</Project>
<Name>OpenMetaverse</Name>
</ProjectReference>
<ProjectReference Include="SLProxy.csproj">
<Name>SLProxy</Name>
<Project>{E4115DC9-FC88-47D6-B3B6-2400AD19B80D}</Project>
<Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="ChatConsole.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,809 @@
/*
* ClientAO.cs: SLProxy application that acts as a client side animation overrider.
* The application will start and stop animations corresponding to the movements
* of the avatar on screen.
*
* Copyright (c) 2007 Gilbert Roulot
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the Second Life Reverse Engineering Team nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using SLProxy;
using libsecondlife;
using libsecondlife.Packets;
using libsecondlife.StructuredData;
using Nwc.XmlRpc;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Reflection;
public class ClientAO : ProxyPlugin
{
private ProxyFrame frame;
private Proxy proxy;
private LLUUID[] wetikonanims = {
Animations.WALK,
Animations.RUN,
Animations.CROUCHWALK,
Animations.FLY,
Animations.TURNLEFT,
Animations.TURNRIGHT,
Animations.JUMP,
Animations.HOVER_UP,
Animations.CROUCH,
Animations.HOVER_DOWN,
Animations.STAND,
Animations.STAND_1,
Animations.STAND_2,
Animations.STAND_3,
Animations.STAND_4,
Animations.HOVER,
Animations.SIT,
Animations.PRE_JUMP,
Animations.FALLDOWN,
Animations.LAND,
Animations.STANDUP,
Animations.FLYSLOW,
Animations.SIT_GROUND_staticRAINED,
LLUUID.Zero, //swimming doesnt exist
LLUUID.Zero,
LLUUID.Zero,
LLUUID.Zero
};
private string[] wetikonanimnames = {
"walk",
"run",
"crouch walk",
"fly",
"turn left",
"turn right",
"jump",
"hover up",
"crouch",
"hover down",
"stand",
"stand 2",
"stand 3",
"stand 4",
"stand 5",
"hover",
"sit",
"pre jump",
"fall down",
"land",
"stand up",
"fly slow",
"sit on ground",
"swim (ignored)", //swimming doesnt exist
"swim (ignored)",
"swim (ignored)",
"swim (ignored)"
};
private Dictionary<LLUUID, string> animuid2name;
//private Assembly libslAssembly;
#region Packet delegates members
private PacketDelegate _packetDelegate;
private PacketDelegate packetDelegate
{
get
{
if (_packetDelegate == null)
{
_packetDelegate = new PacketDelegate(AnimationPacketHandler);
}
return _packetDelegate;
}
}
private PacketDelegate _inventoryPacketDelegate;
private PacketDelegate inventoryPacketDelegate
{
get
{
if (_inventoryPacketDelegate == null)
{
_inventoryPacketDelegate = new PacketDelegate(InventoryDescendentsHandler);
}
return _inventoryPacketDelegate;
}
}
private PacketDelegate _transferPacketDelegate;
private PacketDelegate transferPacketDelegate
{
get
{
if (_transferPacketDelegate == null)
{
_transferPacketDelegate = new PacketDelegate(TransferPacketHandler);
}
return _transferPacketDelegate;
}
}
private PacketDelegate _transferInfoDelegate;
private PacketDelegate transferInfoDelegate
{
get
{
if (_transferInfoDelegate == null)
{
_transferInfoDelegate = new PacketDelegate(TransferInfoHandler);
}
return _transferInfoDelegate;
}
}
#endregion
//map of built in SL animations and their overrides
private Dictionary<LLUUID,LLUUID> overrides = new Dictionary<LLUUID,LLUUID>();
//list of animations currently running
private Dictionary<LLUUID, int> SignaledAnimations = new Dictionary<LLUUID, int>();
//playing status of animations'override animation
private Dictionary<LLUUID, bool> overrideanimationisplaying;
//Current inventory path search
string[] searchPath;
//Search level
int searchLevel;
//Current folder
LLUUID currentFolder;
// Number of directory descendents received
int nbdescendantsreceived;
//List of items in the current folder
Dictionary<string,InventoryItem> currentFolderItems;
//Asset download request ID
LLUUID assetdownloadID;
//Downloaded bytes so far
int downloadedbytes;
//size of download
int downloadsize;
//data buffer
byte[] buffer;
public ClientAO(ProxyFrame frame)
{
this.frame = frame;
this.proxy = frame.proxy;
}
//Initialise the plugin
public override void Init()
{
//libslAssembly = Assembly.Load("libsecondlife");
//if (libslAssembly == null) throw new Exception("Assembly load exception");
// build the table of /command delegates
InitializeCommandDelegates();
SayToUser("ClientAO loaded");
}
// InitializeCommandDelegates: configure ClientAO's commands
private void InitializeCommandDelegates()
{
//The ClientAO responds to command beginning with /ao
frame.AddCommand("/ao", new ProxyFrame.CommandDelegate(CmdAO));
}
//Process commands from the user
private void CmdAO(string[] words) {
if (words.Length < 2)
{
SayToUser("Usage: /ao on/off/notecard path");
}
else if (words[1] == "on")
{
//Turn AO on
AOOn();
SayToUser("AO started");
}
else if (words[1] == "off")
{
//Turn AO off
AOOff();
SayToUser("AO stopped");
}
else
{
//Load notecard from path
//exemple: /ao Objects/My AOs/wetikon/config.txt
string[] tmp = new string[words.Length - 1];
//join the arguments together with spaces, to
//take care of folder and item names with spaces in them
for (int i = 1; i < words.Length; i++)
{
tmp[i - 1] = words[i];
}
// add a delegate to monitor inventory infos
proxy.AddDelegate(PacketType.InventoryDescendents, Direction.Incoming, this.inventoryPacketDelegate);
RequestFindObjectByPath(frame.InventoryRoot, String.Join(" ", tmp));
}
}
private void AOOn()
{
// add a delegate to track agent movements
proxy.AddDelegate(PacketType.AvatarAnimation, Direction.Incoming, this.packetDelegate);
}
private void AOOff()
{
// remove the delegate to track agent movements
proxy.RemoveDelegate(PacketType.AvatarAnimation, Direction.Incoming, this.packetDelegate);
//Stop all override animations
foreach (LLUUID tmp in overrides.Values)
{
Animate(tmp, false);
}
}
// Inventory functions
//start requesting an item by its path
public void RequestFindObjectByPath(LLUUID baseFolder, string path)
{
if (path == null || path.Length == 0)
throw new ArgumentException("Empty path is not supported");
currentFolder = baseFolder;
//split path by '/'
searchPath = path.Split('/');
//search for first element in the path
searchLevel = 0;
// Start the search
RequestFolderContents(baseFolder,
true,
(searchPath.Length == 1) ? true : false,
InventorySortOrder.ByName);
}
//request a folder content
public void RequestFolderContents(LLUUID folder, bool folders, bool items,
InventorySortOrder order)
{
//empty the dictionnary containing current folder items by name
currentFolderItems = new Dictionary<string, InventoryItem>();
//reset the number of descendants received
nbdescendantsreceived = 0;
//build a packet to request the content
FetchInventoryDescendentsPacket fetch = new FetchInventoryDescendentsPacket();
fetch.AgentData.AgentID = frame.AgentID;
fetch.AgentData.SessionID = frame.SessionID;
fetch.InventoryData.FetchFolders = folders;
fetch.InventoryData.FetchItems = items;
fetch.InventoryData.FolderID = folder;
fetch.InventoryData.OwnerID = frame.AgentID; //is it correct?
fetch.InventoryData.SortOrder = (int)order;
//send packet to SL
proxy.InjectPacket(fetch, Direction.Outgoing);
}
//process the reply from SL
private Packet InventoryDescendentsHandler(Packet packet, IPEndPoint sim)
{
bool intercept = false;
InventoryDescendentsPacket reply = (InventoryDescendentsPacket)packet;
if (reply.AgentData.Descendents > 0
&& reply.AgentData.FolderID == currentFolder)
{
//SayToUser("nb descendents: " + reply.AgentData.Descendents);
//this packet concerns the folder we asked for
if (reply.FolderData[0].FolderID != LLUUID.Zero
&& searchLevel < searchPath.Length - 1)
{
nbdescendantsreceived += reply.FolderData.Length;
//SayToUser("nb received: " + nbdescendantsreceived);
//folders are present, and we are not at end of path.
//look at them
for (int i = 0; i < reply.FolderData.Length; i++)
{
//SayToUser("Folder: " + Helpers.FieldToUTF8String(reply.FolderData[i].Name));
if (searchPath[searchLevel] == Helpers.FieldToUTF8String(reply.FolderData[i].Name)) {
//We found the next folder in the path
currentFolder = reply.FolderData[i].FolderID;
if (searchLevel < searchPath.Length - 1)
{
// ask for next item in path
searchLevel++;
RequestFolderContents(currentFolder,
true,
(searchLevel < searchPath.Length - 1) ? false : true,
InventorySortOrder.ByName);
//Jump to end
goto End;
}
}
}
if (nbdescendantsreceived >= reply.AgentData.Descendents)
{
//We have not found the folder. The user probably mistyped it
SayToUser("Didn't find folder " + searchPath[searchLevel]);
//Stop looking at packets
proxy.RemoveDelegate(PacketType.InventoryDescendents, Direction.Incoming, this.inventoryPacketDelegate);
}
}
else if (searchLevel < searchPath.Length - 1)
{
//There are no folders in the packet ; but we are looking for one!
//We have not found the folder. The user probably mistyped it
SayToUser("Didn't find folder " + searchPath[searchLevel]);
//Stop looking at packets
proxy.RemoveDelegate(PacketType.InventoryDescendents, Direction.Incoming, this.inventoryPacketDelegate);
}
else
{
//There are folders in the packet. And we are at the end of
//the path, count their number in nbdescendantsreceived
nbdescendantsreceived += reply.FolderData.Length;
//SayToUser("nb received: " + nbdescendantsreceived);
}
if (reply.ItemData[0].ItemID != LLUUID.Zero
&& searchLevel == searchPath.Length - 1)
{
//there are items returned and we are looking for one
//(end of search path)
//count them
nbdescendantsreceived += reply.ItemData.Length;
//SayToUser("nb received: " + nbdescendantsreceived);
for (int i = 0; i < reply.ItemData.Length; i++)
{
//we are going to store info on all items. we'll need
//it to get the asset ID of animations refered to by the
//configuration notecard
if (reply.ItemData[i].ItemID != LLUUID.Zero)
{
InventoryItem item = CreateInventoryItem((InventoryType)reply.ItemData[i].InvType, reply.ItemData[i].ItemID);
item.ParentUUID = reply.ItemData[i].FolderID;
item.CreatorID = reply.ItemData[i].CreatorID;
item.AssetType = (AssetType)reply.ItemData[i].Type;
item.AssetUUID = reply.ItemData[i].AssetID;
item.CreationDate = Helpers.UnixTimeToDateTime((uint)reply.ItemData[i].CreationDate);
item.Description = Helpers.FieldToUTF8String(reply.ItemData[i].Description);
item.Flags = (uint)reply.ItemData[i].Flags;
item.Name = Helpers.FieldToUTF8String(reply.ItemData[i].Name);
item.GroupID = reply.ItemData[i].GroupID;
item.GroupOwned = reply.ItemData[i].GroupOwned;
item.Permissions = new Permissions(
reply.ItemData[i].BaseMask,
reply.ItemData[i].EveryoneMask,
reply.ItemData[i].GroupMask,
reply.ItemData[i].NextOwnerMask,
reply.ItemData[i].OwnerMask);
item.SalePrice = reply.ItemData[i].SalePrice;
item.SaleType = (SaleType)reply.ItemData[i].SaleType;
item.OwnerID = reply.AgentData.OwnerID;
//SayToUser("item in folder: " + item.Name);
//Add the item to the name -> item hash
currentFolderItems.Add(item.Name, item);
}
}
if (nbdescendantsreceived >= reply.AgentData.Descendents)
{
//We have received all the items in the last folder
//Let's look for the item we are looking for
if (currentFolderItems.ContainsKey(searchPath[searchLevel]))
{
//We found what we where looking for
//Stop looking at packets
proxy.RemoveDelegate(PacketType.InventoryDescendents, Direction.Incoming, this.inventoryPacketDelegate);
//Download the notecard
assetdownloadID = RequestInventoryAsset(currentFolderItems[searchPath[searchLevel]]);
}
else
{
//We didnt find the item, the user probably mistyped its name
SayToUser("Didn't find notecard " + searchPath[searchLevel]);
//TODO: keep looking for a moment, or else reply packets may still
//come in case of a very large inventory folder
//Stop looking at packets
proxy.RemoveDelegate(PacketType.InventoryDescendents, Direction.Incoming, this.inventoryPacketDelegate);
}
}
}
else if (searchLevel == searchPath.Length - 1 && nbdescendantsreceived >= reply.AgentData.Descendents)
{
//There are no items in the packet, but we are looking for one!
//We didnt find the item, the user probably mistyped its name
SayToUser("Didn't find notecard " + searchPath[searchLevel]);
//TODO: keep looking for a moment, or else reply packets may still
//come in case of a very large inventory folder
//Stop looking at packets
proxy.RemoveDelegate(PacketType.InventoryDescendents, Direction.Incoming, this.inventoryPacketDelegate);
}
//Intercept the packet, it was a reply to our request. No need
//to confuse the actual SL client
intercept = true;
}
End:
if (intercept)
{
//stop packet
return null;
}
else
{
//let packet go to client
return packet;
}
}
public static InventoryItem CreateInventoryItem(InventoryType type, LLUUID id)
{
switch (type)
{
case InventoryType.Texture: return new InventoryTexture(id);
case InventoryType.Sound: return new InventorySound(id);
case InventoryType.CallingCard: return new InventoryCallingCard(id);
case InventoryType.Landmark: return new InventoryLandmark(id);
case InventoryType.Object: return new InventoryObject(id);
case InventoryType.Notecard: return new InventoryNotecard(id);
case InventoryType.Category: return new InventoryCategory(id);
case InventoryType.LSL: return new InventoryLSL(id);
case InventoryType.Snapshot: return new InventorySnapshot(id);
case InventoryType.Attachment: return new InventoryAttachment(id);
case InventoryType.Wearable: return new InventoryWearable(id);
case InventoryType.Animation: return new InventoryAnimation(id);
case InventoryType.Gesture: return new InventoryGesture(id);
default: return new InventoryItem(type, id);
}
}
//Ask for download of an item
public LLUUID RequestInventoryAsset(InventoryItem item)
{
// Build the request packet and send it
TransferRequestPacket request = new TransferRequestPacket();
request.TransferInfo.ChannelType = (int)ChannelType.Asset;
request.TransferInfo.Priority = 101.0f;
request.TransferInfo.SourceType = (int)SourceType.SimInventoryItem;
LLUUID transferID = LLUUID.Random();
request.TransferInfo.TransferID = transferID;
byte[] paramField = new byte[100];
Buffer.BlockCopy(frame.AgentID.GetBytes(), 0, paramField, 0, 16);
Buffer.BlockCopy(frame.SessionID.GetBytes(), 0, paramField, 16, 16);
Buffer.BlockCopy(item.OwnerID.GetBytes(), 0, paramField, 32, 16);
Buffer.BlockCopy(LLUUID.Zero.GetBytes(), 0, paramField, 48, 16);
Buffer.BlockCopy(item.UUID.GetBytes(), 0, paramField, 64, 16);
Buffer.BlockCopy(item.AssetUUID.GetBytes(), 0, paramField, 80, 16);
Buffer.BlockCopy(Helpers.IntToBytes((int)item.AssetType), 0, paramField, 96, 4);
request.TransferInfo.Params = paramField;
// add a delegate to monitor configuration notecards download
proxy.AddDelegate(PacketType.TransferPacket, Direction.Incoming, this.transferPacketDelegate);
//send packet to SL
proxy.InjectPacket(request, Direction.Outgoing);
//so far we downloaded 0 bytes
downloadedbytes = 0;
//the total size of the download is yet unknown
downloadsize = 0;
//A 100K buffer should be enough for everyone
buffer = new byte[1024 * 100];
//Return the transfer ID
return transferID;
}
// SayToUser: send a message to the user as in-world chat
private void SayToUser(string message)
{
ChatFromSimulatorPacket packet = new ChatFromSimulatorPacket();
packet.ChatData.FromName = Helpers.StringToField("ClientAO");
packet.ChatData.SourceID = LLUUID.Random();
packet.ChatData.OwnerID = frame.AgentID;
packet.ChatData.SourceType = (byte)2;
packet.ChatData.ChatType = (byte)1;
packet.ChatData.Audible = (byte)1;
packet.ChatData.Position = new LLVector3(0, 0, 0);
packet.ChatData.Message = Helpers.StringToField(message);
proxy.InjectPacket(packet, Direction.Incoming);
}
//start or stop an animation
public void Animate(LLUUID animationuuid, bool run)
{
AgentAnimationPacket animate = new AgentAnimationPacket();
animate.Header.Reliable = true;
animate.AgentData.AgentID = frame.AgentID;
animate.AgentData.SessionID = frame.SessionID;
//We send one animation
animate.AnimationList = new AgentAnimationPacket.AnimationListBlock[1];
animate.AnimationList[0] = new AgentAnimationPacket.AnimationListBlock();
animate.AnimationList[0].AnimID = animationuuid;
animate.AnimationList[0].StartAnim = run;
//SayToUser("anim " + animname(animationuuid) + " " + run);
proxy.InjectPacket(animate, Direction.Outgoing);
}
//return the name of an animation by its UUID
private string animname(LLUUID arg)
{
return animuid2name[arg];
}
//handle animation packets from simulator
private Packet AnimationPacketHandler(Packet packet, IPEndPoint sim) {
AvatarAnimationPacket animation = (AvatarAnimationPacket)packet;
if (animation.Sender.ID == frame.AgentID)
{
//the received animation packet is about our Agent, handle it
lock (SignaledAnimations)
{
// Reset the signaled animation list
SignaledAnimations.Clear();
//fill it with the fresh list from simulator
for (int i = 0; i < animation.AnimationList.Length; i++)
{
LLUUID animID = animation.AnimationList[i].AnimID;
int sequenceID = animation.AnimationList[i].AnimSequenceID;
// Add this animation to the list of currently signaled animations
SignaledAnimations[animID] = sequenceID;
//SayToUser("Animation: " + animname(animID));
}
}
//we now have a list of currently running animations
//Start override animations if necessary
foreach (LLUUID key in overrides.Keys)
{
//For each overriden animation key, test if its override is running
if (SignaledAnimations.ContainsKey(key) && (!overrideanimationisplaying[key] ))
{
//An overriden animation is present and its override animation
//isnt currently playing
//Start the override animation
//SayToUser("animation " + animname(key) + " started, will override with " + animname(overrides[key]));
overrideanimationisplaying[key] = true;
Animate(overrides[key], true);
}
else if ((!SignaledAnimations.ContainsKey(key)) && overrideanimationisplaying[key])
{
//an override animation is currently playing, but it's overriden
//animation is not.
//stop the override animation
//SayToUser("animation " + animname(key) + " stopped, will override with " + animname(overrides[key]));
overrideanimationisplaying[key] = false;
Animate(overrides[key], false);
}
}
}
//Let the packet go to the client
return packet;
}
//handle packets that contain info about the notecard data transfer
private Packet TransferInfoHandler(Packet packet, IPEndPoint simulator)
{
TransferInfoPacket info = (TransferInfoPacket)packet;
if (info.TransferInfo.TransferID == assetdownloadID)
{
//this is our requested tranfer, handle it
downloadsize = info.TransferInfo.Size;
if ((StatusCode)info.TransferInfo.Status != StatusCode.OK)
{
SayToUser("Failed to read notecard");
}
if (downloadedbytes >= downloadsize)
{
//Download already completed!
downloadCompleted();
}
//intercept packet
return null;
}
return packet;
}
//handle packets which contain the notecard data
private Packet TransferPacketHandler(Packet packet, IPEndPoint simulator)
{
TransferPacketPacket asset = (TransferPacketPacket)packet;
if (asset.TransferData.TransferID == assetdownloadID) {
Buffer.BlockCopy(asset.TransferData.Data, 0, buffer, 1000 * asset.TransferData.Packet,
asset.TransferData.Data.Length);
downloadedbytes += asset.TransferData.Data.Length;
// Check if we downloaded the full asset
if (downloadedbytes >= downloadsize)
{
downloadCompleted();
}
//Intercept packet
return null;
}
return packet;
}
private void downloadCompleted()
{
//We have the notecard.
//Stop looking at transfer packets
proxy.RemoveDelegate(PacketType.TransferPacket, Direction.Incoming, this.transferPacketDelegate);
//crop the buffer size
byte[] tmp = new byte[downloadedbytes];
Buffer.BlockCopy(buffer, 0, tmp, 0, downloadedbytes);
buffer = tmp;
String notecardtext = getNotecardText(Helpers.FieldToUTF8String(buffer));
//Load config, wetikon format
loadWetIkon(notecardtext);
}
private void loadWetIkon(string config)
{
//Reinitialise override table
overrides = new Dictionary<LLUUID,LLUUID>();
overrideanimationisplaying = new Dictionary<LLUUID, bool>();
animuid2name = new Dictionary<LLUUID,string>();
foreach (LLUUID key in wetikonanims )
{
animuid2name[key] = wetikonanimnames[Array.IndexOf(wetikonanims, key)];
}
//list of animations in wetikon
//read every second line in the config
char[] sep = { '\n' };
string[] lines = config.Split(sep);
int length = lines.Length;
int i = 1;
while (i < length) {
//Read animation name and look it up
string animname = lines[i].Trim();
//SayToUser("anim: " + animname);
if (animname != "")
{
if (currentFolderItems.ContainsKey(animname))
{
LLUUID over = currentFolderItems[animname].AssetUUID;
LLUUID orig = wetikonanims[((i + 1) / 2) - 1];
//put it in overrides
animuid2name[over] = animname;
overrides[orig] = over;
overrideanimationisplaying[orig] = false;
//SayToUser(wetikonanimnames[((i + 1) / 2) - 1] + " overriden by " + animname + " ( " + over + ")");
}
else
{
//Not found
SayToUser(animname + " not found.");
}
}
i += 2;
}
SayToUser("Notecard read, " + overrides.Count + " animations found");
}
private string getNotecardText(string data)
{
// Version 1 format:
// Linden text version 1
// {
// <EmbeddedItemList chunk>
// Text length
// <ASCII text; 0x80 | index = embedded item>
// }
// Version 2 format: (NOTE: Imports identically to version 1)
// Linden text version 2
// {
// <EmbeddedItemList chunk>
// Text length
// <UTF8 text; FIRST_EMBEDDED_CHAR + index = embedded item>
// }
int i = 0;
char[] sep = { '\n' };
string[] lines = data.Split(sep);
int length = lines.Length;
string result = "";
//check format
if (!lines[i].StartsWith("Linden text version "))
{
SayToUser("error");
return "";
}
//{
i++;
if (lines[i] != "{")
{
SayToUser("error");
return "";
}
i++;
if (lines[i] != "LLEmbeddedItems version 1")
{
SayToUser("error");
return "";
}
//{
i++;
if (lines[i] != "{")
{
SayToUser("error");
return "";
}
//count ...
i++;
if (!lines[i].StartsWith("count "))
{
SayToUser("error");
return "";
}
//}
i++;
if (lines[i] != "}")
{
SayToUser("error");
return "";
}
//Text length ...
i++;
if (!lines[i].StartsWith("Text length "))
{
SayToUser("error");
return "";
}
i++;
while (i < length)
{
result += lines[i] + "\n";
i++;
}
result = result.Substring(0, result.Length - 3);
return result;
}
}

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{173E70E4-44EE-440C-AD59-1CCD0BF03AC1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ClientAO</RootNamespace>
<AssemblyName>ClientAO</AssemblyName>
<StartupObject>
</StartupObject>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<Compile Include="ClientAO.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="libsecondlife, Version=0.9.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\bin\libsecondlife.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SLProxy.csproj">
<Project>{E4115DC9-FC88-47D6-B3B6-2400AD19B80D}</Project>
<Name>SLProxy</Name>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,35 @@
ClientAO by Issarlk Chatnoir
What is it?
***********
ClientAO is an implementation of an animation overrider running as a plugin for SLProxy.
Since it runs on the local computer and not on SL's server, this AO has no impact on sim
performance and lag. Also, it reacts to animation changes instantly instead of having to
poll the avatar state every so often, like inworld AO.
Instead of using an object like a regular AO, you point it to a folder in your inventory
containing the animations and a configuration notecard.
The AO understands "wetikon" type notecards (see sample)
How to use
**********
- Run SLProxy and start your SecondLife client so that it connects through the Proxy
(ex: SecondLife.exe ...(usual options here)... -loginuri http://localhost:8080/ )
- Login like usual
- once logged in, load the ClientAO plugin: /load ClientAO.dll
- Point it to a folder where you have previously put animations and a configuration
notecard, ex: /ao Objects/MyAO/*Default Anims
The AO will load the notecard.
- start the AO: /ao on
The AO should now replace your animations.

View File

@@ -0,0 +1,54 @@
:: [ Walking (also Striding) ] ::
:: [ Running ] ::
:: [ CrouchWalking ] ::
:: [ Flying (also FlyingSlow) ] ::
:: [ Turning Left ] ::
:: [ Turning Right ] ::
:: [ Jumping ] ::
:: [ Hovering Up ] ::
:: [ Crouching ] ::
:: [ Fly Down ] ::
:: [ Standing 1 ] ::
:: [ Standing 2 ] ::
:: [ Standing 3 ] ::
:: [ Standing 4 ] ::
:: [ Standing 5 ] ::
:: [ Hovering ] ::
:: [ Sitting ] ::
:: [ PreJumping ] ::
:: [ Falling ] ::
:: [ Soft Landing/Landing ] ::
:: [ Standing Up (That anim you play after you fall when you stand up and brush yourself off) ] ::
:: [ FlyingSlow ] ::
:: [ Sitting on Ground ] ::
:: [ Floating (Hovering underwater) ] ::
:: [ Swimming Forward (Flying underwater) ] ::
:: [ Swimming Up (Hover Up underwater) ] ::
:: [ Swimming Down (Fly Down underwater) ] ::

View File

@@ -0,0 +1 @@
All information about SLProxy can be found on the libsecondlife wiki at http://www.libsecondlife.org/wiki/SLProxy

View File

@@ -0,0 +1,153 @@
<?xml version="1.0"?>
<project name="libsecondlife" default="build">
<!-- global framework settings -->
<property name="target.framework" value="${framework::get-target-framework()}" />
<property name="assembly.dir" value="${framework::get-assembly-directory(target.framework)}" />
<!-- global project settings -->
<xmlpeek
file="../libsecondlife.build"
xpath="/project/property[@name = 'project.version']/@value"
property="project.version" />
<property name="build.number"
value="${math::abs(math::floor(timespan::get-total-days(datetime::now()
- datetime::parse('01/01/2002'))))}" />
<property name="assembly" value="SLProxy"/>
<property name="bin_dir" value="../bin" />
<!-- default configuration -->
<property name="project.config" value="debug" /> <!-- debug|release -->
<!-- named configurations -->
<target name="init" description="Initializes build properties">
<call target="${project.config}" />
</target>
<target name="debug" description="configures a debug build">
<property name="build.debug" value="true" />
<property name="package.name"
value="${project::get-name()}-${project.version}-${project.config}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()} [${project.config}]" />
</target>
<target name="release" description="configures a release build">
<property name="project.config" value="release" />
<property name="build.debug" value="false" />
<property name="package.name"
value="${project::get-name()}-${project.version}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()}" />
</target>
<!-- build tasks -->
<!-- target name="build" depends="build-analyst build-chatconsole build-main"
description="build analyst and chatconsole"
FIXME: Analyst's build is broken and Analyst and SLProxyLoader have
circular dependencies. Skipping Analyst for now. -axial -->
<target name="build" depends="build-analyst build-slproxy build-chatconsole build-main"
description="build SLProxy and chatconsole">
</target>
<target name="build-slproxy" depends="init"
description="Builds the binaries for the current configuration">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="library"
debug="${build.debug}"
output="${bin_dir}/SLProxy.dll">
<sources failonempty="true">
<include name="SLProxy.cs" />
<include name="XmlRpcCS/*.cs" />
<include name="SLProxyLoader.cs" />
<!-- <include name="legacy/*.cs" /> -->
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
</references>
</csc>
</target>
<target name="build-analyst" depends="init build-slproxy"
description="Builds the binaries for the current configuration">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="library"
debug="${build.debug}"
output="${bin_dir}/Analyst.dll">
<sources failonempty="true">
<include name="Analyst.cs" />
<!-- <include name="legacy/*.cs" /> -->
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
<include name="SLProxy.dll"/>
</references>
</csc>
</target>
<!-- Note - please, please, PLEASE, refrain from calling the executable
SLProxy.exe, as the name conflict with SLProxy.dll confuses Mono -->
<target name="build-main"
depends="init build-slproxy"
description="build SLProxy main">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="exe"
debug="${build.debug}"
output="${bin_dir}/SLProxyMain.exe">
<sources failonempty="true">
<include name="SLProxyMain.cs" />
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
<include name="SLProxy.dll"/>
<include name="Analyst.dll"/>
</references>
</csc>
</target>
<target name="build-chatconsole"
depends="init build-slproxy"
description="build SLProxy ChatConsole">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="exe"
debug="${build.debug}"
output="${bin_dir}/ChatConsole.exe">
<sources failonempty="true">
<include name="ChatConsole.cs" />
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
<include name="SLProxy.dll"/>
</references>
</csc>
</target>
<target name="clean" depends="init"
description="Deletes the current configuration">
<delete failonerror="false">
<fileset basedir="${bin_dir}/">
<include name="SLProxy.dll" />
<include name="SLProxy.dll.mdb" />
<include name="ChatConsole.exe" />
<include name="ChatConsole.exe.mdb" />
<include name="Analyst.exe" />
<include name="Analyst.exe.mdb" />
</fileset>
</delete>
</target>
<target
name="*"
description="Handles unknown targets">
<echo message="skipping unknown target" />
</target>
</project>

2127
Programs/SLProxy/SLProxy.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{E4115DC9-FC88-47D6-B3B6-2400AD19B80D}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>SLProxy</AssemblyName>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>Exe</OutputType>
<RootNamespace>SLProxy</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>ProxyMain</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>..\bin\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>..\bin\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-docs|AnyCPU' ">
<OutputPath>bin\Release-docs\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<Optimize>true</Optimize>
<DebugType>
</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Analyst.cs" />
<Compile Include="SLProxy.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="SLProxyLoader.cs" />
<Compile Include="SLProxyMain.cs" />
<Compile Include="XmlRpcCS\Logger.cs" />
<Compile Include="XmlRpcCS\SimpleHttpRequest.cs" />
<Compile Include="XmlRpcCS\XmlRpcBoxcarRequest.cs" />
<Compile Include="XmlRpcCS\XmlRpcClientProxy.cs" />
<Compile Include="XmlRpcCS\XmlRpcDeserializer.cs" />
<Compile Include="XmlRpcCS\XmlRpcErrorCodes.cs" />
<Compile Include="XmlRpcCS\XmlRpcException.cs" />
<Compile Include="XmlRpcCS\XmlRpcExposedAttribute.cs" />
<Compile Include="XmlRpcCS\XmlRpcRequest.cs" />
<Compile Include="XmlRpcCS\XmlRpcRequestDeserializer.cs" />
<Compile Include="XmlRpcCS\XmlRpcRequestSerializer.cs" />
<Compile Include="XmlRpcCS\XmlRpcResponder.cs" />
<Compile Include="XmlRpcCS\XmlRpcResponse.cs" />
<Compile Include="XmlRpcCS\XmlRpcResponseDeserializer.cs" />
<Compile Include="XmlRpcCS\XmlRpcResponseSerializer.cs" />
<Compile Include="XmlRpcCS\XmlRpcSerializer.cs" />
<Compile Include="XmlRpcCS\XmlRpcServer.cs" />
<Compile Include="XmlRpcCS\XmlRpcSystemObject.cs" />
<Compile Include="XmlRpcCS\XmlRpcXmlTokens.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libsecondlife\OpenMetaverse.csproj">
<Project>{D9CDEDFB-8169-4B03-B57F-0DF638F044EC}</Project>
<Name>OpenMetaverse</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,210 @@
using SLProxy;
using OpenMetaverse;
using Nwc.XmlRpc;
using OpenMetaverse.Packets;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
namespace SLProxy
{
public class ProxyFrame
{
public Proxy proxy;
private Dictionary<string, CommandDelegate> commandDelegates = new Dictionary<string, CommandDelegate>();
private LLUUID agentID;
private LLUUID sessionID;
private LLUUID inventoryRoot;
private bool logLogin = false;
private string[] args;
public delegate void CommandDelegate(string[] words);
public string[] Args
{
get { return args; }
}
public LLUUID AgentID
{
get { return agentID; }
}
public LLUUID SessionID
{
get { return sessionID; }
}
public LLUUID InventoryRoot
{
get { return inventoryRoot; }
}
public void AddCommand(string cmd, CommandDelegate deleg)
{
commandDelegates[cmd] = deleg;
}
public ProxyFrame(string[] args)
{
//bool externalPlugin = false;
this.args = args;
ProxyConfig proxyConfig = new ProxyConfig("SLProxy", "Austin Jennings / Andrew Ortman", args);
proxy = new Proxy(proxyConfig);
// add delegates for login
proxy.SetLoginRequestDelegate(new XmlRpcRequestDelegate(LoginRequest));
proxy.SetLoginResponseDelegate(new XmlRpcResponseDelegate(LoginResponse));
// add a delegate for outgoing chat
proxy.AddDelegate(PacketType.ChatFromViewer, Direction.Outgoing, new PacketDelegate(ChatFromViewerOut));
// handle command line arguments
foreach (string arg in args)
if (arg == "--log-login")
logLogin = true;
else if (arg.Substring(0, 2) == "--")
{
int ipos = arg.IndexOf("=");
if (ipos != -1)
{
string sw = arg.Substring(0, ipos);
string val = arg.Substring(ipos + 1);
Console.WriteLine("arg '" + sw + "' val '" + val + "'");
if (sw == "--load")
{
//externalPlugin = true;
LoadPlugin(val);
}
}
}
commandDelegates["/load"] = new CommandDelegate(CmdLoad);
}
private void CmdLoad(string[] words)
{
if (words.Length != 2)
SayToUser("Usage: /load <plugin name>");
else
{
try
{
LoadPlugin(words[1]);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
public void LoadPlugin(string name)
{
Assembly assembly = Assembly.LoadFile(Path.GetFullPath(name));
foreach (Type t in assembly.GetTypes())
{
try
{
if (t.IsSubclassOf(typeof(ProxyPlugin)))
{
ConstructorInfo info = t.GetConstructor(new Type[] { typeof(ProxyFrame) });
ProxyPlugin plugin = (ProxyPlugin)info.Invoke(new object[] { this });
plugin.Init();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
// LoginRequest: dump a login request to the console
private void LoginRequest(XmlRpcRequest request)
{
if (logLogin)
{
Console.WriteLine("==> Login Request");
Console.WriteLine(request);
}
}
// Loginresponse: dump a login response to the console
private void LoginResponse(XmlRpcResponse response)
{
System.Collections.Hashtable values = (System.Collections.Hashtable)response.Value;
if (values.Contains("agent_id"))
agentID = new LLUUID((string)values["agent_id"]);
if (values.Contains("session_id"))
sessionID = new LLUUID((string)values["session_id"]);
if (values.Contains("inventory-root"))
{
inventoryRoot = new LLUUID(
(string)((System.Collections.Hashtable)(((System.Collections.ArrayList)values["inventory-root"])[0]))["folder_id"]
);
Console.WriteLine("inventory root: " + inventoryRoot);
}
if (logLogin)
{
Console.WriteLine("<== Login Response");
Console.WriteLine(response);
}
}
// ChatFromViewerOut: outgoing ChatFromViewer delegate; check for Analyst commands
private Packet ChatFromViewerOut(Packet packet, IPEndPoint sim)
{
// deconstruct the packet
ChatFromViewerPacket cpacket = (ChatFromViewerPacket)packet;
string message = System.Text.Encoding.UTF8.GetString(cpacket.ChatData.Message).Replace("\0", "");
if (message.Length > 1 && message[0] == '/')
{
string[] words = message.Split(' ');
if (commandDelegates.ContainsKey(words[0]))
{
// this is an Analyst command; act on it and drop the chat packet
((CommandDelegate)commandDelegates[words[0]])(words);
return null;
}
}
return packet;
}
// SayToUser: send a message to the user as in-world chat
public void SayToUser(string message)
{
ChatFromSimulatorPacket packet = new ChatFromSimulatorPacket();
packet.ChatData.FromName = Helpers.StringToField("SLProxy");
packet.ChatData.SourceID = LLUUID.Random();
packet.ChatData.OwnerID = agentID;
packet.ChatData.SourceType = (byte)2;
packet.ChatData.ChatType = (byte)1;
packet.ChatData.Audible = (byte)1;
packet.ChatData.Position = new LLVector3(0, 0, 0);
packet.ChatData.Message = Helpers.StringToField(message);
proxy.InjectPacket(packet, Direction.Incoming);
}
}
public abstract class ProxyPlugin : MarshalByRefObject
{
// public abstract ProxyPlugin(ProxyFrame main);
public abstract void Init();
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Reflection;
using SLProxy;
class ProxyMain
{
public static void Main(string[] args)
{
ProxyFrame p = new ProxyFrame(args);
ProxyPlugin analyst = new Analyst(p);
analyst.Init();
p.proxy.Start();
}
}

View File

@@ -0,0 +1,46 @@
namespace Nwc.XmlRpc
{
using System;
/// <summary>Define levels of logging.</summary><remarks> This duplicates
/// similar enumerations in System.Diagnostics.EventLogEntryType. The
/// duplication was merited because .NET Compact Framework lacked the EventLogEntryType enum.</remarks>
public enum LogLevel
{
/// <summary>Information level, log entry for informational reasons only.</summary>
Information,
/// <summary>Warning level, indicates a possible problem.</summary>
Warning,
/// <summary>Error level, implies a significant problem.</summary>
Error
}
///<summary>
///Logging singleton with swappable output delegate.
///</summary>
///<remarks>
///This singleton provides a centralized log. The actual WriteEntry calls are passed
///off to a delegate however. Having a delegate do the actual logginh allows you to
///implement different logging mechanism and have them take effect throughout the system.
///</remarks>
public class Logger
{
///<summary>Delegate definition for logging.</summary>
///<param name="message">The message <c>String</c> to log.</param>
///<param name="level">The <c>LogLevel</c> of your message.</param>
public delegate void LoggerDelegate(String message, LogLevel level);
///<summary>The LoggerDelegate that will recieve WriteEntry requests.</summary>
static public LoggerDelegate Delegate = null;
///<summary>
///Method logging events are sent to.
///</summary>
///<param name="message">The message <c>String</c> to log.</param>
///<param name="level">The <c>LogLevel</c> of your message.</param>
static public void WriteEntry(String message, LogLevel level)
{
if (Delegate != null)
Delegate(message, level);
}
}
}

View File

@@ -0,0 +1,204 @@
namespace Nwc.XmlRpc
{
using System;
using System.IO;
using System.Net.Sockets;
using System.Collections;
///<summary>Very basic HTTP request handler.</summary>
///<remarks>This class is designed to accept a TcpClient and treat it as an HTTP request.
/// It will do some basic header parsing and manage the input and output streams associated
/// with the request.</remarks>
public class SimpleHttpRequest
{
private String _httpMethod = null;
private String _protocol;
private String _filePathFile = null;
private String _filePathDir = null;
private String __filePath;
private TcpClient _client;
private StreamReader _input;
private StreamWriter _output;
private Hashtable _headers;
/// <summary>A constructor which accepts the TcpClient.</summary>
/// <remarks>It creates the associated input and output streams, determines the request type,
/// and parses the remaining HTTP header.</remarks>
/// <param name="client">The <c>TcpClient</c> associated with the HTTP connection.</param>
public SimpleHttpRequest(TcpClient client)
{
_client = client;
_output = new StreamWriter(client.GetStream());
_input = new StreamReader(client.GetStream());
GetRequestMethod();
GetRequestHeaders();
}
/// <summary>The output <c>StreamWriter</c> associated with the request.</summary>
public StreamWriter Output
{
get { return _output; }
}
/// <summary>The input <c>StreamReader</c> associated with the request.</summary>
public StreamReader Input
{
get { return _input; }
}
/// <summary>The <c>TcpClient</c> with the request.</summary>
public TcpClient Client
{
get { return _client; }
}
private String _filePath
{
get { return __filePath; }
set
{
__filePath = value;
_filePathDir = null;
_filePathFile = null;
}
}
/// <summary>The type of HTTP request (i.e. PUT, GET, etc.).</summary>
public String HttpMethod
{
get { return _httpMethod; }
}
/// <summary>The level of the HTTP protocol.</summary>
public String Protocol
{
get { return _protocol; }
}
/// <summary>The "path" which is part of any HTTP request.</summary>
public String FilePath
{
get { return _filePath; }
}
/// <summary>The file portion of the "path" which is part of any HTTP request.</summary>
public String FilePathFile
{
get
{
if (_filePathFile != null)
return _filePathFile;
int i = FilePath.LastIndexOf("/");
if (i == -1)
return "";
i++;
_filePathFile = FilePath.Substring(i, FilePath.Length - i);
return _filePathFile;
}
}
/// <summary>The directory portion of the "path" which is part of any HTTP request.</summary>
public String FilePathDir
{
get
{
if (_filePathDir != null)
return _filePathDir;
int i = FilePath.LastIndexOf("/");
if (i == -1)
return "";
i++;
_filePathDir = FilePath.Substring(0, i);
return _filePathDir;
}
}
private void GetRequestMethod()
{
string req = _input.ReadLine();
if (req == null)
throw new ApplicationException("Void request.");
if (0 == String.Compare("GET ", req.Substring(0, 4), true))
_httpMethod = "GET";
else if (0 == String.Compare("POST ", req.Substring(0, 5), true))
_httpMethod = "POST";
else
throw new InvalidOperationException("Unrecognized method in query: " + req);
req = req.TrimEnd();
int idx = req.IndexOf(' ') + 1;
if (idx >= req.Length)
throw new ApplicationException("What do you want?");
string page_protocol = req.Substring(idx);
int idx2 = page_protocol.IndexOf(' ');
if (idx2 == -1)
idx2 = page_protocol.Length;
_filePath = page_protocol.Substring(0, idx2).Trim();
_protocol = page_protocol.Substring(idx2).Trim();
}
private void GetRequestHeaders()
{
String line;
int idx;
_headers = new Hashtable();
while ((line = _input.ReadLine()) != "")
{
if (line == null)
{
break;
}
idx = line.IndexOf(':');
if (idx == -1 || idx == line.Length - 1)
{
Logger.WriteEntry("Malformed header line: " + line, LogLevel.Information);
continue;
}
String key = line.Substring(0, idx);
String value = line.Substring(idx + 1);
try
{
_headers.Add(key, value);
}
catch (Exception)
{
Logger.WriteEntry("Duplicate header key in line: " + line, LogLevel.Information);
}
}
}
/// <summary>
/// Format the object contents into a useful string representation.
/// </summary>
///<returns><c>String</c> representation of the <c>SimpleHttpRequest</c> as the <i>HttpMethod FilePath Protocol</i>.</returns>
override public String ToString()
{
return HttpMethod + " " + FilePath + " " + Protocol;
}
/// <summary>
/// Close the <c>SimpleHttpRequest</c>. This flushes and closes all associated io streams.
/// </summary>
public void Close()
{
_output.Flush();
_output.Close();
_input.Close();
_client.Close();
}
}
}

View File

@@ -0,0 +1,51 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Net;
using System.Text;
using System.Reflection;
/// <summary>Class that collects individual <c>XmlRpcRequest</c> objects and submits them as a <i>boxcarred</i> request.</summary>
/// <remarks>A boxcared request is when a number of request are collected before being sent via XML-RPC, and then are sent via
/// a single HTTP connection. This results in a speed up from reduced connection time. The results are then retuned collectively
/// as well.
///</remarks>
/// <seealso cref="XmlRpcRequest"/>
public class XmlRpcBoxcarRequest : XmlRpcRequest
{
/// <summary>ArrayList to collect the requests to boxcar.</summary>
public IList Requests = new ArrayList();
/// <summary>Basic constructor.</summary>
public XmlRpcBoxcarRequest()
{
}
/// <summary>Returns the <c>String</c> "system.multiCall" which is the server method that handles boxcars.</summary>
public override String MethodName
{
get { return "system.multiCall"; }
}
/// <summary>The <c>ArrayList</c> of boxcarred <paramref>Requests</paramref> as properly formed parameters.</summary>
public override IList Params
{
get {
_params.Clear();
ArrayList reqArray = new ArrayList();
foreach (XmlRpcRequest request in Requests)
{
Hashtable requestEntry = new Hashtable();
requestEntry.Add(XmlRpcXmlTokens.METHOD_NAME, request.MethodName);
requestEntry.Add(XmlRpcXmlTokens.PARAMS, request.Params);
reqArray.Add(requestEntry);
}
_params.Add(reqArray);
return _params;
}
}
}
}

View File

@@ -0,0 +1,61 @@
namespace Nwc.XmlRpc
{
using System;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
/// <summary>This class provides support for creating local proxies of XML-RPC remote objects</summary>
/// <remarks>
/// To create a local proxy you need to create a local C# interface and then, via <i>createProxy</i>
/// associate that interface with a remote object at a given URL.
/// </remarks>
public class XmlRpcClientProxy : RealProxy
{
private String _remoteObjectName;
private String _url;
private XmlRpcRequest _client = new XmlRpcRequest();
/// <summary>Factory method to create proxies.</summary>
/// <remarks>
/// To create a local proxy you need to create a local C# interface with methods that mirror those of the server object.
/// Next, pass that interface into <c>createProxy</c> along with the object name and URL of the remote object and
/// cast the resulting object to the specifice interface.
/// </remarks>
/// <param name="remoteObjectName"><c>String</c> The name of the remote object.</param>
/// <param name="url"><c>String</c> The URL of the remote object.</param>
/// <param name="anInterface"><c>Type</c> The typeof() of a C# interface.</param>
/// <returns><c>Object</c> A proxy for your specified interface. Cast to appropriate type.</returns>
public static Object createProxy(String remoteObjectName, String url, Type anInterface)
{
return new XmlRpcClientProxy(remoteObjectName, url, anInterface).GetTransparentProxy();
}
private XmlRpcClientProxy(String remoteObjectName, String url, Type t) : base(t)
{
_remoteObjectName = remoteObjectName;
_url = url;
}
/// <summary>The local method dispatcher - do not invoke.</summary>
override public IMessage Invoke(IMessage msg)
{
IMethodCallMessage methodMessage = (IMethodCallMessage)msg;
_client.MethodName = _remoteObjectName + "." + methodMessage.MethodName;
_client.Params.Clear();
foreach (Object o in methodMessage.Args)
_client.Params.Add(o);
try
{
Object ret = _client.Invoke(_url);
return new ReturnMessage(ret,null,0,
methodMessage.LogicalCallContext, methodMessage);
}
catch (Exception e)
{
return new ReturnMessage(e, methodMessage);
}
}
}
}

View File

@@ -0,0 +1,195 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Globalization;
/// <summary>Parser context, we maintain contexts in a stack to avoiding recursion. </summary>
struct Context
{
public String Name;
public Object Container;
}
/// <summary>Basic XML-RPC data deserializer.</summary>
/// <remarks>Uses <c>XmlTextReader</c> to parse the XML data. This level of the class
/// only handles the tokens common to both Requests and Responses. This class is not useful in and of itself
/// but is designed to be subclassed.</remarks>
public class XmlRpcDeserializer : XmlRpcXmlTokens
{
private static DateTimeFormatInfo _dateFormat = new DateTimeFormatInfo();
private Object _container;
private Stack _containerStack;
/// <summary>Protected reference to last text.</summary>
protected String _text;
/// <summary>Protected reference to last deserialized value.</summary>
protected Object _value;
/// <summary>Protected reference to last name field.</summary>
protected String _name;
/// <summary>Basic constructor.</summary>
public XmlRpcDeserializer()
{
Reset();
_dateFormat.FullDateTimePattern = ISO_DATETIME;
}
/// <summary>Static method that parses XML data into a response using the Singleton.</summary>
/// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC response.</param>
/// <returns><c>Object</c> object resulting from the deserialization.</returns>
virtual public Object Deserialize(TextReader xmlData)
{
return null;
}
/// <summary>Protected method to parse a node in an XML-RPC XML stream.</summary>
/// <remarks>Method deals with elements common to all XML-RPC data, subclasses of
/// this object deal with request/response spefic elements.</remarks>
/// <param name="reader"><c>XmlTextReader</c> of the in progress parsing data stream.</param>
protected void DeserializeNode(XmlTextReader reader)
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (Logger.Delegate != null)
Logger.WriteEntry("START " + reader.Name, LogLevel.Information);
switch (reader.Name)
{
case VALUE:
_value = null;
_text = null;
break;
case STRUCT:
PushContext();
_container = new Hashtable();
break;
case ARRAY:
PushContext();
_container = new ArrayList();
break;
}
break;
case XmlNodeType.EndElement:
if (Logger.Delegate != null)
Logger.WriteEntry("END " + reader.Name, LogLevel.Information);
switch (reader.Name)
{
case BASE64:
_value = Convert.FromBase64String(_text);
break;
case BOOLEAN:
int val = Int16.Parse(_text);
if (val == 0)
_value = false;
else if (val == 1)
_value = true;
break;
case STRING:
_value = _text;
break;
case DOUBLE:
_value = Double.Parse(_text);
break;
case INT:
case ALT_INT:
_value = Int32.Parse(_text);
break;
case DATETIME:
#if __MONO__
_value = DateParse(_text);
#else
_value = DateTime.ParseExact(_text, "F", _dateFormat);
#endif
break;
case NAME:
_name = _text;
break;
case VALUE:
if (_value == null)
_value = _text; // some kits don't use <string> tag, they just do <value>
if ((_container != null) && (_container is IList)) // in an array? If so add value to it.
((IList)_container).Add(_value);
break;
case MEMBER:
if ((_container != null) && (_container is IDictionary)) // in an struct? If so add value to it.
((IDictionary)_container).Add(_name, _value);
break;
case ARRAY:
case STRUCT:
_value = _container;
PopContext();
break;
}
break;
case XmlNodeType.Text:
if (Logger.Delegate != null)
Logger.WriteEntry("Text " + reader.Value, LogLevel.Information);
_text = reader.Value;
break;
default:
break;
}
}
/// <summary>Static method that parses XML in a <c>String</c> into a
/// request using the Singleton.</summary>
/// <param name="xmlData"><c>String</c> containing an XML-RPC request.</param>
/// <returns><c>XmlRpcRequest</c> object resulting from the parse.</returns>
public Object Deserialize(String xmlData)
{
StringReader sr = new StringReader(xmlData);
return Deserialize(sr);
}
/// <summary>Pop a Context of the stack, an Array or Struct has closed.</summary>
private void PopContext()
{
Context c = (Context)_containerStack.Pop();
_container = c.Container;
_name = c.Name;
}
/// <summary>Push a Context on the stack, an Array or Struct has opened.</summary>
private void PushContext()
{
Context context;
context.Container = _container;
context.Name = _name;
_containerStack.Push(context);
}
/// <summary>Reset the internal state of the deserializer.</summary>
protected void Reset()
{
_text = null;
_value = null;
_name = null;
_container = null;
_containerStack = new Stack();
}
#if __MONO__
private DateTime DateParse(String str)
{
int year = Int32.Parse(str.Substring(0,4));
int month = Int32.Parse(str.Substring(4,2));
int day = Int32.Parse(str.Substring(6,2));
int hour = Int32.Parse(str.Substring(9,2));
int min = Int32.Parse(str.Substring(12,2));
int sec = Int32.Parse(str.Substring(15,2));
return new DateTime(year,month,day,hour,min,sec);
}
#endif
}
}

View File

@@ -0,0 +1,51 @@
namespace Nwc.XmlRpc
{
using System;
/// <summary>Standard XML-RPC error codes.</summary>
public class XmlRpcErrorCodes
{
/// <summary></summary>
public const int PARSE_ERROR_MALFORMED = -32700;
/// <summary></summary>
public const String PARSE_ERROR_MALFORMED_MSG = "Parse Error, not well formed";
/// <summary></summary>
public const int PARSE_ERROR_ENCODING = -32701;
/// <summary></summary>
public const String PARSE_ERROR_ENCODING_MSG = "Parse Error, unsupported encoding";
//
// -32702 ---> parse error. invalid character for encoding
// -32600 ---> server error. invalid xml-rpc. not conforming to spec.
//
/// <summary></summary>
public const int SERVER_ERROR_METHOD = -32601;
/// <summary></summary>
public const String SERVER_ERROR_METHOD_MSG = "Server Error, requested method not found";
/// <summary></summary>
public const int SERVER_ERROR_PARAMS = -32602;
/// <summary></summary>
public const String SERVER_ERROR_PARAMS_MSG = "Server Error, invalid method parameters";
//
// -32603 ---> server error. internal xml-rpc error
//
/// <summary></summary>
public const int APPLICATION_ERROR = -32500;
/// <summary></summary>
public const String APPLICATION_ERROR_MSG = "Application Error";
//
// -32400 ---> system error
//
/// <summary></summary>
public const int TRANSPORT_ERROR = -32300;
/// <summary></summary>
public const String TRANSPORT_ERROR_MSG = "Transport Layer Error";
}
}

View File

@@ -0,0 +1,39 @@
namespace Nwc.XmlRpc
{
using System;
/// <summary>An XML-RPC Exception.</summary>
/// <remarks>Maps a C# exception to an XML-RPC fault. Normal exceptions
/// include a message so this adds the code needed by XML-RPC.</remarks>
public class XmlRpcException : Exception
{
private int _code;
/// <summary>Instantiate an <c>XmlRpcException</c> with a code and message.</summary>
/// <param name="code"><c>Int</c> faultCode associated with this exception.</param>
/// <param name="message"><c>String</c> faultMessage associated with this exception.</param>
public XmlRpcException(int code, String message)
: base(message)
{
_code = code;
}
/// <summary>The value of the faults message, i.e. the faultString.</summary>
public String FaultString
{
get { return Message; }
}
/// <summary>The value of the faults code, i.e. the faultCode.</summary>
public int FaultCode
{
get { return _code; }
}
/// <summary>Format the message to include the code.</summary>
override public String ToString()
{
return "Code: " + FaultCode + " Message: " + base.ToString();
}
}
}

View File

@@ -0,0 +1,60 @@
namespace Nwc.XmlRpc
{
using System;
using System.Reflection;
/// <summary>
/// Simple tagging attribute to indicate participation is XML-RPC exposure.
/// </summary>
/// <remarks>
/// If present at the class level it indicates that this class does explicitly
/// expose methods. If present at the method level it denotes that the method
/// is exposed.
/// </remarks>
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = false,
Inherited = true
)]
public class XmlRpcExposedAttribute : Attribute
{
/// <summary>Check if <paramref>obj</paramref> is an object utilizing the XML-RPC exposed Attribute.</summary>
/// <param name="obj"><c>Object</c> of a class or method to check for attribute.</param>
/// <returns><c>Boolean</c> true if attribute present.</returns>
public static Boolean ExposedObject(Object obj)
{
return IsExposed(obj.GetType());
}
/// <summary>Check if <paramref>obj</paramref>.<paramref>methodName</paramref> is an XML-RPC exposed method.</summary>
/// <remarks>A method is considered to be exposed if it exists and, either, the object does not use the XmlRpcExposed attribute,
/// or the object does use the XmlRpcExposed attribute and the method has the XmlRpcExposed attribute as well.</remarks>
/// <returns><c>Boolean</c> true if the method is exposed.</returns>
public static Boolean ExposedMethod(Object obj, String methodName)
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod(methodName);
if (method == null)
throw new MissingMethodException("Method " + methodName + " not found.");
if (!IsExposed(type))
return true;
return IsExposed(method);
}
/// <summary>Check if <paramref>mi</paramref> is XML-RPC exposed.</summary>
/// <param name="mi"><c>MemberInfo</c> of a class or method to check for attribute.</param>
/// <returns><c>Boolean</c> true if attribute present.</returns>
public static Boolean IsExposed(MemberInfo mi)
{
foreach (Attribute attr in mi.GetCustomAttributes(true))
{
if (attr is XmlRpcExposedAttribute)
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,150 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Net;
using System.Text;
using System.Reflection;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
internal class AcceptAllCertificatePolicy : ICertificatePolicy
{
public AcceptAllCertificatePolicy()
{
}
public bool CheckValidationResult(ServicePoint sPoint,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
WebRequest wRequest, int certProb)
{
// Always accept
return true;
}
}
/// <summary>Class supporting the request side of an XML-RPC transaction.</summary>
public class XmlRpcRequest
{
private String _methodName = null;
private Encoding _encoding = new ASCIIEncoding();
private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer();
private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer();
/// <summary><c>ArrayList</c> containing the parameters.</summary>
protected IList _params = null;
/// <summary>Instantiate an <c>XmlRpcRequest</c></summary>
public XmlRpcRequest()
{
_params = new ArrayList();
}
/// <summary>Instantiate an <c>XmlRpcRequest</c> for a specified method and parameters.</summary>
/// <param name="methodName"><c>String</c> designating the <i>object.method</i> on the server the request
/// should be directed to.</param>
/// <param name="parameters"><c>ArrayList</c> of XML-RPC type parameters to invoke the request with.</param>
public XmlRpcRequest(String methodName, IList parameters)
{
MethodName = methodName;
_params = parameters;
}
/// <summary><c>ArrayList</c> conntaining the parameters for the request.</summary>
public virtual IList Params
{
get { return _params; }
}
/// <summary><c>String</c> conntaining the method name, both object and method, that the request will be sent to.</summary>
public virtual String MethodName
{
get { return _methodName; }
set { _methodName = value; }
}
/// <summary><c>String</c> object name portion of the method name.</summary>
public String MethodNameObject
{
get
{
int index = MethodName.IndexOf(".");
if (index == -1)
return MethodName;
return MethodName.Substring(0, index);
}
}
/// <summary><c>String</c> method name portion of the object.method name.</summary>
public String MethodNameMethod
{
get
{
int index = MethodName.IndexOf(".");
if (index == -1)
return MethodName;
return MethodName.Substring(index + 1, MethodName.Length - index - 1);
}
}
/// <summary>Invoke this request on the server.</summary>
/// <param name="url"><c>String</c> The url of the XML-RPC server.</param>
/// <returns><c>Object</c> The value returned from the method invocation on the server.</returns>
/// <exception cref="XmlRpcException">If an exception generated on the server side.</exception>
public Object Invoke(String url)
{
XmlRpcResponse res = Send(url, 10000);
if (res.IsFault)
throw new XmlRpcException(res.FaultCode, res.FaultString);
return res.Value;
}
/// <summary>Send the request to the server.</summary>
/// <param name="url"><c>String</c> The url of the XML-RPC server.</param>
/// <param name="timeout">Milliseconds before the connection times out.</param>
/// <returns><c>XmlRpcResponse</c> The response generated.</returns>
public XmlRpcResponse Send(String url, int timeout)
{
// Override SSL authentication mechanisms
ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
if (request == null)
throw new XmlRpcException(XmlRpcErrorCodes.TRANSPORT_ERROR,
XmlRpcErrorCodes.TRANSPORT_ERROR_MSG + ": Could not create request with " + url);
request.Method = "POST";
request.ContentType = "text/xml";
request.AllowWriteStreamBuffering = true;
request.Timeout = timeout;
Stream stream = request.GetRequestStream();
XmlTextWriter xml = new XmlTextWriter(stream, _encoding);
_serializer.Serialize(xml, this);
xml.Flush();
xml.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader input = new StreamReader(response.GetResponseStream());
XmlRpcResponse resp = (XmlRpcResponse)_deserializer.Deserialize(input);
input.Close();
response.Close();
return resp;
}
/// <summary>Produce <c>String</c> representation of the object.</summary>
/// <returns><c>String</c> representation of the object.</returns>
override public String ToString()
{
return _serializer.Serialize(this);
}
}
}

View File

@@ -0,0 +1,64 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Xml;
/// <summary>Class to deserialize XML data representing a request.</summary>
public class XmlRpcRequestDeserializer : XmlRpcDeserializer
{
static private XmlRpcRequestDeserializer _singleton;
/// <summary>A static singleton instance of this deserializer.</summary>
[Obsolete("This object is now thread safe, just use an instance.", false)]
static public XmlRpcRequestDeserializer Singleton
{
get
{
if (_singleton == null)
_singleton = new XmlRpcRequestDeserializer();
return _singleton;
}
}
/// <summary>Static method that parses XML data into a request using the Singleton.</summary>
/// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC request.</param>
/// <returns><c>XmlRpcRequest</c> object resulting from the parse.</returns>
override public Object Deserialize(TextReader xmlData)
{
XmlTextReader reader = new XmlTextReader(xmlData);
XmlRpcRequest request = new XmlRpcRequest();
bool done = false;
lock (this)
{
Reset();
while (!done && reader.Read())
{
DeserializeNode(reader); // Parent parse...
switch (reader.NodeType)
{
case XmlNodeType.EndElement:
switch (reader.Name)
{
case METHOD_NAME:
request.MethodName = _text;
break;
case METHOD_CALL:
done = true;
break;
case PARAM:
request.Params.Add(_value);
_text = null;
break;
}
break;
}
}
}
return request;
}
}
}

View File

@@ -0,0 +1,51 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.Xml;
using System.IO;
/// <summary>Class responsible for serializing an XML-RPC request.</summary>
/// <remarks>This class handles the request envelope, depending on <c>XmlRpcSerializer</c>
/// to serialize the payload.</remarks>
/// <seealso cref="XmlRpcSerializer"/>
public class XmlRpcRequestSerializer : XmlRpcSerializer
{
static private XmlRpcRequestSerializer _singleton;
/// <summary>A static singleton instance of this deserializer.</summary>
static public XmlRpcRequestSerializer Singleton
{
get
{
if (_singleton == null)
_singleton = new XmlRpcRequestSerializer();
return _singleton;
}
}
/// <summary>Serialize the <c>XmlRpcRequest</c> to the output stream.</summary>
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
/// <param name="obj">An <c>XmlRpcRequest</c> to serialize.</param>
/// <seealso cref="XmlRpcRequest"/>
override public void Serialize(XmlTextWriter output, Object obj)
{
XmlRpcRequest request = (XmlRpcRequest)obj;
output.WriteStartDocument();
output.WriteStartElement(METHOD_CALL);
output.WriteElementString(METHOD_NAME, request.MethodName);
output.WriteStartElement(PARAMS);
foreach (Object param in request.Params)
{
output.WriteStartElement(PARAM);
output.WriteStartElement(VALUE);
SerializeObject(output, param);
output.WriteEndElement();
output.WriteEndElement();
}
output.WriteEndElement();
output.WriteEndElement();
}
}
}

View File

@@ -0,0 +1,98 @@
namespace Nwc.XmlRpc
{
using System;
using System.Xml;
using System.Net.Sockets;
/// <summary>The class is a container of the context of an XML-RPC dialog on the server side.</summary>
/// <remarks>Instances of this class maintain the context for an individual XML-RPC server
/// side dialog. Namely they manage an inbound deserializer and an outbound serializer. </remarks>
public class XmlRpcResponder
{
private XmlRpcRequestDeserializer _deserializer = new XmlRpcRequestDeserializer();
private XmlRpcResponseSerializer _serializer = new XmlRpcResponseSerializer();
private XmlRpcServer _server;
private TcpClient _client;
private SimpleHttpRequest _httpReq;
/// <summary>The SimpleHttpRequest based on the TcpClient.</summary>
public SimpleHttpRequest HttpReq
{
get { return _httpReq; }
}
/// <summary>Basic constructor.</summary>
/// <param name="server">XmlRpcServer that this XmlRpcResponder services.</param>
/// <param name="client">TcpClient with the connection.</param>
public XmlRpcResponder(XmlRpcServer server, TcpClient client)
{
_server = server;
_client = client;
_httpReq = new SimpleHttpRequest(_client);
}
/// <summary>Call close to insure proper shutdown.</summary>
~XmlRpcResponder()
{
Close();
}
///<summary>Respond using this responders HttpReq.</summary>
public void Respond()
{
Respond(HttpReq);
}
/// <summary>Handle an HTTP request containing an XML-RPC request.</summary>
/// <remarks>This method deserializes the XML-RPC request, invokes the
/// described method, serializes the response (or fault) and sends the XML-RPC response
/// back as a valid HTTP page.
/// </remarks>
/// <param name="httpReq"><c>SimpleHttpRequest</c> containing the request.</param>
public void Respond(SimpleHttpRequest httpReq)
{
XmlRpcRequest xmlRpcReq = (XmlRpcRequest)_deserializer.Deserialize(httpReq.Input);
XmlRpcResponse xmlRpcResp = new XmlRpcResponse();
try
{
xmlRpcResp.Value = _server.Invoke(xmlRpcReq);
}
catch (XmlRpcException e)
{
xmlRpcResp.SetFault(e.FaultCode, e.FaultString);
}
catch (Exception e2)
{
xmlRpcResp.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
}
if (Logger.Delegate != null)
Logger.WriteEntry(xmlRpcResp.ToString(), LogLevel.Information);
XmlRpcServer.HttpHeader(httpReq.Protocol, "text/xml", 0, " 200 OK", httpReq.Output);
httpReq.Output.Flush();
XmlTextWriter xml = new XmlTextWriter(httpReq.Output);
_serializer.Serialize(xml, xmlRpcResp);
xml.Flush();
httpReq.Output.Flush();
}
///<summary>Close all contained resources, both the HttpReq and client.</summary>
public void Close()
{
if (_httpReq != null)
{
_httpReq.Close();
_httpReq = null;
}
if (_client != null)
{
_client.Close();
_client = null;
}
}
}
}

View File

@@ -0,0 +1,85 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
/// <summary>Class designed to represent an XML-RPC response.</summary>
public class XmlRpcResponse
{
private Object _value;
/// <summary><c>bool</c> indicating if this response represents a fault.</summary>
public bool IsFault;
/// <summary>Basic constructor</summary>
public XmlRpcResponse()
{
Value = null;
IsFault = false;
}
/// <summary>Constructor for a fault.</summary>
/// <param name="code"><c>int</c> the numeric faultCode value.</param>
/// <param name="message"><c>String</c> the faultString value.</param>
public XmlRpcResponse(int code, String message)
: this()
{
SetFault(code, message);
}
/// <summary>The data value of the response, may be fault data.</summary>
public Object Value
{
get { return _value; }
set
{
IsFault = false;
_value = value;
}
}
/// <summary>The faultCode if this is a fault.</summary>
public int FaultCode
{
get
{
if (!IsFault)
return 0;
else
return (int)((Hashtable)_value)[XmlRpcXmlTokens.FAULT_CODE];
}
}
/// <summary>The faultString if this is a fault.</summary>
public String FaultString
{
get
{
if (!IsFault)
return "";
else
return (String)((Hashtable)_value)[XmlRpcXmlTokens.FAULT_STRING];
}
}
/// <summary>Set this response to be a fault.</summary>
/// <param name="code"><c>int</c> the numeric faultCode value.</param>
/// <param name="message"><c>String</c> the faultString value.</param>
public void SetFault(int code, String message)
{
Hashtable fault = new Hashtable();
fault.Add("faultCode", code);
fault.Add("faultString", message);
Value = fault;
IsFault = true;
}
/// <summary>Form a useful string representation of the object, in this case the XML response.</summary>
/// <returns><c>String</c> The XML serialized XML-RPC response.</returns>
override public String ToString()
{
return XmlRpcResponseSerializer.Singleton.Serialize(this);
}
}
}

View File

@@ -0,0 +1,65 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
/// <summary>Class to deserialize XML data representing a response.</summary>
public class XmlRpcResponseDeserializer : XmlRpcDeserializer
{
static private XmlRpcResponseDeserializer _singleton;
/// <summary>A static singleton instance of this deserializer.</summary>
[Obsolete("This object is now thread safe, just use an instance.", false)]
static public XmlRpcResponseDeserializer Singleton
{
get
{
if (_singleton == null)
_singleton = new XmlRpcResponseDeserializer();
return _singleton;
}
}
/// <summary>Static method that parses XML data into a response using the Singleton.</summary>
/// <param name="xmlData"><c>StreamReader</c> containing an XML-RPC response.</param>
/// <returns><c>XmlRpcResponse</c> object resulting from the parse.</returns>
override public Object Deserialize(TextReader xmlData)
{
XmlTextReader reader = new XmlTextReader(xmlData);
XmlRpcResponse response = new XmlRpcResponse();
bool done = false;
lock (this)
{
Reset();
while (!done && reader.Read())
{
DeserializeNode(reader); // Parent parse...
switch (reader.NodeType)
{
case XmlNodeType.EndElement:
switch (reader.Name)
{
case FAULT:
response.Value = _value;
response.IsFault = true;
break;
case PARAM:
response.Value = _value;
_value = null;
_text = null;
break;
}
break;
default:
break;
}
}
}
return response;
}
}
}

View File

@@ -0,0 +1,57 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.Xml;
/// <summary>Class responsible for serializing an XML-RPC response.</summary>
/// <remarks>This class handles the response envelope, depending on XmlRpcSerializer
/// to serialize the payload.</remarks>
/// <seealso cref="XmlRpcSerializer"/>
public class XmlRpcResponseSerializer : XmlRpcSerializer
{
static private XmlRpcResponseSerializer _singleton;
/// <summary>A static singleton instance of this deserializer.</summary>
static public XmlRpcResponseSerializer Singleton
{
get
{
if (_singleton == null)
_singleton = new XmlRpcResponseSerializer();
return _singleton;
}
}
/// <summary>Serialize the <c>XmlRpcResponse</c> to the output stream.</summary>
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
/// <param name="obj">An <c>Object</c> to serialize.</param>
/// <seealso cref="XmlRpcResponse"/>
override public void Serialize(XmlTextWriter output, Object obj)
{
XmlRpcResponse response = (XmlRpcResponse)obj;
output.WriteStartDocument();
output.WriteStartElement(METHOD_RESPONSE);
if (response.IsFault)
output.WriteStartElement(FAULT);
else
{
output.WriteStartElement(PARAMS);
output.WriteStartElement(PARAM);
}
output.WriteStartElement(VALUE);
SerializeObject(output, response.Value);
output.WriteEndElement();
output.WriteEndElement();
if (!response.IsFault)
output.WriteEndElement();
output.WriteEndElement();
}
}
}

View File

@@ -0,0 +1,109 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Xml;
/// <summary>Base class of classes serializing data to XML-RPC's XML format.</summary>
/// <remarks>This class handles the basic type conversions like Integer to &lt;i4&gt;. </remarks>
/// <seealso cref="XmlRpcXmlTokens"/>
public class XmlRpcSerializer : XmlRpcXmlTokens
{
/// <summary>Serialize the <c>XmlRpcRequest</c> to the output stream.</summary>
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
/// <param name="obj">An <c>Object</c> to serialize.</param>
/// <seealso cref="XmlRpcRequest"/>
virtual public void Serialize(XmlTextWriter output, Object obj)
{
}
/// <summary>Serialize the <c>XmlRpcRequest</c> to a String.</summary>
/// <remarks>Note this may represent a real memory hog for a large request.</remarks>
/// <param name="obj">An <c>Object</c> to serialize.</param>
/// <returns><c>String</c> containing XML-RPC representation of the request.</returns>
/// <seealso cref="XmlRpcRequest"/>
public String Serialize(Object obj)
{
StringWriter strBuf = new StringWriter();
XmlTextWriter xml = new XmlTextWriter(strBuf);
xml.Formatting = Formatting.Indented;
xml.Indentation = 4;
Serialize(xml, obj);
xml.Flush();
String returns = strBuf.ToString();
xml.Close();
return returns;
}
/// <remarks>Serialize the object to the output stream.</remarks>
/// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
/// <param name="obj">An <c>Object</c> to serialize.</param>
public void SerializeObject(XmlTextWriter output, Object obj)
{
if (obj == null)
return;
if (obj is byte[])
{
byte[] ba = (byte[])obj;
output.WriteStartElement(BASE64);
output.WriteBase64(ba, 0, ba.Length);
output.WriteEndElement();
}
else if (obj is String)
{
output.WriteElementString(STRING, obj.ToString());
}
else if (obj is Int32)
{
output.WriteElementString(INT, obj.ToString());
}
else if (obj is DateTime)
{
output.WriteElementString(DATETIME, ((DateTime)obj).ToString(ISO_DATETIME));
}
else if (obj is Double)
{
output.WriteElementString(DOUBLE, obj.ToString());
}
else if (obj is Boolean)
{
output.WriteElementString(BOOLEAN, ((((Boolean)obj) == true) ? "1" : "0"));
}
else if (obj is IList)
{
output.WriteStartElement(ARRAY);
output.WriteStartElement(DATA);
if (((ArrayList)obj).Count > 0)
{
foreach (Object member in ((IList)obj))
{
output.WriteStartElement(VALUE);
SerializeObject(output, member);
output.WriteEndElement();
}
}
output.WriteEndElement();
output.WriteEndElement();
}
else if (obj is IDictionary)
{
IDictionary h = (IDictionary)obj;
output.WriteStartElement(STRUCT);
foreach (String key in h.Keys)
{
output.WriteStartElement(MEMBER);
output.WriteElementString(NAME, key);
output.WriteStartElement(VALUE);
SerializeObject(output, h[key]);
output.WriteEndElement();
output.WriteEndElement();
}
output.WriteEndElement();
}
}
}
}

View File

@@ -0,0 +1,239 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Xml;
/// <summary>A restricted HTTP server for use with XML-RPC.</summary>
/// <remarks>It only handles POST requests, and only POSTs representing XML-RPC calls.
/// In addition to dispatching requests it also provides a registry for request handlers.
/// </remarks>
public class XmlRpcServer : IEnumerable
{
#pragma warning disable 0414 // disable "private field assigned but not used"
const int RESPONDER_COUNT = 10;
private TcpListener _myListener;
private int _port;
private IPAddress _address;
private IDictionary _handlers;
private XmlRpcSystemObject _system;
private WaitCallback _wc;
#pragma warning restore 0414
///<summary>Constructor with port and address.</summary>
///<remarks>This constructor sets up a TcpListener listening on the
///given port and address. It also calls a Thread on the method StartListen().</remarks>
///<param name="address"><c>IPAddress</c> value of the address to listen on.</param>
///<param name="port"><c>Int</c> value of the port to listen on.</param>
public XmlRpcServer(IPAddress address, int port)
{
_port = port;
_address = address;
_handlers = new Hashtable();
_system = new XmlRpcSystemObject(this);
_wc = new WaitCallback(WaitCallback);
}
///<summary>Basic constructor.</summary>
///<remarks>This constructor sets up a TcpListener listening on the
///given port. It also calls a Thread on the method StartListen(). IPAddress.Any
///is assumed as the address here.</remarks>
///<param name="port"><c>Int</c> value of the port to listen on.</param>
public XmlRpcServer(int port) : this(IPAddress.Any, port) { }
/// <summary>Start the server.</summary>
public void Start()
{
try
{
Stop();
//start listing on the given port
// IPAddress addr = IPAddress.Parse("127.0.0.1");
lock (this)
{
_myListener = new TcpListener(IPAddress.Any, _port);
_myListener.Start();
//start the thread which calls the method 'StartListen'
Thread th = new Thread(new ThreadStart(StartListen));
th.Start();
}
}
catch (Exception e)
{
Logger.WriteEntry("An Exception Occurred while Listening :" + e.ToString(), LogLevel.Error);
}
}
/// <summary>Stop the server.</summary>
public void Stop()
{
try
{
if (_myListener != null)
{
lock (this)
{
_myListener.Stop();
_myListener = null;
}
}
}
catch (Exception e)
{
Logger.WriteEntry("An Exception Occurred while stopping :" +
e.ToString(), LogLevel.Error);
}
}
/// <summary>Get an enumeration of my XML-RPC handlers.</summary>
/// <returns><c>IEnumerable</c> the handler enumeration.</returns>
public IEnumerator GetEnumerator()
{
return _handlers.GetEnumerator();
}
/// <summary>Retrieve a handler by name.</summary>
/// <param name="name"><c>String</c> naming a handler</param>
/// <returns><c>Object</c> that is the handler.</returns>
public Object this[String name]
{
get { return _handlers[name]; }
}
///<summary>
///This method Accepts new connections and dispatches them when appropriate.
///</summary>
public void StartListen()
{
while (true && _myListener != null)
{
//Accept a new connection
XmlRpcResponder responder = new XmlRpcResponder(this, _myListener.AcceptTcpClient());
ThreadPool.QueueUserWorkItem(_wc, responder);
}
}
///<summary>
///Add an XML-RPC handler object by name.
///</summary>
///<param name="name"><c>String</c> XML-RPC dispatch name of this object.</param>
///<param name="obj"><c>Object</c> The object that is the XML-RPC handler.</param>
public void Add(String name, Object obj)
{
_handlers.Add(name, obj);
}
///<summary>Return a C# object.method name for and XML-RPC object.method name pair.</summary>
///<param name="methodName">The XML-RPC object.method.</param>
///<returns><c>String</c> of form object.method for the underlying C# method.</returns>
public String MethodName(String methodName)
{
int dotAt = methodName.LastIndexOf('.');
if (dotAt == -1)
{
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Bad method name " + methodName);
}
String objectName = methodName.Substring(0, dotAt);
Object target = _handlers[objectName];
if (target == null)
{
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Object " + objectName + " not found");
}
return target.GetType().FullName + "." + methodName.Substring(dotAt + 1);
}
///<summary>Invoke a method described in a request.</summary>
///<param name="req"><c>XmlRpcRequest</c> containing a method descriptions.</param>
/// <seealso cref="XmlRpcSystemObject.Invoke"/>
/// <seealso cref="XmlRpcServer.Invoke(String,String,IList)"/>
public Object Invoke(XmlRpcRequest req)
{
return Invoke(req.MethodNameObject, req.MethodNameMethod, req.Params);
}
///<summary>Invoke a method on a named handler.</summary>
///<param name="objectName"><c>String</c> The name of the handler.</param>
///<param name="methodName"><c>String</c> The name of the method to invoke on the handler.</param>
///<param name="parameters"><c>IList</c> The parameters to invoke the method with.</param>
/// <seealso cref="XmlRpcSystemObject.Invoke"/>
public Object Invoke(String objectName, String methodName, IList parameters)
{
Object target = _handlers[objectName];
if (target == null)
{
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Object " + objectName + " not found");
}
return XmlRpcSystemObject.Invoke(target, methodName, parameters);
}
/// <summary>The method the thread pool invokes when a thread is available to handle an HTTP request.</summary>
/// <param name="responder">TcpClient from the socket accept.</param>
public void WaitCallback(object responder)
{
XmlRpcResponder resp = (XmlRpcResponder)responder;
if (resp.HttpReq.HttpMethod == "POST")
{
try
{
resp.Respond();
}
catch (Exception e)
{
Logger.WriteEntry("Failed on post: " + e, LogLevel.Error);
}
}
else
{
Logger.WriteEntry("Only POST methods are supported: " + resp.HttpReq.HttpMethod +
" ignored", LogLevel.Error);
}
resp.Close();
}
/// <summary>
/// This function send the Header Information to the client (Browser)
/// </summary>
/// <param name="sHttpVersion">HTTP Version</param>
/// <param name="sMIMEHeader">Mime Type</param>
/// <param name="iTotBytes">Total Bytes to be sent in the body</param>
/// <param name="sStatusCode"></param>
/// <param name="output">Socket reference</param>
static public void HttpHeader(string sHttpVersion, string sMIMEHeader, long iTotBytes, string sStatusCode, TextWriter output)
{
String sBuffer = "";
// if Mime type is not provided set default to text/html
if (sMIMEHeader.Length == 0)
{
sMIMEHeader = "text/html"; // Default Mime Type is text/html
}
sBuffer += sHttpVersion + sStatusCode + "\r\n";
sBuffer += "Connection: close\r\n";
if (iTotBytes > 0)
sBuffer += "Content-Length: " + iTotBytes + "\r\n";
sBuffer += "Server: XmlRpcServer \r\n";
sBuffer += "Content-Type: " + sMIMEHeader + "\r\n";
sBuffer += "\r\n";
output.Write(sBuffer);
}
}
}

View File

@@ -0,0 +1,252 @@
namespace Nwc.XmlRpc
{
using System;
using System.Collections;
using System.Reflection;
/// <summary> XML-RPC System object implementation of extended specifications.</summary>
[XmlRpcExposed]
public class XmlRpcSystemObject
{
private XmlRpcServer _server;
static private IDictionary _methodHelp = new Hashtable();
/// <summary>Static <c>IDictionary</c> to hold mappings of method name to associated documentation String</summary>
static public IDictionary MethodHelp
{
get { return _methodHelp; }
}
/// <summary>Constructor.</summary>
/// <param name="server"><c>XmlRpcServer</c> server to be the system object for.</param>
public XmlRpcSystemObject(XmlRpcServer server)
{
_server = server;
server.Add("system", this);
_methodHelp.Add(this.GetType().FullName + ".methodHelp", "Return a string description.");
}
/// <summary>Invoke a method on a given object.</summary>
/// <remarks>Using reflection, and respecting the <c>XmlRpcExposed</c> attribute,
/// invoke the <paramref>methodName</paramref> method on the <paramref>target</paramref>
/// instance with the <paramref>parameters</paramref> provided. All this packages other <c>Invoke</c> methods
/// end up calling this.</remarks>
/// <returns><c>Object</c> the value the invoked method returns.</returns>
/// <exception cref="XmlRpcException">If method does not exist, is not exposed, parameters invalid, or invocation
/// results in an exception. Note, the <c>XmlRpcException.Code</c> will indicate cause.</exception>
static public Object Invoke(Object target, String methodName, IList parameters)
{
if (target == null)
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Invalid target object.");
Type type = target.GetType();
MethodInfo method = type.GetMethod(methodName);
try
{
if (!XmlRpcExposedAttribute.ExposedMethod(target, methodName))
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Method " + methodName + " is not exposed.");
}
catch (MissingMethodException me)
{
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": " + me.Message);
}
Object[] args = new Object[parameters.Count];
int index = 0;
foreach (Object arg in parameters)
{
args[index] = arg;
index++;
}
try
{
Object retValue = method.Invoke(target, args);
if (retValue == null)
throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": Method returned NULL.");
return retValue;
}
catch (XmlRpcException e)
{
throw e;
}
catch (ArgumentException ae)
{
Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + ae.Message,
LogLevel.Information);
String call = methodName + "( ";
foreach (Object o in args)
{
call += o.GetType().Name;
call += " ";
}
call += ")";
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement type mismatch invoking " + call);
}
catch (TargetParameterCountException tpce)
{
Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + tpce.Message,
LogLevel.Information);
throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement count mismatch invoking " + methodName);
}
catch (TargetInvocationException tie)
{
throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + " Invoked method " + methodName + ": " + tie.Message);
}
}
/// <summary>List methods available on all handlers of this server.</summary>
/// <returns><c>IList</c> An array of <c>Strings</c>, each <c>String</c> will have form "object.method".</returns>
[XmlRpcExposed]
public IList listMethods()
{
IList methods = new ArrayList();
Boolean considerExposure;
foreach (DictionaryEntry handlerEntry in _server)
{
considerExposure = XmlRpcExposedAttribute.IsExposed(handlerEntry.Value.GetType());
foreach (MemberInfo mi in handlerEntry.Value.GetType().GetMembers())
{
if (mi.MemberType != MemberTypes.Method)
continue;
if (!((MethodInfo)mi).IsPublic)
continue;
if (considerExposure && !XmlRpcExposedAttribute.IsExposed(mi))
continue;
methods.Add(handlerEntry.Key + "." + mi.Name);
}
}
return methods;
}
/// <summary>Given a method name return the possible signatures for it.</summary>
/// <param name="name"><c>String</c> The object.method name to look up.</param>
/// <returns><c>IList</c> Of arrays of signatures.</returns>
[XmlRpcExposed]
public IList methodSignature(String name)
{
IList signatures = new ArrayList();
int index = name.IndexOf('.');
if (index < 0)
return signatures;
String oName = name.Substring(0, index);
Object obj = _server[oName];
if (obj == null)
return signatures;
MemberInfo[] mi = obj.GetType().GetMember(name.Substring(index + 1));
if (mi == null || mi.Length != 1) // for now we want a single signature
return signatures;
MethodInfo method;
try
{
method = (MethodInfo)mi[0];
}
catch (Exception e)
{
Logger.WriteEntry("Attempted methodSignature call on " + mi[0] + " caused: " + e,
LogLevel.Information);
return signatures;
}
if (!method.IsPublic)
return signatures;
IList signature = new ArrayList();
signature.Add(method.ReturnType.Name);
foreach (ParameterInfo param in method.GetParameters())
{
signature.Add(param.ParameterType.Name);
}
signatures.Add(signature);
return signatures;
}
/// <summary>Help for given method signature. Not implemented yet.</summary>
/// <param name="name"><c>String</c> The object.method name to look up.</param>
/// <returns><c>String</c> help text. Rich HTML text.</returns>
[XmlRpcExposed]
public String methodHelp(String name)
{
String help = null;
try
{
help = (String)_methodHelp[_server.MethodName(name)];
}
catch (XmlRpcException e)
{
throw e;
}
catch (Exception) { /* ignored */ };
if (help == null)
help = "No help available for: " + name;
return help;
}
/// <summary>Boxcarring support method.</summary>
/// <param name="calls"><c>IList</c> of calls</param>
/// <returns><c>ArrayList</c> of results/faults.</returns>
[XmlRpcExposed]
public IList multiCall(IList calls)
{
IList responses = new ArrayList();
XmlRpcResponse fault = new XmlRpcResponse();
foreach (IDictionary call in calls)
{
try
{
XmlRpcRequest req = new XmlRpcRequest((String)call[XmlRpcXmlTokens.METHOD_NAME],
(ArrayList)call[XmlRpcXmlTokens.PARAMS]);
Object results = _server.Invoke(req);
IList response = new ArrayList();
response.Add(results);
responses.Add(response);
}
catch (XmlRpcException e)
{
fault.SetFault(e.FaultCode, e.FaultString);
responses.Add(fault.Value);
}
catch (Exception e2)
{
fault.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
responses.Add(fault.Value);
}
}
return responses;
}
}
}

View File

@@ -0,0 +1,76 @@
namespace Nwc.XmlRpc
{
using System;
/// <summary>Class collecting <c>String</c> tokens that are part of XML-RPC files.</summary>
public class XmlRpcXmlTokens
{
/// <summary>C# formatting string to describe an ISO 8601 date.</summary>
public const String ISO_DATETIME = "yyyyMMdd\\THH\\:mm\\:ss";
/// <summary>Base64 field indicator.</summary>
/// <remarks>Corresponds to the &lt;base64&gt; tag.</remarks>
public const String BASE64 = "base64";
/// <summary>String field indicator.</summary>
/// <remarks>Corresponds to the &lt;string&gt; tag.</remarks>
public const String STRING = "string";
/// <summary>Integer field integer.</summary>
/// <remarks>Corresponds to the &lt;i4&gt; tag.</remarks>
public const String INT = "i4";
/// <summary>Alternate integer field indicator.</summary>
/// <remarks>Corresponds to the &lt;int&gt; tag.</remarks>
public const String ALT_INT = "int";
/// <summary>Date field indicator.</summary>
/// <remarks>Corresponds to the &lt;dateTime.iso8601&gt; tag.</remarks>
public const String DATETIME = "dateTime.iso8601";
/// <summary>Boolean field indicator.</summary>
/// <remarks>Corresponds to the &lt;boolean&gt; tag.</remarks>
public const String BOOLEAN = "boolean";
/// <summary>Value token.</summary>
/// <remarks>Corresponds to the &lt;value&gt; tag.</remarks>
public const String VALUE = "value";
/// <summary>Name token.</summary>
/// <remarks>Corresponds to the &lt;name&gt; tag.</remarks>
public const String NAME = "name";
/// <summary>Array field indicator..</summary>
/// <remarks>Corresponds to the &lt;array&gt; tag.</remarks>
public const String ARRAY = "array";
/// <summary>Data token.</summary>
/// <remarks>Corresponds to the &lt;data&gt; tag.</remarks>
public const String DATA = "data";
/// <summary>Member token.</summary>
/// <remarks>Corresponds to the &lt;member&gt; tag.</remarks>
public const String MEMBER = "member";
/// <summary>Stuct field indicator.</summary>
/// <remarks>Corresponds to the &lt;struct&gt; tag.</remarks>
public const String STRUCT = "struct";
/// <summary>Double field indicator.</summary>
/// <remarks>Corresponds to the &lt;double&gt; tag.</remarks>
public const String DOUBLE = "double";
/// <summary>Param token.</summary>
/// <remarks>Corresponds to the &lt;param&gt; tag.</remarks>
public const String PARAM = "param";
/// <summary>Params token.</summary>
/// <remarks>Corresponds to the &lt;params&gt; tag.</remarks>
public const String PARAMS = "params";
/// <summary>MethodCall token.</summary>
/// <remarks>Corresponds to the &lt;methodCall&gt; tag.</remarks>
public const String METHOD_CALL = "methodCall";
/// <summary>MethodName token.</summary>
/// <remarks>Corresponds to the &lt;methodName&gt; tag.</remarks>
public const String METHOD_NAME = "methodName";
/// <summary>MethodResponse token</summary>
/// <remarks>Corresponds to the &lt;methodResponse&gt; tag.</remarks>
public const String METHOD_RESPONSE = "methodResponse";
/// <summary>Fault response token.</summary>
/// <remarks>Corresponds to the &lt;fault&gt; tag.</remarks>
public const String FAULT = "fault";
/// <summary>FaultCode token.</summary>
/// <remarks>Corresponds to the &lt;faultCode&gt; tag.</remarks>
public const String FAULT_CODE = "faultCode";
/// <summary>FaultString token.</summary>
/// <remarks>Corresponds to the &lt;faultString&gt; tag.</remarks>
public const String FAULT_STRING = "faultString";
}
}

View File

@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SecondGlance")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SecondGlance")]
[assembly: AssemblyCopyright("Copyright © 2006")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("02456c47-f074-4302-a3a3-01a719de9d20")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.308
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SecondGlance.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SecondGlance.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.308
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SecondGlance.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace SecondGlance
{
static class SecondGlance
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmSecondGlance());
}
}
}

View File

@@ -0,0 +1,98 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D72C92D1-559A-48A7-93F5-99F4E99F3F98}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SecondGlance</RootNamespace>
<AssemblyName>SecondGlance</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-docs|AnyCPU' ">
<OutputPath>bin\Release-docs\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="frmSecondGlance.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmSecondGlance.Designer.cs">
<DependentUpon>frmSecondGlance.cs</DependentUpon>
</Compile>
<Compile Include="SecondGlance.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="frmSecondGlance.resx">
<SubType>Designer</SubType>
<DependentUpon>frmSecondGlance.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libsecondlife\OpenMetaverse.csproj">
<Project>{D9CDEDFB-8169-4B03-B57F-0DF638F044EC}</Project>
<Name>OpenMetaverse</Name>
</ProjectReference>
<ProjectReference Include="..\SLProxy\SLProxy.csproj">
<Project>{E4115DC9-FC88-47D6-B3B6-2400AD19B80D}</Project>
<Name>SLProxy</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,232 @@
namespace SecondGlance
{
partial class frmSecondGlance
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.cboToLog = new System.Windows.Forms.ComboBox();
this.cmdAddLogger = new System.Windows.Forms.Button();
this.cmdDontLog = new System.Windows.Forms.Button();
this.cboLogged = new System.Windows.Forms.ComboBox();
this.lstPackets = new System.Windows.Forms.ListBox();
this.panel1.SuspendLayout();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.Controls.Add(this.splitContainer1);
this.panel1.Location = new System.Drawing.Point(29, 100);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(664, 333);
this.panel1.TabIndex = 0;
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.lstPackets);
this.splitContainer1.Size = new System.Drawing.Size(664, 333);
this.splitContainer1.SplitterDistance = 294;
this.splitContainer1.TabIndex = 0;
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem,
this.aboutToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(705, 24);
this.menuStrip1.TabIndex = 1;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.newToolStripMenuItem,
this.openToolStripMenuItem,
this.toolStripMenuItem1,
this.saveToolStripMenuItem,
this.toolStripMenuItem2,
this.exitToolStripMenuItem});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "File";
//
// newToolStripMenuItem
//
this.newToolStripMenuItem.Name = "newToolStripMenuItem";
this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
this.newToolStripMenuItem.Size = new System.Drawing.Size(188, 22);
this.newToolStripMenuItem.Text = "New Session";
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
this.openToolStripMenuItem.Size = new System.Drawing.Size(188, 22);
this.openToolStripMenuItem.Text = "Open Session";
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(185, 6);
//
// saveToolStripMenuItem
//
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
this.saveToolStripMenuItem.Size = new System.Drawing.Size(188, 22);
this.saveToolStripMenuItem.Text = "Save Session";
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(185, 6);
//
// exitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(188, 22);
this.exitToolStripMenuItem.Text = "Exit";
//
// aboutToolStripMenuItem
//
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(52, 20);
this.aboutToolStripMenuItem.Text = "About";
//
// cboToLog
//
this.cboToLog.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboToLog.FormattingEnabled = true;
this.cboToLog.Location = new System.Drawing.Point(12, 27);
this.cboToLog.Name = "cboToLog";
this.cboToLog.Size = new System.Drawing.Size(150, 21);
this.cboToLog.TabIndex = 4;
//
// cmdAddLogger
//
this.cmdAddLogger.Location = new System.Drawing.Point(168, 25);
this.cmdAddLogger.Name = "cmdAddLogger";
this.cmdAddLogger.Size = new System.Drawing.Size(75, 23);
this.cmdAddLogger.TabIndex = 5;
this.cmdAddLogger.Text = "Log";
this.cmdAddLogger.UseVisualStyleBackColor = true;
this.cmdAddLogger.Click += new System.EventHandler(this.cmdAddLogger_Click);
//
// cmdDontLog
//
this.cmdDontLog.Location = new System.Drawing.Point(430, 25);
this.cmdDontLog.Name = "cmdDontLog";
this.cmdDontLog.Size = new System.Drawing.Size(75, 23);
this.cmdDontLog.TabIndex = 7;
this.cmdDontLog.Text = "Don\'t Log";
this.cmdDontLog.UseVisualStyleBackColor = true;
this.cmdDontLog.Click += new System.EventHandler(this.cmdDontLog_Click);
//
// cboLogged
//
this.cboLogged.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboLogged.FormattingEnabled = true;
this.cboLogged.Location = new System.Drawing.Point(274, 27);
this.cboLogged.Name = "cboLogged";
this.cboLogged.Size = new System.Drawing.Size(150, 21);
this.cboLogged.TabIndex = 6;
//
// lstPackets
//
this.lstPackets.FormattingEnabled = true;
this.lstPackets.Location = new System.Drawing.Point(26, 40);
this.lstPackets.Name = "lstPackets";
this.lstPackets.Size = new System.Drawing.Size(243, 277);
this.lstPackets.TabIndex = 1;
//
// frmSecondGlance
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(705, 498);
this.Controls.Add(this.cmdDontLog);
this.Controls.Add(this.cboLogged);
this.Controls.Add(this.cmdAddLogger);
this.Controls.Add(this.cboToLog);
this.Controls.Add(this.panel1);
this.Controls.Add(this.menuStrip1);
this.MainMenuStrip = this.menuStrip1;
this.Name = "frmSecondGlance";
this.Text = "Second Glance";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmSecondGlance_FormClosing);
this.panel1.ResumeLayout(false);
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.ResumeLayout(false);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.ComboBox cboToLog;
private System.Windows.Forms.Button cmdAddLogger;
private System.Windows.Forms.Button cmdDontLog;
private System.Windows.Forms.ComboBox cboLogged;
private System.Windows.Forms.ListBox lstPackets;
}
}

View File

@@ -0,0 +1,154 @@
/*
*
* Copyright (c) 2007 openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Net;
using System.Windows.Forms;
using OpenMetaverse;
using OpenMetaverse.Packets;
using SLProxy;
namespace SecondGlance
{
public partial class frmSecondGlance : Form
{
private Proxy Proxy;
private Queue<LoggedPacket> Inbox = new Queue<LoggedPacket>();
private System.Timers.Timer DisplayTimer = new System.Timers.Timer(200);
public frmSecondGlance()
{
InitializeComponent();
PacketType[] types = (PacketType[])Enum.GetValues(typeof(PacketType));
// Fill up the "To Log" combo box with options
foreach (PacketType type in types)
{
if (type != PacketType.Default) cboToLog.Items.Add(type);
}
// Set the default selection to the first entry
cboToLog.SelectedIndex = 0;
// Setup the proxy
ProxyConfig proxyConfig = new ProxyConfig("Second Glance", "John Hurliman <jhurliman@wsu.edu>",
new string[0]);
Proxy = new Proxy(proxyConfig);
Proxy.Start();
// Start the timer that moves packets from the queue and displays them
DisplayTimer.Elapsed += new System.Timers.ElapsedEventHandler(DisplayTimer_Elapsed);
DisplayTimer.Start();
}
void DisplayTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.BeginInvoke(new MethodInvoker(UpdateDisplay));
}
void UpdateDisplay()
{
lock (Inbox)
{
while (Inbox.Count > 0)
{
lstPackets.Items.Add(Inbox.Dequeue());
}
}
}
private void frmSecondGlance_FormClosing(object sender, FormClosingEventArgs e)
{
DisplayTimer.Stop();
Proxy.Stop();
}
private void cmdAddLogger_Click(object sender, EventArgs e)
{
if (!cboLogged.Items.Contains(cboToLog.SelectedItem))
{
PacketType type = (PacketType)cboToLog.SelectedItem;
cboLogged.Items.Add(type);
Proxy.AddDelegate(type, Direction.Incoming, new PacketDelegate(IncomingPacketHandler));
Proxy.AddDelegate(type, Direction.Outgoing, new PacketDelegate(OutgoingPacketHandler));
}
}
private void cmdDontLog_Click(object sender, EventArgs e)
{
;
}
private Packet IncomingPacketHandler(Packet packet, IPEndPoint sim)
{
return PacketHandler(packet, sim, Direction.Incoming);
}
private Packet OutgoingPacketHandler(Packet packet, IPEndPoint sim)
{
return PacketHandler(packet, sim, Direction.Outgoing);
}
private Packet PacketHandler(Packet packet, IPEndPoint sim, Direction direction)
{
LoggedPacket logged = new LoggedPacket();
logged.Packet = packet;
logged.Sim = sim;
logged.Direction = direction;
lock (Inbox)
Inbox.Enqueue(logged);
// TODO: Packet modifications
return packet;
}
}
public class LoggedPacket
{
public Packet Packet;
public IPEndPoint Sim;
public Direction Direction;
public override string ToString()
{
string text = (Direction == Direction.Incoming) ? "<-- " : "--> ";
text += Sim.ToString() + " " + Packet.Type.ToString();
return text;
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0"?>
<project name="libsecondlife" default="build">
<!-- global framework settings -->
<property name="target.framework" value="${framework::get-target-framework()}" />
<property name="assembly.dir" value="${framework::get-assembly-directory(target.framework)}" />
<!-- global project settings -->
<xmlpeek
file="../libsecondlife.build"
xpath="/project/property[@name = 'project.version']/@value"
property="project.version" />
<property name="build.number"
value="${math::abs(math::floor(timespan::get-total-days(datetime::now()
- datetime::parse('01/01/2002'))))}" />
<property name="assembly" value="SLProxy"/>
<property name="bin_dir" value="../bin" />
<!-- default configuration -->
<property name="project.config" value="debug" /> <!-- debug|release -->
<!-- named configurations -->
<target name="init" description="Initializes build properties">
<call target="${project.config}" />
</target>
<target name="debug" description="configures a debug build">
<property name="build.debug" value="true" />
<property name="package.name"
value="${project::get-name()}-${project.version}-${project.config}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()} [${project.config}]" />
</target>
<target name="release" description="configures a release build">
<property name="project.config" value="release" />
<property name="build.debug" value="false" />
<property name="package.name"
value="${project::get-name()}-${project.version}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()}" />
</target>
<!-- build tasks -->
<target name="build"
depends="init"
description="build VoiceTest">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="exe"
debug="${build.debug}"
output="${bin_dir}/VoiceTest.exe">
<sources failonempty="true">
<include name="VoiceTest.cs" />
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
</references>
</csc>
</target>
<target name="clean" depends="init"
description="Deletes the current configuration">
<delete failonerror="false">
<fileset basedir="${bin_dir}/">
<include name="VoiceTest.exe" />
<include name="VoiceTest.exe.mdb" />
</fileset>
</delete>
</target>
<target
name="*"
description="Handles unknown targets">
<echo message="skipping unknown target" />
</target>
</project>

View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2006-2008, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Utilities;
namespace VoiceTest
{
public class VoiceException: Exception
{
public bool LoggedIn = false;
public VoiceException(string msg): base(msg)
{
}
public VoiceException(string msg, bool loggedIn): base(msg)
{
LoggedIn = loggedIn;
}
}
class VoiceTest
{
static AutoResetEvent EventQueueRunningEvent = new AutoResetEvent(false);
static AutoResetEvent ProvisionEvent = new AutoResetEvent(false);
static AutoResetEvent ParcelVoiceInfoEvent = new AutoResetEvent(false);
static string VoiceAccount = String.Empty;
static string VoicePassword = String.Empty;
static string VoiceRegionName = String.Empty;
static int VoiceLocalID = 0;
static string VoiceChannelURI = String.Empty;
static void Main(string[] args)
{
if (args.Length < 3)
{
Console.WriteLine("Usage: VoiceTest.exe [firstname] [lastname] [password]");
return;
}
string firstName = args[0];
string lastName = args[1];
string password = args[2];
GridClient client = new GridClient();
client.Settings.MULTIPLE_SIMS = false;
Settings.LOG_LEVEL = Helpers.LogLevel.None;
client.Settings.LOG_RESENDS = false;
client.Settings.STORE_LAND_PATCHES = true;
client.Settings.ALWAYS_DECODE_OBJECTS = true;
client.Settings.ALWAYS_REQUEST_OBJECTS = true;
client.Settings.SEND_AGENT_UPDATES = true;
string loginURI = client.Settings.LOGIN_SERVER;
if (4 == args.Length) {
loginURI = args[3];
}
VoiceManager voice = new VoiceManager(client);
voice.OnProvisionAccount += voice_OnProvisionAccount;
voice.OnParcelVoiceInfo += voice_OnParcelVoiceInfo;
client.Network.OnEventQueueRunning += client_OnEventQueueRunning;
try {
if (!voice.ConnectToDaemon()) throw new VoiceException("Failed to connect to the voice daemon");
List<string> captureDevices = voice.CaptureDevices();
Console.WriteLine("Capture Devices:");
for (int i = 0; i < captureDevices.Count; i++)
Console.WriteLine(String.Format("{0}. \"{1}\"", i, captureDevices[i]));
Console.WriteLine();
List<string> renderDevices = voice.RenderDevices();
Console.WriteLine("Render Devices:");
for (int i = 0; i < renderDevices.Count; i++)
Console.WriteLine(String.Format("{0}. \"{1}\"", i, renderDevices[i]));
Console.WriteLine();
// Login
Console.WriteLine("Logging into the grid as " + firstName + " " + lastName + "...");
LoginParams loginParams =
client.Network.DefaultLoginParams(firstName, lastName, password, "Voice Test", "1.0.0");
loginParams.URI = loginURI;
if (!client.Network.Login(loginParams))
throw new VoiceException("Login to SL failed: " + client.Network.LoginMessage);
Console.WriteLine("Logged in: " + client.Network.LoginMessage);
Console.WriteLine("Creating voice connector...");
int status;
string connectorHandle = voice.CreateConnector(out status);
if (String.IsNullOrEmpty(connectorHandle))
throw new VoiceException("Failed to create a voice connector, error code: " + status, true);
Console.WriteLine("Voice connector handle: " + connectorHandle);
Console.WriteLine("Waiting for OnEventQueueRunning");
if (!EventQueueRunningEvent.WaitOne(45 * 1000, false))
throw new VoiceException("EventQueueRunning event did not occur", true);
Console.WriteLine("EventQueue running");
Console.WriteLine("Asking the current simulator to create a provisional account...");
if (!voice.RequestProvisionAccount())
throw new VoiceException("Failed to request a provisional account", true);
if (!ProvisionEvent.WaitOne(120 * 1000, false))
throw new VoiceException("Failed to create a provisional account", true);
Console.WriteLine("Provisional account created. Username: " + VoiceAccount +
", Password: " + VoicePassword);
Console.WriteLine("Logging in to voice server " + voice.VoiceServer);
string accountHandle = voice.Login(VoiceAccount, VoicePassword, connectorHandle, out status);
if (String.IsNullOrEmpty(accountHandle))
throw new VoiceException("Login failed, error code: " + status, true);
Console.WriteLine("Login succeeded, account handle: " + accountHandle);
if (!voice.RequestParcelVoiceInfo())
throw new Exception("Failed to request parcel voice info");
if (!ParcelVoiceInfoEvent.WaitOne(45 * 1000, false))
throw new VoiceException("Failed to obtain parcel info voice", true);
Console.WriteLine("Parcel Voice Info obtained. Region name {0}, local parcel ID {1}, channel URI {2}",
VoiceRegionName, VoiceLocalID, VoiceChannelURI);
client.Network.Logout();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
if (e is VoiceException && (e as VoiceException).LoggedIn)
{
client.Network.Logout();
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
static void client_OnEventQueueRunning(Simulator sim) {
EventQueueRunningEvent.Set();
}
static void client_OnLogMessage(string message, Helpers.LogLevel level)
{
if (level == Helpers.LogLevel.Warning || level == Helpers.LogLevel.Error)
Console.WriteLine(level.ToString() + ": " + message);
}
static void voice_OnProvisionAccount(string username, string password)
{
VoiceAccount = username;
VoicePassword = password;
ProvisionEvent.Set();
}
static void voice_OnParcelVoiceInfo(string regionName, int localID, string channelURI)
{
VoiceRegionName = regionName;
VoiceLocalID = localID;
VoiceChannelURI = channelURI;
ParcelVoiceInfoEvent.Set();
}
}
}

View File

@@ -0,0 +1,70 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B69597A7-5DC5-4564-9089-727D0348EB4E}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VoiceTest</RootNamespace>
<AssemblyName>VoiceTest</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-docs|AnyCPU' ">
<OutputPath>bin\Release-docs\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="VoiceTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libsecondlife\OpenMetaverse.csproj">
<Project>{D9CDEDFB-8169-4B03-B57F-0DF638F044EC}</Project>
<Name>OpenMetaverse</Name>
</ProjectReference>
<ProjectReference Include="..\libsecondlife\libsecondlife.Utilities\OpenMetaverse.Utilities.csproj">
<Project>{CE5E06C2-2428-416B-ADC1-F1FE16A0FB27}</Project>
<Name>OpenMetaverse.Utilities</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0"?>
<project name="libsecondlife" default="build">
<!-- global framework settings -->
<property name="target.framework" value="${framework::get-target-framework()}" />
<property name="assembly.dir" value="${framework::get-assembly-directory(target.framework)}" />
<!-- global project settings -->
<xmlpeek
file="../libsecondlife.build"
xpath="/project/property[@name = 'project.version']/@value"
property="project.version" />
<property name="build.number"
value="${math::abs(math::floor(timespan::get-total-days(datetime::now()
- datetime::parse('01/01/2002'))))}" />
<property name="assembly" value="importprimscript"/>
<property name="bin_dir" value="../bin" />
<!-- default configuration -->
<property name="project.config" value="debug" /> <!-- debug|release -->
<!-- named configurations -->
<target name="init" description="Initializes build properties">
<call target="${project.config}" />
</target>
<target name="debug" description="configures a debug build">
<property name="build.debug" value="true" />
<property name="package.name"
value="${project::get-name()}-${project.version}-${project.config}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()} [${project.config}]" />
</target>
<target name="release" description="configures a release build">
<property name="project.config" value="release" />
<property name="build.debug" value="false" />
<property name="package.name"
value="${project::get-name()}-${project.version}" />
<property name="assembly.configuration"
value="${framework::get-target-framework()}.${platform::get-name()}" />
</target>
<!-- build tasks -->
<target name="build"
depends="init"
description="build importprimscript">
<echo message="Build Directory is ${bin_dir}/" />
<mkdir dir="${bin_dir}" failonerror="false" />
<csc
target="exe"
debug="${build.debug}"
output="${bin_dir}/importprimscript.exe">
<sources failonempty="true">
<include name="importprimscript.cs" />
</sources>
<references basedir="${bin_dir}/">
<include name="libsecondlife.dll"/>
<include name="System.Drawing.dll"/>
</references>
</csc>
</target>
<target name="clean" depends="init"
description="Deletes the current configuration">
<delete failonerror="false">
<fileset basedir="${bin_dir}/">
<include name="importprimscript.exe" />
<include name="importprimscript.exe.mdb" />
</fileset>
</delete>
</target>
<target
name="*"
description="Handles unknown targets">
<echo message="skipping unknown target" />
</target>
</project>

View File

@@ -0,0 +1,386 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Drawing;
using OpenMetaverse;
using OpenMetaverse.Capabilities;
using OpenMetaverse.Imaging;
namespace importprimscript
{
class Sculpt
{
public string Name;
public string TextureFile;
public LLUUID TextureID;
public string SculptFile;
public LLUUID SculptID;
public LLVector3 Scale;
public LLVector3 Offset;
}
class importprimscript
{
static GridClient Client = new GridClient();
static Sculpt CurrentSculpt = null;
static AutoResetEvent RezzedEvent = new AutoResetEvent(false);
static LLVector3 RootPosition = LLVector3.Zero;
static List<uint> RezzedPrims = new List<uint>();
static LLUUID UploadFolderID = LLUUID.Zero;
static void Main(string[] args)
{
if (args.Length != 8 && args.Length != 9)
{
Console.WriteLine("Usage: importprimscript.exe [firstname] [lastname] [password] " +
"[loginuri] [Simulator] [x] [y] [z] [input.primscript]" +
Environment.NewLine + "Example: importprimscript.exe My Bot password " +
"Hooper 128 128 40 maya-export" + Path.DirectorySeparatorChar + "ant.primscript" +
Environment.NewLine + "(the loginuri is optional and only used for logging in to another grid)");
Environment.Exit(-1);
}
// Strip quotes from any arguments
for (int i = 0; i < args.Length; i++)
args[i] = args[i].Trim(new char[] { '"' });
// Parse the primscript file
string scriptfilename = args[args.Length - 1];
string error;
List<Sculpt> sculpties = ParsePrimscript(scriptfilename, out error);
scriptfilename = Path.GetFileNameWithoutExtension(scriptfilename);
// Check for parsing errors
if (error != String.Empty)
{
Console.WriteLine("An error was encountered reading the input file: " + error);
Environment.Exit(-2);
}
else if (sculpties.Count == 0)
{
Console.WriteLine("No primitives were read from the input file");
Environment.Exit(-3);
}
// Add callback handlers for asset uploads finishing. new prims spotted, and logging
Client.Objects.OnNewPrim += new ObjectManager.NewPrimCallback(Objects_OnNewPrim);
Logger.OnLogMessage += new Logger.LogCallback(Client_OnLogMessage);
// Optimize the connection for our purposes
Client.Self.Movement.Camera.Far = 64f;
Client.Settings.MULTIPLE_SIMS = false;
Client.Settings.SEND_AGENT_UPDATES = true;
Client.Settings.DISABLE_AGENT_UPDATE_DUPLICATE_CHECK = true;
Settings.LOG_LEVEL = Helpers.LogLevel.None;
Client.Settings.ALWAYS_REQUEST_OBJECTS = true;
Client.Settings.ALWAYS_DECODE_OBJECTS = true;
Client.Throttle.Land = 0;
Client.Throttle.Wind = 0;
Client.Throttle.Cloud = 0;
// Not sure if Asset or Texture will help with uploads, but it won't hurt
Client.Throttle.Asset = 220000.0f;
Client.Throttle.Texture = 446000.0f;
Client.Throttle.Task = 446000.0f;
// Create a handler for the event queue connecting, so we know when
// it is safe to start uploading
AutoResetEvent eventQueueEvent = new AutoResetEvent(false);
NetworkManager.EventQueueRunningCallback eventQueueCallback =
delegate(Simulator simulator)
{
if (simulator == Client.Network.CurrentSim)
eventQueueEvent.Set();
};
Client.Network.OnEventQueueRunning += eventQueueCallback;
int x = Int32.Parse(args[args.Length - 4]);
int y = Int32.Parse(args[args.Length - 3]);
int z = Int32.Parse(args[args.Length - 2]);
string start = NetworkManager.StartLocation(args[args.Length - 5], x, y, z);
LoginParams loginParams = Client.Network.DefaultLoginParams(args[0], args[1], args[2],
"importprimscript", "1.4.0");
loginParams.Start = start;
if (args.Length == 9) loginParams.URI = args[3];
// Attempt to login
if (!Client.Network.Login(loginParams))
{
Console.WriteLine("Login failed: " + Client.Network.LoginMessage);
Environment.Exit(-4);
}
// Need to be connected to the event queue before we can upload
Console.WriteLine("Login succeeded, waiting for the event handler to connect...");
if (!eventQueueEvent.WaitOne(1000 * 90, false))
{
Console.WriteLine("Event queue connection timed out, disconnecting...");
Client.Network.Logout();
Environment.Exit(-5);
}
// Don't need this anymore
Client.Network.OnEventQueueRunning -= eventQueueCallback;
// Set the root position for the import
RootPosition = Client.Self.SimPosition;
RootPosition.Z += 3.0f;
// TODO: Check if our account balance is high enough to upload everything
//
// Create a folder to hold all of our texture uploads
UploadFolderID = Client.Inventory.CreateFolder(Client.Inventory.Store.RootFolder.UUID, scriptfilename);
// Loop through each sculpty and do what we need to do
for (int i = 0; i < sculpties.Count; i++)
{
// Upload the sculpt map and texture
sculpties[i].SculptID = UploadImage(sculpties[i].SculptFile, true);
sculpties[i].TextureID = UploadImage(sculpties[i].TextureFile, false);
// Check for failed uploads
if (sculpties[i].SculptID == LLUUID.Zero)
{
Console.WriteLine("Sculpt map " + sculpties[i].SculptFile + " failed to upload, skipping " + sculpties[i].Name);
continue;
}
else if (sculpties[i].TextureID == LLUUID.Zero)
{
Console.WriteLine("Texture " + sculpties[i].TextureFile + " failed to upload, skipping " + sculpties[i].Name);
continue;
}
// Create basic spherical volume parameters. It will be set to
// a scultpy in the callback for new objects being created
LLObject.ObjectData volume = new LLObject.ObjectData();
volume.PCode = PCode.Prim;
volume.Material = LLObject.MaterialType.Wood;
volume.PathScaleY = 0.5f;
volume.PathCurve = LLObject.PathCurve.Circle;
volume.ProfileCurve = LLObject.ProfileCurve.Circle;
// Rez this prim
CurrentSculpt = sculpties[i];
Client.Objects.AddPrim(Client.Network.CurrentSim, volume, LLUUID.Zero,
RootPosition + CurrentSculpt.Offset, CurrentSculpt.Scale, LLQuaternion.Identity);
// Wait for the prim to rez and the properties be set for it
if (!RezzedEvent.WaitOne(1000 * 10, false))
{
Console.WriteLine("Timed out waiting for prim " + CurrentSculpt.Name + " to rez, skipping");
continue;
}
}
CurrentSculpt = null;
lock (RezzedPrims)
{
// Set full permissions for all of the objects
Client.Objects.SetPermissions(Client.Network.CurrentSim, RezzedPrims, PermissionWho.All,
PermissionMask.All, true);
// Link the entire object together
Client.Objects.LinkPrims(Client.Network.CurrentSim, RezzedPrims);
}
Console.WriteLine("Rezzed, textured, and linked " + RezzedPrims.Count + " sculpted prims, logging out...");
Client.Network.Logout();
}
static void Client_OnLogMessage(object message, Helpers.LogLevel level)
{
if (level >= Helpers.LogLevel.Warning)
Console.WriteLine(level + ": " + message);
}
static LLUUID UploadImage(string filename, bool lossless)
{
LLUUID newAssetID = LLUUID.Zero;
byte[] jp2data = null;
try
{
Bitmap image = (Bitmap)Bitmap.FromFile(filename);
jp2data = OpenJPEG.EncodeFromImage(image, lossless);
}
catch (Exception ex)
{
Console.WriteLine("Failed to encode image file " + filename + ": " + ex.ToString());
return LLUUID.Zero;
}
AutoResetEvent uploadEvent = new AutoResetEvent(false);
Client.Inventory.RequestCreateItemFromAsset(jp2data, Path.GetFileNameWithoutExtension(filename),
"Uploaded with importprimscript", AssetType.Texture, InventoryType.Texture, UploadFolderID,
delegate(CapsClient client, long bytesReceived, long bytesSent, long totalBytesToReceive, long totalBytesToSend)
{
// FIXME: Do something with progress?
},
delegate(bool success, string status, LLUUID itemID, LLUUID assetID)
{
if (success)
{
Console.WriteLine("Finished uploading image " + filename + ", AssetID: " + assetID.ToString());
newAssetID = assetID;
}
else
{
Console.WriteLine("Failed to upload image file " + filename + ": " + status);
}
uploadEvent.Set();
}
);
// The images are small, 60 seconds should be plenty
uploadEvent.WaitOne(1000 * 60, false);
return newAssetID;
}
static void Objects_OnNewPrim(Simulator simulator, Primitive prim, ulong regionHandle, ushort timeDilation)
{
if (CurrentSculpt != null && (prim.Flags & LLObject.ObjectFlags.CreateSelected) != 0 &&
!RezzedPrims.Contains(prim.LocalID))
{
lock (RezzedPrims) RezzedPrims.Add(prim.LocalID);
Console.WriteLine("Rezzed prim " + CurrentSculpt.Name + ", setting properties");
// Deselect the prim
Client.Objects.DeselectObject(Client.Network.CurrentSim, prim.LocalID);
// Set the prim position
Client.Objects.SetPosition(Client.Network.CurrentSim, prim.LocalID,
RootPosition + CurrentSculpt.Offset);
// Set the texture
LLObject.TextureEntry textures = new LLObject.TextureEntry(CurrentSculpt.TextureID);
Client.Objects.SetTextures(Client.Network.CurrentSim, prim.LocalID, textures);
// Turn it in to a sculpted prim
Primitive.SculptData sculpt = new Primitive.SculptData();
sculpt.SculptTexture = CurrentSculpt.SculptID;
sculpt.Type = Primitive.SculptType.Sphere;
Client.Objects.SetSculpt(Client.Network.CurrentSim, prim.LocalID, sculpt);
// Set the prim name
if (!String.IsNullOrEmpty(CurrentSculpt.Name))
Client.Objects.SetName(Client.Network.CurrentSim, prim.LocalID, CurrentSculpt.Name);
RezzedEvent.Set();
}
}
static List<Sculpt> ParsePrimscript(string primscriptfile, out string error)
{
string line;
Sculpt current = null;
List<Sculpt> sculpties = new List<Sculpt>();
error = String.Empty;
StreamReader primscript = null;
// Parse a directory out of the primscriptfile string, if one exists
string path = Path.GetDirectoryName(primscriptfile);
if (!String.IsNullOrEmpty(path))
path += Path.DirectorySeparatorChar;
else
path = String.Empty;
try
{
primscript = File.OpenText(primscriptfile);
while ((line = primscript.ReadLine()) != null)
{
string[] words = line.Split(new char[] { ' ' });
if (words.Length > 0)
{
if (current != null)
{
switch (words[0])
{
case "newPrim":
if (current.Scale != LLVector3.Zero &&
!String.IsNullOrEmpty(current.SculptFile) &&
!String.IsNullOrEmpty(current.TextureFile))
{
// Add the previous prim to the list as it is now finalized
sculpties.Add(current);
}
// Start a new prim
current = new Sculpt();
break;
case "prim":
// The only useful bit of information here is the prim name
if (words.Length >= 3)
current.Name = words[2];
break;
case "shape":
// This line has the name of the sculpt texture
if (words.Length >= 3)
current.SculptFile = path + words[2] + ".bmp";
break;
case "texture":
// This line has the name of the actual texture
if (words.Length >= 3)
current.TextureFile = path + words[2] + ".bmp";
break;
case "transform":
// Get some primitive params
if (words.Length >= 9)
{
float x, y, z;
x = Single.Parse(words[2]);
y = Single.Parse(words[3]);
z = Single.Parse(words[4]);
current.Scale = new LLVector3(x, y, z);
x = Single.Parse(words[6]);
y = Single.Parse(words[7]);
z = Single.Parse(words[8]);
current.Offset = new LLVector3(x, y, z);
}
break;
}
}
else if (words[0] == "newPrim")
{
// Start a new prim
current = new Sculpt();
}
}
}
// Add the final prim
if (current != null && current.Scale != LLVector3.Zero &&
!String.IsNullOrEmpty(current.SculptFile) &&
!String.IsNullOrEmpty(current.TextureFile))
{
// Add the previous prim to the list as it is now finalized
sculpties.Add(current);
}
}
catch (Exception ex)
{
error = ex.ToString();
}
finally
{
if (primscript != null)
primscript.Close();
}
return sculpties;
}
}
}

View File

@@ -0,0 +1,67 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{32A7AA59-5129-4446-A6DC-2F581ED1A25C}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>importprimscript</RootNamespace>
<AssemblyName>importprimscript</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-docs|AnyCPU' ">
<OutputPath>bin\Release-docs\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="importprimscript.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libsecondlife\OpenMetaverse.csproj">
<Project>{D9CDEDFB-8169-4B03-B57F-0DF638F044EC}</Project>
<Name>OpenMetaverse</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>