// // Copyright 2014 Perforce Software Inc. // using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Text.RegularExpressions; namespace Perforce.Helper { public class SearchHelper { private string _searchURL; public SearchHelper(string url) { _searchURL = url; } public string SearchURL { get { return _searchURL; } set { _searchURL = value; } } public List DoSearch(string searchStr, bool files = true, bool content = true, bool tags = true) { Log.TraceFunction(); var searchResults = new List(); var helper = Utility.GetPerforceHelper(); searchStr = Regex.Replace(searchStr, @"\s+", " "); // clean up extra whitespace searchStr = Regex.Replace(searchStr, @"\s+", " "); var searchStrBuilder = new StringBuilder(); var parts = searchStr.Split(' '); if (parts.Length == 1) { if (!parts[0].StartsWith("\'")) { searchStrBuilder.Append("*"); } searchStrBuilder.Append(parts[0].Replace("'", string.Empty)); if (!parts[0].EndsWith("\'")) { searchStrBuilder.Append("*"); } } else { foreach (var p in searchStr.Split(' ')) { if (searchStrBuilder.Length > 0) { searchStrBuilder.Append(" OR "); } if (!p.StartsWith("\'")) { searchStrBuilder.Append("*"); } searchStrBuilder.Append(p.Replace("'", string.Empty)); if (!p.EndsWith("\'")) { searchStrBuilder.Append("*"); } } } var queryString = new StringBuilder(); if (files) { queryString.AppendFormat("filename:({0})", searchStrBuilder.ToString()); } if (tags) { if (queryString.Length > 0) queryString.Append(" OR "); queryString.AppendFormat("p4attr_tags:({0})", searchStrBuilder.ToString()); } if (content) { if (queryString.Length > 0) queryString.Append(" OR "); queryString.AppendFormat("text:({0})", searchStrBuilder.ToString()); } var query = new SearchQuery { userId = helper.Username, ticket = helper.Ticket, query = string.Format("l:({0})", queryString.ToString()), searchFields = new string[0] }; var json = JsonConvert.SerializeObject(query, Formatting.Indented); Log.Debug(string.Format("SEARCH QUERY: {0}", json)); var raw = POST(json); var result = JsonConvert.DeserializeObject(raw); if (result.status.code == 200) { foreach (var p in result.payload) { searchResults.Add(p); } } else { Log.Debug(string.Format("ERROR ERROR ERROR: [{0}] {1}", result.status.code, result.status.message)); } return searchResults; } // Returns JSON string public string GET() { Log.TraceFunction(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_searchURL + "/api/search"); try { WebResponse response = request.GetResponse(); using (Stream responseStream = response.GetResponseStream()) { StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); return reader.ReadToEnd(); } } catch (WebException ex) { WebResponse errorResponse = ex.Response; using (Stream responseStream = errorResponse.GetResponseStream()) { StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); String errorText = reader.ReadToEnd(); // log errorText } throw; } } // POST a JSON string public string POST(string jsonContent) { Log.TraceFunction(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_searchURL + "/api/search"); request.Method = "POST"; System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); Byte[] byteArray = encoding.GetBytes(jsonContent); request.ContentLength = byteArray.Length; request.ContentType = @"application/json"; using (Stream dataStream = request.GetRequestStream()) { dataStream.Write(byteArray, 0, byteArray.Length); } long length = 0; try { using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { length = response.ContentLength; using (Stream stream = response.GetResponseStream()) { StreamReader reader = new StreamReader(stream, Encoding.UTF8); String responseString = reader.ReadToEnd(); return responseString; } } } catch (WebException ex) { // Log exception and throw as for GET example above Log.Warning(ex.Message); return null; } } } public class SearchQuery { public string userId { get; set; } public string ticket { get; set; } public string query { get; set; } public string[] searchFields { get; set; } } public class SearchResult { public PayloadItem[] payload { get; set; } public StatusItem status { get; set; } } public class StatusItem { public string message { get; set; } public int code { get; set; } } public class PayloadItem { public long time { get; set; } public int change { get; set; } public string depotFile { get; set; } public string action { get; set; } public int rev { get; set; } public string type { get; set; } } }