DO NOT DOWNLOAD. DOWNLOAT LATEST STABLE FROM RELEASE TAB
Created 4.1.0 branch [TFS Changeset #55082]
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* $Id: ConfigSection.cs 439 2007-11-26 13:26:10Z spocke $
|
||||
*
|
||||
* @author Moxiecode
|
||||
* @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ConfigSection.
|
||||
/// </summary>
|
||||
public class ConfigSection {
|
||||
#region private
|
||||
private NameValueCollection globalSettings;
|
||||
private bool gzipEnabled, gzipDiskCache, gzipNoCompression;
|
||||
private string installPath, mode, gzipCachePath;
|
||||
private long gzipExpiresOffset;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public ConfigSection() {
|
||||
this.globalSettings = new NameValueCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string InstallPath {
|
||||
get { return installPath; }
|
||||
set { installPath = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Mode {
|
||||
get { return mode; }
|
||||
set { mode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public NameValueCollection GlobalSettings {
|
||||
get { return globalSettings; }
|
||||
set { globalSettings = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool GzipEnabled {
|
||||
get { return gzipEnabled; }
|
||||
set { gzipEnabled = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public long GzipExpiresOffset {
|
||||
get { return gzipExpiresOffset; }
|
||||
set { gzipExpiresOffset = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool GzipDiskCache {
|
||||
get { return gzipDiskCache; }
|
||||
set { gzipDiskCache = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string GzipCachePath {
|
||||
get { return gzipCachePath; }
|
||||
set { gzipCachePath = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool GzipNoCompression {
|
||||
get { return gzipNoCompression; }
|
||||
set { gzipNoCompression = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* $Id: GzipCompressor.cs 439 2007-11-26 13:26:10Z spocke $
|
||||
*
|
||||
* @author Moxiecode
|
||||
* @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of GzipCompressor.
|
||||
/// </summary>
|
||||
public class GzipCompressor {
|
||||
#region private
|
||||
private bool diskCache, noCompression;
|
||||
private string cachePath;
|
||||
private ArrayList items;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public GzipCompressor() {
|
||||
this.items = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool NoCompression {
|
||||
get { return noCompression; }
|
||||
set { noCompression = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DiskCache {
|
||||
get { return diskCache; }
|
||||
set { diskCache = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string CachePath {
|
||||
get { return cachePath; }
|
||||
set { cachePath = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
public void AddFile(string path) {
|
||||
//System.Web.HttpContext.Current.Response.Write(path + "\n");
|
||||
if (File.Exists(path))
|
||||
this.items.Add(new CompressItem(CompressItemType.File, path));
|
||||
else
|
||||
throw new Exception("File could not be found \"" + path + "\", unable to add it for Gzip compression.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public void AddData(string data) {
|
||||
this.items.Add(new CompressItem(CompressItemType.Chunk, data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="to_stream"></param>
|
||||
public void Compress(Stream to_stream) {
|
||||
GZipStream gzipStream = null;
|
||||
string key = "";
|
||||
byte[] bytes;
|
||||
|
||||
// Build cache key
|
||||
foreach (CompressItem item in this.items) {
|
||||
if (item.Type == CompressItemType.File)
|
||||
key += item.Data;
|
||||
}
|
||||
|
||||
key = MD5(key);
|
||||
if (this.NoCompression) {
|
||||
this.SendPlainText(key, to_stream);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for cached file on disk, stream that one if it was found
|
||||
if (this.DiskCache && File.Exists(Path.Combine(this.CachePath, key + ".gz"))) {
|
||||
this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".gz")), to_stream, 4096, CloseMode.InStream);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Build new gzipped stream
|
||||
if (this.DiskCache) {
|
||||
gzipStream = new GZipStream(File.OpenWrite(Path.Combine(this.CachePath, key + ".gz")), CompressionMode.Compress);
|
||||
|
||||
// Compress all files into memory
|
||||
foreach (CompressItem item in this.items) {
|
||||
// Add file
|
||||
if (item.Type == CompressItemType.File)
|
||||
StreamFromTo(File.OpenRead(item.Data), gzipStream, 4096, CloseMode.InStream);
|
||||
|
||||
// Add chunk
|
||||
if (item.Type == CompressItemType.Chunk) {
|
||||
bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray());
|
||||
gzipStream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
|
||||
// Close gzip stream
|
||||
gzipStream.Close();
|
||||
gzipStream = null;
|
||||
|
||||
// Send cached file to user
|
||||
this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".gz")), to_stream, 4096, CloseMode.InStream);
|
||||
} else {
|
||||
gzipStream = new GZipStream(to_stream, CompressionMode.Compress);
|
||||
|
||||
// Compress all files into output stream
|
||||
foreach (CompressItem item in this.items) {
|
||||
// Add file
|
||||
if (item.Type == CompressItemType.File)
|
||||
StreamFromTo(File.OpenRead(item.Data), gzipStream, 4096, CloseMode.InStream);
|
||||
|
||||
// Add chunk
|
||||
if (item.Type == CompressItemType.Chunk) {
|
||||
bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray());
|
||||
gzipStream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (gzipStream != null)
|
||||
gzipStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
#region private
|
||||
|
||||
private void SendPlainText(string key, Stream to_stream) {
|
||||
Stream fileStream = null;
|
||||
byte[] bytes;
|
||||
|
||||
// Check for cached file on disk, stream that one if it was found
|
||||
if (this.DiskCache && File.Exists(Path.Combine(this.CachePath, key + ".js"))) {
|
||||
this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".js")), to_stream, 4096, CloseMode.InStream);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build new plain text stream
|
||||
if (this.DiskCache) {
|
||||
try {
|
||||
fileStream = File.OpenWrite(Path.Combine(this.CachePath, key + ".js"));
|
||||
|
||||
// Compress all files into memory
|
||||
foreach (CompressItem item in this.items) {
|
||||
// Add file
|
||||
if (item.Type == CompressItemType.File)
|
||||
StreamFromTo(File.OpenRead(item.Data), fileStream, 4096, CloseMode.InStream);
|
||||
|
||||
// Add chunk
|
||||
if (item.Type == CompressItemType.Chunk) {
|
||||
bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray());
|
||||
fileStream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
|
||||
// Close file stream
|
||||
fileStream.Close();
|
||||
fileStream = null;
|
||||
} finally {
|
||||
// Close file stream
|
||||
if (fileStream != null)
|
||||
fileStream.Close();
|
||||
}
|
||||
|
||||
// Send cached file to user
|
||||
this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".js")), to_stream, 4096, CloseMode.InStream);
|
||||
} else {
|
||||
// Concat all files into output stream
|
||||
foreach (CompressItem item in this.items) {
|
||||
// Add file
|
||||
if (item.Type == CompressItemType.File)
|
||||
StreamFromTo(File.OpenRead(item.Data), to_stream, 4096, CloseMode.InStream);
|
||||
|
||||
// Add chunk
|
||||
if (item.Type == CompressItemType.Chunk) {
|
||||
bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray());
|
||||
to_stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StreamFromTo(Stream in_stream, Stream out_stream, int buff_size, CloseMode mode) {
|
||||
byte[] buff = new byte[buff_size];
|
||||
int len;
|
||||
|
||||
try {
|
||||
while ((len = in_stream.Read(buff, 0, buff_size)) > 0) {
|
||||
out_stream.Write(buff, 0, len);
|
||||
out_stream.Flush();
|
||||
}
|
||||
} finally {
|
||||
if (in_stream != null && (mode == CloseMode.Both || mode == CloseMode.InStream))
|
||||
in_stream.Close();
|
||||
|
||||
if (out_stream != null && (mode == CloseMode.Both || mode == CloseMode.OutStream))
|
||||
out_stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private string MD5(string str) {
|
||||
MD5 md5 = new MD5CryptoServiceProvider();
|
||||
byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(str));
|
||||
str = BitConverter.ToString(result);
|
||||
|
||||
return str.Replace("-", "");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
enum CloseMode {
|
||||
None, InStream, OutStream, Both
|
||||
}
|
||||
|
||||
enum CompressItemType {
|
||||
File, Chunk
|
||||
}
|
||||
|
||||
class CompressItem {
|
||||
private string data;
|
||||
private CompressItemType type;
|
||||
|
||||
public CompressItem(CompressItemType type, string data) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public string Data {
|
||||
get { return data; }
|
||||
set { data = value; }
|
||||
}
|
||||
|
||||
public CompressItemType Type {
|
||||
get { return type; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* $Id: GzipModule.cs 439 2007-11-26 13:26:10Z spocke $
|
||||
*
|
||||
* @author Moxiecode
|
||||
* @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of HttpHandler.
|
||||
/// </summary>
|
||||
public class GzipModule : IModule {
|
||||
/// <summary></summary>
|
||||
/// <param name="context">Request context.</param>
|
||||
public void ProcessRequest(HttpContext context) {
|
||||
HttpRequest request = context.Request;
|
||||
HttpResponse response = context.Response;
|
||||
HttpServerUtility server = context.Server;
|
||||
GzipCompressor gzipCompressor = new GzipCompressor();
|
||||
ConfigSection configSection = (ConfigSection) System.Web.HttpContext.Current.GetSection("TinyMCE");
|
||||
string suffix = "", enc;
|
||||
string[] languages = request.QueryString["languages"].Split(',');
|
||||
bool supportsGzip;
|
||||
|
||||
// Set response headers
|
||||
response.ContentType = "text/javascript";
|
||||
response.Charset = "UTF-8";
|
||||
response.Buffer = false;
|
||||
|
||||
// UMBRACO: Populate the configsection if it's empty
|
||||
if (configSection == null)
|
||||
{
|
||||
configSection = new ConfigSection();
|
||||
configSection.GzipEnabled = true;
|
||||
configSection.InstallPath = umbraco.editorControls.tinymce.tinyMCEConfiguration.JavascriptPath;
|
||||
configSection.GzipExpiresOffset = TimeSpan.FromDays(10).Ticks;
|
||||
}
|
||||
|
||||
// Setup cache
|
||||
response.Cache.SetExpires(DateTime.Now.AddTicks(configSection.GzipExpiresOffset));
|
||||
response.Cache.SetCacheability(HttpCacheability.Public);
|
||||
response.Cache.SetValidUntilExpires(false);
|
||||
|
||||
// Check if it supports gzip
|
||||
enc = Regex.Replace("" + request.Headers["Accept-Encoding"], @"\s+", "").ToLower();
|
||||
supportsGzip = enc.IndexOf("gzip") != -1 || request.Headers["---------------"] != null;
|
||||
enc = enc.IndexOf("x-gzip") != -1 ? "x-gzip" : "gzip";
|
||||
|
||||
// Handle mode/suffix
|
||||
if (configSection.Mode != null)
|
||||
suffix = "_" + configSection.Mode;
|
||||
|
||||
gzipCompressor.AddData("var tinyMCEPreInit = {base : '" + new Uri(request.Url, configSection.InstallPath).ToString() + "', suffix : '" + suffix + "'};");
|
||||
|
||||
// Add core
|
||||
gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/tiny_mce" + suffix + ".js"));
|
||||
|
||||
// Add core languages
|
||||
foreach (string lang in languages)
|
||||
gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/langs/" + lang + ".js"));
|
||||
|
||||
// Add themes
|
||||
if (request.QueryString["themes"] != null) {
|
||||
foreach (string theme in request.QueryString["themes"].Split(',')) {
|
||||
gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/themes/" + theme + "/editor_template" + suffix + ".js"));
|
||||
|
||||
// Add theme languages
|
||||
foreach (string lang in languages) {
|
||||
string path = server.MapPath(configSection.InstallPath + "/themes/" + theme + "/langs/" + lang + ".js");
|
||||
|
||||
if (File.Exists(path))
|
||||
gzipCompressor.AddFile(path);
|
||||
}
|
||||
|
||||
gzipCompressor.AddData("tinymce.ThemeManager.urls['" + theme + "'] = tinymce.baseURL+'/themes/" + theme + "';");
|
||||
}
|
||||
}
|
||||
|
||||
// Add plugins
|
||||
if (request.QueryString["plugins"] != null) {
|
||||
foreach (string plugin in request.QueryString["plugins"].Split(',')) {
|
||||
gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/plugins/" + plugin + "/editor_plugin" + suffix + ".js"));
|
||||
|
||||
// Add plugin languages
|
||||
foreach (string lang in languages) {
|
||||
string path = server.MapPath(configSection.InstallPath + "/plugins/" + plugin + "/langs/" + lang + ".js");
|
||||
|
||||
if (File.Exists(path))
|
||||
gzipCompressor.AddFile(path);
|
||||
}
|
||||
|
||||
gzipCompressor.AddData("tinymce.ThemeManager.urls['" + plugin + "'] = tinymce.baseURL+'/plugins/" + plugin + "';");
|
||||
}
|
||||
}
|
||||
|
||||
// Output compressed file
|
||||
gzipCompressor.NoCompression = !supportsGzip || configSection.GzipNoCompression;
|
||||
if (!gzipCompressor.NoCompression)
|
||||
response.AppendHeader("Content-Encoding", enc);
|
||||
|
||||
gzipCompressor.DiskCache = configSection.GzipDiskCache;
|
||||
gzipCompressor.CachePath = configSection.GzipCachePath;
|
||||
|
||||
gzipCompressor.Compress(response.OutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Created by SharpDevelop.
|
||||
* User: spocke
|
||||
* Date: 2007-11-22
|
||||
* Time: 14:32
|
||||
*
|
||||
* To change this template use Tools | Options | Coding | Edit Standard Headers.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin {
|
||||
/// <summary>
|
||||
/// Description of IAction.
|
||||
/// </summary>
|
||||
public interface IModule {
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
void ProcessRequest(HttpContext context);
|
||||
}
|
||||
}
|
||||
352
components/editorControls/tinyMCE3/webcontrol/plugin/JSON.cs
Normal file
352
components/editorControls/tinyMCE3/webcontrol/plugin/JSON.cs
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* $Id: JSON.cs 439 2007-11-26 13:26:10Z spocke $
|
||||
*
|
||||
* Copyright © 2007, Moxiecode Systems AB, All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of JSON.
|
||||
/// </summary>
|
||||
public class JSON {
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static void SerializeRPC(string id, object error, object obj, Stream stream) {
|
||||
JSONWriter writer = new JSONWriter(new StreamWriter(stream));
|
||||
|
||||
// Start JSON output
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName("result");
|
||||
WriteValue(writer, obj);
|
||||
|
||||
// Write id
|
||||
writer.WritePropertyName("id");
|
||||
writer.WriteValue(id);
|
||||
|
||||
// Write error
|
||||
writer.WritePropertyName("error");
|
||||
writer.WriteValue(null);
|
||||
|
||||
// Close
|
||||
writer.WriteEndObject();
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="obj"></param>
|
||||
public static void WriteObject(TextWriter writer, object obj) {
|
||||
WriteValue(new JSONWriter(writer), obj);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
private static void WriteValue(JSONWriter writer, object obj) {
|
||||
if (obj == null)
|
||||
writer.WriteNull();
|
||||
|
||||
if (obj is System.String)
|
||||
writer.WriteValue((string) obj);
|
||||
|
||||
if (obj is System.Boolean)
|
||||
writer.WriteValue((bool) obj);
|
||||
|
||||
if (obj is System.Double)
|
||||
writer.WriteValue(Convert.ToDouble(obj));
|
||||
|
||||
if (obj is System.Int32)
|
||||
writer.WriteValue(Convert.ToInt32(obj));
|
||||
|
||||
if (obj is System.Int64)
|
||||
writer.WriteValue(Convert.ToInt64(obj));
|
||||
|
||||
if (obj is ArrayList) {
|
||||
writer.WriteStartArray();
|
||||
|
||||
foreach (object val in ((ArrayList) obj))
|
||||
WriteValue(writer, val);
|
||||
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
if (obj is string[]) {
|
||||
writer.WriteStartArray();
|
||||
|
||||
foreach (string val in ((string[]) obj))
|
||||
WriteValue(writer, val);
|
||||
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
if (obj is NameValueCollection) {
|
||||
writer.WriteStartObject();
|
||||
|
||||
string[] keys = GetReversedKeys(obj);
|
||||
foreach (string key in keys) {
|
||||
writer.WritePropertyName(key);
|
||||
WriteValue(writer, ((NameValueCollection) obj)[key]);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
if (obj is Hashtable) {
|
||||
writer.WriteStartObject();
|
||||
|
||||
string[] keys = GetReversedKeys(obj);
|
||||
foreach (string key in keys) {
|
||||
writer.WritePropertyName((string) key);
|
||||
WriteValue(writer, ((Hashtable) obj)[key]);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] GetReversedKeys(object obj) {
|
||||
ICollection keyCollection;
|
||||
string[] keys;
|
||||
int count;
|
||||
|
||||
if (obj is Hashtable)
|
||||
keyCollection = ((Hashtable) obj).Keys;
|
||||
else
|
||||
keyCollection = ((NameValueCollection) obj).AllKeys;
|
||||
|
||||
count = keyCollection.Count;
|
||||
keys = new string[count];
|
||||
|
||||
foreach (string key in keyCollection)
|
||||
keys[--count] = key;
|
||||
|
||||
Array.Sort(keys);
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <returns></returns>
|
||||
public static object ParseJSON(TextReader reader) {
|
||||
return ReadValue(new JSONReader(reader));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <returns></returns>
|
||||
public static JSONRpcCall ParseRPC(TextReader reader) {
|
||||
JSONRpcCall call = new JSONRpcCall();
|
||||
object obj = ParseJSON(reader);
|
||||
Hashtable jsonRpc = (Hashtable) obj;
|
||||
|
||||
call.Method = (string) jsonRpc["method"];
|
||||
call.Id = (string) jsonRpc["id"];
|
||||
call.Args = (ArrayList) jsonRpc["params"];
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
#region private methods
|
||||
|
||||
/* private static void Debug(string str) {
|
||||
System.Web.HttpContext.Current.Trace.Write(str);
|
||||
}*/
|
||||
|
||||
private static object ReadValue(JSONReader reader) {
|
||||
Stack parents = new Stack();
|
||||
object cur = null;
|
||||
string key = null;
|
||||
object obj;
|
||||
|
||||
while (reader.Read()) {
|
||||
//Debug(reader.ToString());
|
||||
|
||||
switch (reader.TokenType) {
|
||||
case JSONToken.Boolean:
|
||||
case JSONToken.Integer:
|
||||
case JSONToken.String:
|
||||
case JSONToken.Float:
|
||||
case JSONToken.Null:
|
||||
if (cur is Hashtable) {
|
||||
//Debug(key + "=" + reader.ToString());
|
||||
((Hashtable) cur)[key] = reader.Value;
|
||||
} else if (cur is ArrayList)
|
||||
((ArrayList) cur).Add(reader.Value);
|
||||
else
|
||||
return reader.Value;
|
||||
|
||||
break;
|
||||
|
||||
case JSONToken.PropertyName:
|
||||
key = (string) reader.Value;
|
||||
break;
|
||||
|
||||
case JSONToken.StartArray:
|
||||
case JSONToken.StartObject:
|
||||
if (reader.TokenType == JSONToken.StartObject)
|
||||
obj = new Hashtable();
|
||||
else
|
||||
obj = new ArrayList();
|
||||
|
||||
if (cur is Hashtable) {
|
||||
//Debug(key + "=" + reader.ToString());
|
||||
((Hashtable) cur)[key] = obj;
|
||||
} else if (cur is ArrayList)
|
||||
((ArrayList) cur).Add(obj);
|
||||
|
||||
parents.Push(cur);
|
||||
cur = obj;
|
||||
|
||||
break;
|
||||
|
||||
case JSONToken.EndArray:
|
||||
case JSONToken.EndObject:
|
||||
obj = parents.Pop();
|
||||
|
||||
if (obj != null)
|
||||
cur = obj;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
private static object ReadValue2(JSONReader jsonReader) {
|
||||
jsonReader.Read();
|
||||
|
||||
switch (jsonReader.TokenType) {
|
||||
case JSONToken.Boolean:
|
||||
return (bool) jsonReader.Value;
|
||||
|
||||
case JSONToken.Integer:
|
||||
return Convert.ToInt32(jsonReader.Value);
|
||||
|
||||
case JSONToken.String:
|
||||
return (string) jsonReader.Value;
|
||||
|
||||
case JSONToken.Float:
|
||||
return (double) jsonReader.Value;
|
||||
|
||||
case JSONToken.Null:
|
||||
return null;
|
||||
|
||||
case JSONToken.StartObject:
|
||||
Hashtable hash = new Hashtable();
|
||||
|
||||
while (jsonReader.TokenType != JSONToken.EndObject) {
|
||||
if (jsonReader.TokenType == JSONToken.PropertyName)
|
||||
hash[jsonReader.Value] = ReadValue(jsonReader);
|
||||
else
|
||||
jsonReader.Read();
|
||||
}
|
||||
|
||||
return hash;
|
||||
|
||||
case JSONToken.StartArray:
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
while (jsonReader.TokenType != JSONToken.EndArray) {
|
||||
if (jsonReader.TokenType == JSONToken.EndArray && jsonReader.Value == null)
|
||||
break;
|
||||
|
||||
list.Add(ReadValue(jsonReader));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool FindNext(JSONReader reader, JSONToken token) {
|
||||
if (reader.TokenType == token)
|
||||
return true;
|
||||
|
||||
while (reader.Read() && reader.TokenType != JSONToken.EndObject && reader.TokenType != JSONToken.EndArray) {
|
||||
if (reader.TokenType == token)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool FindNextValue(JSONReader reader) {
|
||||
switch (reader.TokenType) {
|
||||
case JSONToken.Boolean:
|
||||
case JSONToken.Float:
|
||||
case JSONToken.Integer:
|
||||
case JSONToken.Null:
|
||||
case JSONToken.String:
|
||||
return true;
|
||||
}
|
||||
|
||||
while (reader.Read() && reader.TokenType != JSONToken.EndObject) {
|
||||
switch (reader.TokenType) {
|
||||
case JSONToken.Boolean:
|
||||
case JSONToken.Float:
|
||||
case JSONToken.Integer:
|
||||
case JSONToken.Null:
|
||||
case JSONToken.String:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class JSONRpcCall {
|
||||
private string id, method;
|
||||
private ArrayList args;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public JSONRpcCall() {
|
||||
this.args = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Method {
|
||||
get { return method; }
|
||||
set { method = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Id {
|
||||
get { return id; }
|
||||
set { id = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public ArrayList Args {
|
||||
get { return args; }
|
||||
set { args = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* $Id: JSONReader.cs 439 2007-11-26 13:26:10Z spocke $
|
||||
*
|
||||
* Copyright © 2007, Moxiecode Systems AB, All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum JSONToken {
|
||||
/// <summary> </summary>
|
||||
Boolean,
|
||||
|
||||
/// <summary> </summary>
|
||||
Integer,
|
||||
|
||||
/// <summary> </summary>
|
||||
String,
|
||||
|
||||
/// <summary> </summary>
|
||||
Null,
|
||||
|
||||
/// <summary> </summary>
|
||||
Float,
|
||||
|
||||
/// <summary> </summary>
|
||||
StartArray,
|
||||
|
||||
/// <summary> </summary>
|
||||
EndArray,
|
||||
|
||||
/// <summary> </summary>
|
||||
PropertyName,
|
||||
|
||||
/// <summary> </summary>
|
||||
StartObject,
|
||||
|
||||
/// <summary> </summary>
|
||||
EndObject
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Description of JSONReader.
|
||||
/// </summary>
|
||||
public class JSONReader {
|
||||
private TextReader reader;
|
||||
private JSONToken token;
|
||||
private object val;
|
||||
private JSONLocation location;
|
||||
private Stack lastLocations;
|
||||
private bool needProp;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
public JSONReader(TextReader reader) {
|
||||
this.reader = reader;
|
||||
this.val = null;
|
||||
this.token = JSONToken.Null;
|
||||
this.location = JSONLocation.Normal;
|
||||
this.lastLocations = new Stack();
|
||||
this.needProp = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public JSONLocation Location {
|
||||
get { return location; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public JSONToken TokenType {
|
||||
get {
|
||||
return this.token;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public object Value {
|
||||
get {
|
||||
return this.val;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Read() {
|
||||
int chr = this.reader.Read();
|
||||
|
||||
if (chr != -1) {
|
||||
switch ((char) chr) {
|
||||
case '[':
|
||||
this.lastLocations.Push(this.location);
|
||||
this.location = JSONLocation.InArray;
|
||||
this.token = JSONToken.StartArray;
|
||||
this.val = null;
|
||||
this.ReadAway();
|
||||
return true;
|
||||
|
||||
case ']':
|
||||
this.location = (JSONLocation) this.lastLocations.Pop();
|
||||
this.token = JSONToken.EndArray;
|
||||
this.val = null;
|
||||
this.ReadAway();
|
||||
|
||||
if (this.location == JSONLocation.InObject)
|
||||
this.needProp = true;
|
||||
|
||||
return true;
|
||||
|
||||
case '{':
|
||||
this.lastLocations.Push(this.location);
|
||||
this.location = JSONLocation.InObject;
|
||||
this.needProp = true;
|
||||
this.token = JSONToken.StartObject;
|
||||
this.val = null;
|
||||
this.ReadAway();
|
||||
return true;
|
||||
|
||||
case '}':
|
||||
this.location = (JSONLocation) this.lastLocations.Pop();
|
||||
this.token = JSONToken.EndObject;
|
||||
this.val = null;
|
||||
this.ReadAway();
|
||||
|
||||
if (this.location == JSONLocation.InObject)
|
||||
this.needProp = true;
|
||||
|
||||
return true;
|
||||
|
||||
// String
|
||||
case '"':
|
||||
case '\'':
|
||||
return this.ReadString((char) chr);
|
||||
|
||||
// Null
|
||||
case 'n':
|
||||
return this.ReadNull();
|
||||
|
||||
// Bool
|
||||
case 't':
|
||||
case 'f':
|
||||
return this.ReadBool((char) chr);
|
||||
|
||||
default:
|
||||
// Is number
|
||||
if (Char.IsNumber((char) chr) || (char) chr == '-' || (char) chr == '.')
|
||||
return this.ReadNumber((char) chr);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString() {
|
||||
switch (this.token) {
|
||||
case JSONToken.Boolean:
|
||||
return "[Boolean] = " + ((bool) this.Value ? "true" : "false");
|
||||
|
||||
case JSONToken.EndArray:
|
||||
return "[EndArray]";
|
||||
|
||||
case JSONToken.EndObject:
|
||||
return "[EndObject]";
|
||||
|
||||
case JSONToken.Float:
|
||||
return "[Float] = " + Convert.ToDouble(this.Value);
|
||||
|
||||
case JSONToken.Integer:
|
||||
return "[Integer] = " + ((int) this.Value);
|
||||
|
||||
case JSONToken.Null:
|
||||
return "[Null]";
|
||||
|
||||
case JSONToken.StartArray:
|
||||
return "[StartArray]";
|
||||
|
||||
case JSONToken.StartObject:
|
||||
return "[StartObject]";
|
||||
|
||||
case JSONToken.String:
|
||||
return "[String]" + (string) this.Value;
|
||||
|
||||
case JSONToken.PropertyName:
|
||||
return "[PropertyName]" + (string) this.Value;
|
||||
}
|
||||
|
||||
return base.ToString();
|
||||
}
|
||||
|
||||
#region private methods
|
||||
|
||||
private bool ReadString(char quote) {
|
||||
StringBuilder buff = new StringBuilder();
|
||||
this.token = JSONToken.String;
|
||||
bool endString = false;
|
||||
int chr;
|
||||
|
||||
while ((chr = this.reader.Peek()) != -1) {
|
||||
switch (chr) {
|
||||
case '\\':
|
||||
// Read away slash
|
||||
chr = this.reader.Read();
|
||||
|
||||
// Read escape code
|
||||
chr = this.reader.Read();
|
||||
switch (chr) {
|
||||
case 't':
|
||||
buff.Append('\t');
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
buff.Append('\b');
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
buff.Append('\f');
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
buff.Append('\r');
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
buff.Append('\n');
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
buff.Append((char) Convert.ToInt32(ReadLen(4), 16));
|
||||
break;
|
||||
|
||||
default:
|
||||
buff.Append((char) chr);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '"':
|
||||
if (chr == quote)
|
||||
endString = true;
|
||||
|
||||
chr = this.reader.Read();
|
||||
if (chr != -1 && chr != quote)
|
||||
buff.Append((char) chr);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
buff.Append((char) this.reader.Read());
|
||||
break;
|
||||
}
|
||||
|
||||
// String terminated
|
||||
if (endString)
|
||||
break;
|
||||
}
|
||||
|
||||
this.ReadAway();
|
||||
|
||||
this.val = buff.ToString();
|
||||
|
||||
// Needed a property
|
||||
if (this.needProp) {
|
||||
this.token = JSONToken.PropertyName;
|
||||
this.needProp = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.location == JSONLocation.InObject && !this.needProp)
|
||||
this.needProp = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ReadNull() {
|
||||
this.token = JSONToken.Null;
|
||||
this.val = null;
|
||||
|
||||
this.ReadAway(3); // ull
|
||||
this.ReadAway();
|
||||
|
||||
if (this.location == JSONLocation.InObject && !this.needProp)
|
||||
this.needProp = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ReadNumber(char start) {
|
||||
StringBuilder buff = new StringBuilder();
|
||||
int chr;
|
||||
bool isFloat = false;
|
||||
|
||||
this.token = JSONToken.Integer;
|
||||
buff.Append(start);
|
||||
|
||||
while ((chr = this.reader.Peek()) != -1) {
|
||||
if (Char.IsNumber((char) chr) || (char) chr == '-' || (char) chr == '.') {
|
||||
if (((char) chr) == '.')
|
||||
isFloat = true;
|
||||
|
||||
buff.Append((char) this.reader.Read());
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
this.ReadAway();
|
||||
|
||||
if (isFloat) {
|
||||
this.token = JSONToken.Float;
|
||||
this.val = Convert.ToDouble(buff.ToString().Replace('.', ','));
|
||||
} else
|
||||
this.val = Convert.ToInt32(buff.ToString());
|
||||
|
||||
if (this.location == JSONLocation.InObject && !this.needProp)
|
||||
this.needProp = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ReadBool(char chr) {
|
||||
this.token = JSONToken.Boolean;
|
||||
this.val = chr == 't';
|
||||
|
||||
if (chr == 't')
|
||||
this.ReadAway(3); // rue
|
||||
else
|
||||
this.ReadAway(4); // alse
|
||||
|
||||
this.ReadAway();
|
||||
|
||||
if (this.location == JSONLocation.InObject && !this.needProp)
|
||||
this.needProp = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ReadAway() {
|
||||
int chr;
|
||||
|
||||
while ((chr = this.reader.Peek()) != -1) {
|
||||
if (chr != ':' && chr != ',' && !Char.IsWhiteSpace((char) chr))
|
||||
break;
|
||||
|
||||
this.reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
private string ReadLen(int num) {
|
||||
StringBuilder buff = new StringBuilder();
|
||||
int chr;
|
||||
|
||||
for (int i=0; i<num && (chr = this.reader.Read()) != -1; i++)
|
||||
buff.Append((char) chr);
|
||||
|
||||
return buff.ToString();
|
||||
}
|
||||
|
||||
private void ReadAway(int num) {
|
||||
for (int i=0; i<num && this.reader.Read() != -1; i++) ;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* $Id: JSONWriter.cs 439 2007-11-26 13:26:10Z spocke $
|
||||
*
|
||||
* Copyright © 2007, Moxiecode Systems AB, All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
|
||||
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum JSONLocation {
|
||||
/// <summary> </summary>
|
||||
InArray,
|
||||
|
||||
/// <summary> </summary>
|
||||
InObject,
|
||||
|
||||
/// <summary> </summary>
|
||||
Normal
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Description of JSONWriter.
|
||||
/// </summary>
|
||||
public class JSONWriter {
|
||||
private TextWriter writer;
|
||||
private JSONLocation location;
|
||||
private Stack lastLocations;
|
||||
private int index, lastIndex;
|
||||
private bool isProp = false;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
public JSONWriter(TextWriter writer) {
|
||||
this.writer = writer;
|
||||
this.location = JSONLocation.Normal;
|
||||
this.lastLocations = new Stack();
|
||||
this.index = 0;
|
||||
this.lastIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void WriteStartObject() {
|
||||
this.WriteDelim();
|
||||
this.writer.Write('{');
|
||||
this.lastLocations.Push(this.location);
|
||||
this.lastIndex = this.index;
|
||||
this.location = JSONLocation.InObject;
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void WriteEndObject() {
|
||||
this.writer.Write('}');
|
||||
this.location = (JSONLocation) lastLocations.Pop();
|
||||
this.index = this.lastIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void WriteStartArray() {
|
||||
this.WriteDelim();
|
||||
this.writer.Write('[');
|
||||
this.lastLocations.Push(this.location);
|
||||
this.lastIndex = this.index;
|
||||
this.location = JSONLocation.InArray;
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void WriteEndArray() {
|
||||
this.writer.Write(']');
|
||||
this.location = (JSONLocation) lastLocations.Pop();
|
||||
this.index = this.lastIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void WritePropertyName(string name) {
|
||||
this.WriteDelim();
|
||||
this.isProp = true;
|
||||
this.WriteObject(EncodeString(name));
|
||||
this.writer.Write(':');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="obj"></param>
|
||||
public void WriteProperty(string name, object obj) {
|
||||
this.WritePropertyName(name);
|
||||
this.WriteObject(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public void WriteValue(object obj) {
|
||||
this.WriteDelim();
|
||||
this.WriteObject(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void WriteNull() {
|
||||
this.WriteDelim();
|
||||
this.writer.Write("null");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Close() {
|
||||
this.writer.Close();
|
||||
}
|
||||
|
||||
#region private methods
|
||||
|
||||
private void WriteObject(object obj) {
|
||||
if (obj == null) {
|
||||
this.writer.Write("null");
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is bool) {
|
||||
this.writer.Write(((bool) obj) == true ? "true" : "false");
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is int) {
|
||||
this.writer.Write(((int) obj));
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is long) {
|
||||
this.writer.Write(((long) obj));
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is float || obj is double) {
|
||||
string str = Convert.ToString(obj);
|
||||
this.writer.Write(str.Replace(',', '.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is string) {
|
||||
this.writer.Write('"');
|
||||
this.writer.Write(EncodeString((string) obj));
|
||||
this.writer.Write('"');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteDelim() {
|
||||
if (this.index > 0 && !this.isProp)
|
||||
this.writer.Write(',');
|
||||
|
||||
this.isProp = false;
|
||||
this.index++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string EncodeString(string str) {
|
||||
if (str == null)
|
||||
return null;
|
||||
|
||||
StringBuilder strBuilder = new StringBuilder(str.Length);
|
||||
char[] chars = str.ToCharArray();
|
||||
|
||||
for (int i=0; i<chars.Length; i++) {
|
||||
// Unicode it if needed
|
||||
if (chars[i] > 128 || Char.IsControl(chars[i])) {
|
||||
strBuilder.Append("\\u");
|
||||
strBuilder.Append(((int) chars[i]).ToString("X4"));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (chars[i]) {
|
||||
case '\'':
|
||||
strBuilder.Append("\\\'");
|
||||
break;
|
||||
|
||||
case '\"':
|
||||
strBuilder.Append("\\\"");
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
strBuilder.Append("\\\\");
|
||||
break;
|
||||
|
||||
default:
|
||||
strBuilder.Append(chars[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return strBuilder.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user