diff options
author | Josh Bell <josh@lindenlab.com> | 2007-03-14 23:03:50 +0000 |
---|---|---|
committer | Josh Bell <josh@lindenlab.com> | 2007-03-14 23:03:50 +0000 |
commit | 00dbacb215da8d6b6739b4bcefebee552de89a9c (patch) | |
tree | e1256e1fa3b195a1128bb152a876729c7f9a163d | |
parent | cf405184285c25723249d5a023b28d9498cf0c3f (diff) |
svn merge svn+ssh://svn.lindenlab.com/svn/linden/release@59161 svn+ssh://svn.lindenlab.com/svn/linden/branches/release-candidate@59163 --> release
35 files changed, 1564 insertions, 1023 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 8842a9a903..59663640e3 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -4,7 +4,7 @@ along with the issue identifier corresponding to the patches we've received from them. To see more about these contributions, visit http://jira.secondlife.com/ , and enter the issue identifier. -Alissa Sabre - VWR-81, VWR-86 +Alissa Sabre - VWR-81, VWR-83 blino Nakamura - VWR-17 Drewan Keats - VWR-28 Dylan Haskell - VWR-72 diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index c13860033e..20499d4ad3 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -97,6 +97,7 @@ const U32 DEFAULT_USER_SERVER_PORT = 12036; const U32 DEFAULT_RPC_SERVER_PORT = 12037; const U32 DEFAULT_LOG_DATA_SERVER_PORT = 12039; const U32 DEFAULT_BACKBONE_PORT = 12040; +const U32 DEFAULT_CGI_SERVICES_PORT = 12045; const U32 DEFAULT_LOCAL_ASSET_PORT = 12041; //const U32 DEFAULT_BACKBONE_CAP_PORT = 12042; // Deprecated const U32 DEFAULT_CAP_PROXY_PORT = 12043; diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index f9038afedc..a92f1c9388 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -534,7 +534,7 @@ std::istream& fullread(std::istream& str, char *buf, std::streamsize requested) std::istream& operator>>(std::istream& str, const char *tocheck) { - char c; + char c = '\0'; const char *p; p = tocheck; while (*p && !str.bad()) diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 1f64c3bde3..a2c651b444 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -13,273 +13,86 @@ #include "llapp.h" #include "lluri.h" #include "llsd.h" - +#include <iomanip> + #include "../llmath/lluuid.h" -// uric = reserved | unreserved | escaped -// reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," -// unreserved = alphanum | mark -// mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" -// escaped = "%" hex hex -static const char* ESCAPED_CHARACTERS[256] = + +// static +std::string LLURI::escape(const std::string& str, const std::string & allowed) +{ + std::ostringstream ostr; + + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + for(; it != end; ++it) + { + std::string::value_type c = *it; + if(allowed.find(c) == std::string::npos) + { + ostr << "%" + << std::uppercase << std::hex << std::setw(2) << std::setfill('0') + << static_cast<U32>(c); + } + else + { + ostr << c; + } + } + return ostr.str(); +} + +// static +std::string LLURI::unescape(const std::string& str) +{ + std::ostringstream ostr; + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + for(; it != end; ++it) + { + if((*it) == '%') + { + ++it; + if(it == end) break; + U8 c = hex_as_nybble(*it++); + c = c << 4; + if (it == end) break; + c |= hex_as_nybble(*it); + ostr.put((char)c); + } + else + { + ostr.put(*it); + } + } + return ostr.str(); +} + +namespace { - "%00", // 0 - "%01", // 1 - "%02", // 2 - "%03", // 3 - "%04", // 4 - "%05", // 5 - "%06", // 6 - "%07", // 7 - "%08", // 8 - "%09", // 9 - "%0a", // 10 - "%0b", // 11 - "%0c", // 12 - "%0d", // 13 - "%0e", // 14 - "%0f", // 15 - "%10", // 16 - "%11", // 17 - "%12", // 18 - "%13", // 19 - "%14", // 20 - "%15", // 21 - "%16", // 22 - "%17", // 23 - "%18", // 24 - "%19", // 25 - "%1a", // 26 - "%1b", // 27 - "%1c", // 28 - "%1d", // 29 - "%1e", // 30 - "%1f", // 31 - "%20", // 32 - "!", // 33 - "%22", // 34 - "%23", // 35 - "$", // 36 - "%25", // 37 - "&", // 38 - "'", // 39 - "(", // 40 - ")", // 41 - "*", // 42 - "+", // 43 - ",", // 44 - "-", // 45 - ".", // 46 - "/", // 47 - "0", // 48 - "1", // 49 - "2", // 50 - "3", // 51 - "4", // 52 - "5", // 53 - "6", // 54 - "7", // 55 - "8", // 56 - "9", // 57 - ":", // 58 - ";", // 59 - "%3c", // 60 - "=", // 61 - "%3e", // 62 - "?", // 63 - "@", // 64 - "A", // 65 - "B", // 66 - "C", // 67 - "D", // 68 - "E", // 69 - "F", // 70 - "G", // 71 - "H", // 72 - "I", // 73 - "J", // 74 - "K", // 75 - "L", // 76 - "M", // 77 - "N", // 78 - "O", // 79 - "P", // 80 - "Q", // 81 - "R", // 82 - "S", // 83 - "T", // 84 - "U", // 85 - "V", // 86 - "W", // 87 - "X", // 88 - "Y", // 89 - "Z", // 90 - "%5b", // 91 - "%5c", // 92 - "%5d", // 93 - "%5e", // 94 - "_", // 95 - "%60", // 96 - "a", // 97 - "b", // 98 - "c", // 99 - "d", // 100 - "e", // 101 - "f", // 102 - "g", // 103 - "h", // 104 - "i", // 105 - "j", // 106 - "k", // 107 - "l", // 108 - "m", // 109 - "n", // 110 - "o", // 111 - "p", // 112 - "q", // 113 - "r", // 114 - "s", // 115 - "t", // 116 - "u", // 117 - "v", // 118 - "w", // 119 - "x", // 120 - "y", // 121 - "z", // 122 - "%7b", // 123 - "%7c", // 124 - "%7d", // 125 - "~", // 126 - "%7f", // 127 - "%80", // 128 - "%81", // 129 - "%82", // 130 - "%83", // 131 - "%84", // 132 - "%85", // 133 - "%86", // 134 - "%87", // 135 - "%88", // 136 - "%89", // 137 - "%8a", // 138 - "%8b", // 139 - "%8c", // 140 - "%8d", // 141 - "%8e", // 142 - "%8f", // 143 - "%90", // 144 - "%91", // 145 - "%92", // 146 - "%93", // 147 - "%94", // 148 - "%95", // 149 - "%96", // 150 - "%97", // 151 - "%98", // 152 - "%99", // 153 - "%9a", // 154 - "%9b", // 155 - "%9c", // 156 - "%9d", // 157 - "%9e", // 158 - "%9f", // 159 - "%a0", // 160 - "%a1", // 161 - "%a2", // 162 - "%a3", // 163 - "%a4", // 164 - "%a5", // 165 - "%a6", // 166 - "%a7", // 167 - "%a8", // 168 - "%a9", // 169 - "%aa", // 170 - "%ab", // 171 - "%ac", // 172 - "%ad", // 173 - "%ae", // 174 - "%af", // 175 - "%b0", // 176 - "%b1", // 177 - "%b2", // 178 - "%b3", // 179 - "%b4", // 180 - "%b5", // 181 - "%b6", // 182 - "%b7", // 183 - "%b8", // 184 - "%b9", // 185 - "%ba", // 186 - "%bb", // 187 - "%bc", // 188 - "%bd", // 189 - "%be", // 190 - "%bf", // 191 - "%c0", // 192 - "%c1", // 193 - "%c2", // 194 - "%c3", // 195 - "%c4", // 196 - "%c5", // 197 - "%c6", // 198 - "%c7", // 199 - "%c8", // 200 - "%c9", // 201 - "%ca", // 202 - "%cb", // 203 - "%cc", // 204 - "%cd", // 205 - "%ce", // 206 - "%cf", // 207 - "%d0", // 208 - "%d1", // 209 - "%d2", // 210 - "%d3", // 211 - "%d4", // 212 - "%d5", // 213 - "%d6", // 214 - "%d7", // 215 - "%d8", // 216 - "%d9", // 217 - "%da", // 218 - "%db", // 219 - "%dc", // 220 - "%dd", // 221 - "%de", // 222 - "%df", // 223 - "%e0", // 224 - "%e1", // 225 - "%e2", // 226 - "%e3", // 227 - "%e4", // 228 - "%e5", // 229 - "%e6", // 230 - "%e7", // 231 - "%e8", // 232 - "%e9", // 233 - "%ea", // 234 - "%eb", // 235 - "%ec", // 236 - "%ed", // 237 - "%ee", // 238 - "%ef", // 239 - "%f0", // 240 - "%f1", // 241 - "%f2", // 242 - "%f3", // 243 - "%f4", // 244 - "%f5", // 245 - "%f6", // 246 - "%f7", // 247 - "%f8", // 248 - "%f9", // 249 - "%fa", // 250 - "%fb", // 251 - "%fc", // 252 - "%fd", // 253 - "%fe", // 254 - "%ff" // 255 -}; + const std::string unreserved() + { + static const std::string s = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789" + "-._~"; + return s; + } + const std::string sub_delims() + { + static const std::string s = "!$&'()*+,;="; + return s; + } + + std::string escapeHostAndPort(const std::string& s) + { return LLURI::escape(s, unreserved() + sub_delims() +":"); } + std::string escapePathComponent(const std::string& s) + { return LLURI::escape(s, unreserved() + sub_delims() + ":@"); } + std::string escapeQueryVariable(const std::string& s) + { return LLURI::escape(s, unreserved() + ":@!$'()*+,"); } // sub_delims - "&;=" + ":@" + std::string escapeQueryValue(const std::string& s) + { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@" +} LLURI::LLURI() { @@ -352,23 +165,23 @@ LLURI::~LLURI() { } - -LLURI LLURI::buildHTTP(const std::string& host_port, +// static +LLURI LLURI::buildHTTP(const std::string& prefix, const LLSD& path) { LLURI result; // TODO: deal with '/' '?' '#' in host_port - if (host_port.find("://") != host_port.npos) + if (prefix.find("://") != prefix.npos) { - // The scheme is part of the host_port - result.mScheme = ""; - result.mEscapedAuthority = escape(host_port); + // it is a prefix + result = LLURI(prefix); } else { - result.mScheme = "HTTP"; - result.mEscapedAuthority = "//" + escape(host_port); + // it is just a host and optional port + result.mScheme = "http"; + result.mEscapedAuthority = escapeHostAndPort(prefix); } if (path.isArray()) @@ -379,20 +192,20 @@ LLURI LLURI::buildHTTP(const std::string& host_port, ++it) { lldebugs << "PATH: inserting " << it->asString() << llendl; - result.mEscapedPath += "/" + escape(it->asString()); + result.mEscapedPath += "/" + escapePathComponent(it->asString()); } } - result.mEscapedOpaque = result.mEscapedAuthority + + result.mEscapedOpaque = "//" + result.mEscapedAuthority + result.mEscapedPath; return result; } // static -LLURI LLURI::buildHTTP(const std::string& host_port, +LLURI LLURI::buildHTTP(const std::string& prefix, const LLSD& path, const LLSD& query) { - LLURI result = buildHTTP(host_port, path); + LLURI result = buildHTTP(prefix, path); // break out and escape each query component if (query.isMap()) { @@ -400,8 +213,8 @@ LLURI LLURI::buildHTTP(const std::string& host_port, it != query.endMap(); it++) { - result.mEscapedQuery += escape(it->first) + - (it->second.isUndefined() ? "" : "=" + it->second.asString()) + + result.mEscapedQuery += escapeQueryVariable(it->first) + + (it->second.isUndefined() ? "" : "=" + escapeQueryValue(it->second.asString())) + "&"; } if (query.size() > 0) @@ -413,56 +226,62 @@ LLURI LLURI::buildHTTP(const std::string& host_port, } // static -LLURI LLURI::buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app) +LLURI LLURI::buildHTTP(const std::string& host, + const U32& port, + const LLSD& path) { - std::string host = "localhost:12040"; + return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path); +} - if (app) +// static +LLURI LLURI::buildHTTP(const std::string& host, + const U32& port, + const LLSD& path, + const LLSD& query) +{ + return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path, query); +} + + +namespace { + LLURI buildBackboneURL(LLApp* app, + const std::string& p1 = "", + const std::string& p2 = "", + const std::string& p3 = "") { - host = app->getOption("backbone-host-port").asString(); + std::string host = "localhost:12040"; + + if (app) + { + host = app->getOption("backbone-host-port").asString(); + } + + LLSD path = LLSD::emptyArray(); + if (!p1.empty()) path.append(p1); + if (!p2.empty()) path.append(p2); + if (!p3.empty()) path.append(p3); + + return LLURI::buildHTTP(host, path); } +} - LLSD path = LLSD::emptyArray(); - path.append("agent"); - path.append(agent_id); - path.append("presence"); - return buildHTTP(host, path); +// static +LLURI LLURI::buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app) +{ + return buildBackboneURL(app, "agent", agent_id.asString(), "presence"); } // static LLURI LLURI::buildBulkAgentPresenceURI(LLApp* app) { - std::string host = "localhost:12040"; - - if (app) - { - host = app->getOption("backbone-host-port").asString(); - } - - LLSD path = LLSD::emptyArray(); - path.append("agent"); - path.append("presence"); - - return buildHTTP(host, path); + return buildBackboneURL(app, "agent", "presence"); } // static LLURI LLURI::buildAgentSessionURI(const LLUUID& agent_id, LLApp* app) { - std::string host = "localhost:12040"; - - if (app) - { - host = app->getOption("backbone-host-port").asString(); - } - - LLSD path = LLSD::emptyArray(); - path.append("agent"); - path.append(agent_id); - path.append("session"); - - return buildHTTP(host, path); + return buildBackboneURL(app, "agent", agent_id.asString(), "session"); } // static @@ -635,43 +454,3 @@ LLSD LLURI::queryMap(std::string escaped_query_string) return result; } -// static -std::string LLURI::escape(const std::string& str) -{ - std::ostringstream ostr; - std::string::const_iterator it = str.begin(); - std::string::const_iterator end = str.end(); - S32 c; - for(; it != end; ++it) - { - c = (S32)(*it); - ostr << ESCAPED_CHARACTERS[c]; - } - return ostr.str(); -} - -// static -std::string LLURI::unescape(const std::string& str) -{ - std::ostringstream ostr; - std::string::const_iterator it = str.begin(); - std::string::const_iterator end = str.end(); - for(; it != end; ++it) - { - if((*it) == '%') - { - ++it; - if(it == end) break; - U8 c = hex_as_nybble(*it++); - c = c << 4; - if (it == end) break; - c |= hex_as_nybble(*it); - ostr.put((char)c); - } - else - { - ostr.put(*it); - } - } - return ostr.str(); -} diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 514628237d..b5c3a84173 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -26,42 +26,55 @@ class LLApp; class LLURI { public: - LLURI(); - LLURI(const std::string& escaped_str); - // construct from escaped string, as would be transmitted on the net + LLURI(); + LLURI(const std::string& escaped_str); + // construct from escaped string, as would be transmitted on the net - ~LLURI(); + ~LLURI(); - static LLURI buildHTTP(const std::string& host_port, - const LLSD& path); - static LLURI buildHTTP(const std::string& host_port, - const LLSD& path, - const LLSD& query); - - std::string asString() const; - // the whole URI, escaped as needed - - // Parts of a URI - // These functions return parts of the decoded URI. The returned - // strings are un-escaped as needed - - // for all schemes - std::string scheme() const; // ex.: "http", note lack of colon - std::string opaque() const; // everything after the colon + static LLURI buildHTTP(const std::string& prefix, + const LLSD& path); + static LLURI buildHTTP(const std::string& prefix, + const LLSD& path, + const LLSD& query); + // prefix is either a full URL prefix of the form "http://example.com:8080", + // or it can be simply a host and optional port like "example.com" or + // "example.com:8080", in these cases, the "http://" will be added - // for schemes that follow path like syntax (http, https, ftp) - std::string authority() const; // ex.: "bob@host.com:80" - std::string hostName() const; // ex.: "host.com" - U16 hostPort() const; // ex.: 80, will include implicit port - std::string path() const; // ex.: "/abc/def", includes leading slash -// LLSD pathArray() const; // above decoded into an array of strings - std::string query() const; // ex.: "x=34", section after "?" - LLSD queryMap() const; // above decoded into a map - static LLSD queryMap(std::string escaped_query_string); + static LLURI buildHTTP(const std::string& host, + const U32& port, + const LLSD& path); + static LLURI buildHTTP(const std::string& host, + const U32& port, + const LLSD& path, + const LLSD& query); + + + std::string asString() const; + // the whole URI, escaped as needed + + // Parts of a URI + // These functions return parts of the decoded URI. The returned + // strings are un-escaped as needed + + // for all schemes + std::string scheme() const; // ex.: "http", note lack of colon + std::string opaque() const; // everything after the colon + + // for schemes that follow path like syntax (http, https, ftp) + std::string authority() const; // ex.: "host.com:80" + std::string hostName() const; // ex.: "host.com" + U16 hostPort() const; // ex.: 80, will include implicit port + std::string path() const; // ex.: "/abc/def", includes leading slash + // LLSD pathArray() const; // above decoded into an array of strings + std::string query() const; // ex.: "x=34", section after "?" + LLSD queryMap() const; // above decoded into a map + static LLSD queryMap(std::string escaped_query_string); - // Escaping Utilities - static std::string escape(const std::string& str); - static std::string unescape(const std::string& str); + // Escaping Utilities + // Escape a string by urlencoding all the characters that aren't in the allowed string. + static std::string escape(const std::string& str, const std::string & allowed); + static std::string unescape(const std::string& str); // Functions for building specific URIs for web services static LLURI buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app); @@ -71,11 +84,11 @@ public: static LLURI buildInventoryHostURI(const LLUUID& agent_id, LLApp* app); private: - std::string mScheme; - std::string mEscapedOpaque; - std::string mEscapedAuthority; - std::string mEscapedPath; - std::string mEscapedQuery; + std::string mScheme; + std::string mEscapedOpaque; + std::string mEscapedAuthority; + std::string mEscapedPath; + std::string mEscapedQuery; }; #endif // LL_LLURI_H diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 0bc3f19cdf..c392d23d22 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -23,6 +23,24 @@ #include "llsdutil.h" ///---------------------------------------------------------------------------- +/// exported functions +///---------------------------------------------------------------------------- + +static const std::string INV_ITEM_ID_LABEL("item_id"); +static const std::string INV_FOLDER_ID_LABEL("folder_id"); +static const std::string INV_PARENT_ID_LABEL("parent_id"); +static const std::string INV_ASSET_TYPE_LABEL("type"); +static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type"); +static const std::string INV_INVENTORY_TYPE_LABEL("inv_type"); +static const std::string INV_NAME_LABEL("name"); +static const std::string INV_DESC_LABEL("desc"); +static const std::string INV_PERMISSIONS_LABEL("permissions"); +static const std::string INV_ASSET_ID_LABEL("asset_id"); +static const std::string INV_SALE_INFO_LABEL("sale_info"); +static const std::string INV_FLAGS_LABEL("flags"); +static const std::string INV_CREATION_DATE_LABEL("created_at"); + +///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- @@ -1113,24 +1131,24 @@ bool LLInventoryItem::fromLLSD(LLSD& sd) { mInventoryType = LLInventoryType::IT_NONE; mAssetUUID.setNull(); - const char *w; + std::string w; - w = "item_id"; + w = INV_ITEM_ID_LABEL; if (sd.has(w)) { mUUID = sd[w]; } - w = "parent_id"; + w = INV_PARENT_ID_LABEL; if (sd.has(w)) { mParentUUID = sd[w]; } - w = "permissions"; + w = INV_PERMISSIONS_LABEL; if (sd.has(w)) { mPermissions = ll_permissions_from_sd(sd[w]); } - w = "sale_info"; + w = INV_SALE_INFO_LABEL; if (sd.has(w)) { // Sale info used to contain next owner perm. It is now in @@ -1164,40 +1182,40 @@ bool LLInventoryItem::fromLLSD(LLSD& sd) LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); cipher.decrypt(mAssetUUID.mData, UUID_BYTES); } - w = "asset_id"; + w = INV_ASSET_ID_LABEL; if (sd.has(w)) { mAssetUUID = sd[w]; } - w = "type"; + w = INV_ASSET_TYPE_LABEL; if (sd.has(w)) { mType = LLAssetType::lookup(sd[w].asString().c_str()); } - w = "inv_type"; + w = INV_INVENTORY_TYPE_LABEL; if (sd.has(w)) { mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str()); } - w = "flags"; + w = INV_FLAGS_LABEL; if (sd.has(w)) { mFlags = ll_U32_from_sd(sd[w]); } - w = "name"; + w = INV_NAME_LABEL; if (sd.has(w)) { mName = sd[w].asString(); LLString::replaceNonstandardASCII(mName, ' '); LLString::replaceChar(mName, '|', ' '); } - w = "desc"; + w = INV_DESC_LABEL; if (sd.has(w)) { mDescription = sd[w].asString(); LLString::replaceNonstandardASCII(mDescription, ' '); } - w = "creation_date"; + w = INV_CREATION_DATE_LABEL; if (sd.has(w)) { mCreationDate = sd[w]; @@ -1720,24 +1738,6 @@ bool inventory_and_asset_types_match( return rv; } -///---------------------------------------------------------------------------- -/// exported functions -///---------------------------------------------------------------------------- - -static const std::string INV_ITEM_ID_LABEL("item_id"); -static const std::string INV_FOLDER_ID_LABEL("folder_id"); -static const std::string INV_PARENT_ID_LABEL("parent_id"); -static const std::string INV_ASSET_TYPE_LABEL("type"); -static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type"); -static const std::string INV_INVENTORY_TYPE_LABEL("inv_type"); -static const std::string INV_NAME_LABEL("name"); -static const std::string INV_DESC_LABEL("desc"); -static const std::string INV_PERMISSIONS_LABEL("permissions"); -static const std::string INV_ASSET_ID_LABEL("asset_id"); -static const std::string INV_SALE_INFO_LABEL("sale_info"); -static const std::string INV_FLAGS_LABEL("flags"); -static const std::string INV_CREATION_DATE_LABEL("created_at"); - LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item) { LLSD rv; diff --git a/indra/llinventory/llnotecard.cpp b/indra/llinventory/llnotecard.cpp index 79545874b4..96ee7ff800 100644 --- a/indra/llinventory/llnotecard.cpp +++ b/indra/llinventory/llnotecard.cpp @@ -7,11 +7,10 @@ */ #include "linden_common.h" -#include "llinventory.h" #include "llnotecard.h" #include "llstreamtools.h" -LLNotecard::LLNotecard(U32 max_text) +LLNotecard::LLNotecard(S32 max_text) : mMaxText(max_text) { } @@ -179,7 +178,7 @@ bool LLNotecard::importStream(std::istream& str) } line_buf[STD_STRING_STR_LEN] = '\0'; - U32 text_len = 0; + S32 text_len = 0; if( 1 != sscanf(line_buf, "Text length %d", &text_len) ) { llwarns << "Invalid Linden text length field" << llendl; diff --git a/indra/llinventory/llnotecard.h b/indra/llinventory/llnotecard.h index 5f510a674f..04fe666562 100644 --- a/indra/llinventory/llnotecard.h +++ b/indra/llinventory/llnotecard.h @@ -9,12 +9,21 @@ #ifndef LL_NOTECARD_H #define LL_NOTECARD_H -const S32 MAX_NOTECARD_SIZE = 65536; +#include "llmemory.h" +#include "llinventory.h" class LLNotecard { public: - LLNotecard(U32 max_text); + /** + * @brief anonymous enumeration to set max size. + */ + enum + { + MAX_SIZE = 65536 + }; + + LLNotecard(S32 max_text = LLNotecard::MAX_SIZE); virtual ~LLNotecard(); bool importStream(std::istream& str); @@ -33,7 +42,7 @@ private: bool exportEmbeddedItemsStream(std::ostream& str); std::vector<LLPointer<LLInventoryItem> > mItems; LLString mText; - U32 mMaxText; + S32 mMaxText; S32 mVersion; S32 mEmbeddedVersion; }; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index d83308d082..f93a12b274 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -131,6 +131,27 @@ namespace const LLSD mSD; }; + + class RawInjector : public Injector + { + public: + RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {} + virtual ~RawInjector() {} + + const char* contentType() { return "application/octet-stream"; } + + virtual EStatus process_impl(const LLChannelDescriptors& channels, + buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) + { + LLBufferStream ostream(channels, buffer.get()); + ostream.write((const char *)mData, mSize); // hopefully chars are always U8s + eos = true; + return STATUS_DONE; + } + + const U8* mData; + S32 mSize; + }; class FileInjector : public Injector { @@ -301,6 +322,11 @@ void LLHTTPClient::post(const std::string& url, const LLSD& body, ResponderPtr r request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder); } +void LLHTTPClient::post(const std::string& url, const U8* data, S32 size, ResponderPtr responder) +{ + request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder); +} + void LLHTTPClient::del(const std::string& url, ResponderPtr responder) { request(url, LLURLRequest::HTTP_DELETE, NULL, responder); diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index d64662e41d..a8afea312d 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -54,6 +54,7 @@ public: static void put(const std::string& url, const LLSD& body, ResponderPtr); ///< non-blocking static void post(const std::string& url, const LLSD& body, ResponderPtr); + static void post(const std::string& url, const U8* data, S32 size, ResponderPtr responder); static void postFile(const std::string& url, const std::string& filename, ResponderPtr); static void postFile(const std::string& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder); diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 66ce415541..f49ffa1603 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -1,5 +1,5 @@ /* Localized versions of Info.plist keys */ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 1.13.3.3"; -CFBundleGetInfoString = "Second Life version 1.13.3.3, Copyright 2004-2006 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 1.13.4.8"; +CFBundleGetInfoString = "Second Life version 1.13.4.8, Copyright 2004-2007 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 13901656b5..448c7922ff 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>1.13.3.3</string> + <string>1.13.4.8</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index b37538f023..7c615dd159 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -1,10 +1,6 @@ -/** - * @file llmapresponders.h - * @brief Processes responses received for asset upload requests. - * - * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. - * $License$ - */ +// llassetuploadresponders.cpp +// Copyright 2006, Linden Research, Inc. +// Processes responses received for asset upload requests. #include "llviewerprecompiledheaders.h" @@ -19,39 +15,71 @@ #include "llinventorymodel.h" #include "llinventoryview.h" #include "llpermissionsflags.h" +#include "llpreviewnotecard.h" +#include "llpreviewscript.h" +#include "llscrolllistctrl.h" #include "lluploaddialog.h" -#include "llviewermenu.h" // for upload_new_resource() +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewermenu.h" #include "llviewerwindow.h" #include "viewer.h" -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLUUID& uuid, - const LLSD &post_data) - : LLHTTPClient::Responder() +void dialog_refresh_all(); + +LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) + : LLHTTPClient::Responder(), + mPostData(post_data), + mVFileID(vfile_id), + mAssetType(asset_type) +{ + if (!gVFS->getExists(vfile_id, asset_type)) + { + llwarns << "LLAssetUploadResponder called with nonexistant vfile_id" << llendl; + mVFileID.setNull(); + mAssetType = LLAssetType::AT_NONE; + return; + } +} + +LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, + const std::string& file_name) + : LLHTTPClient::Responder(), + mPostData(post_data), + mFileName(file_name) +{ +} + +LLAssetUploadResponder::~LLAssetUploadResponder() { - mUUID = uuid; - mPostData = post_data; + if (!mFileName.empty()) + { + // Delete temp file + LLFile::remove(mFileName.c_str()); + } } // virtual -void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reason) +void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) { - llinfos << "LLNewAgentInventoryResponder::error " << statusNum << llendl; + llinfos << "LLAssetUploadResponder::error " << statusNum + << " reason: " << reason << llendl; LLStringBase<char>::format_map_t args; switch(statusNum) { case 400: - args["[FILE]"] = mPostData["inventory_type"].asString(); - args["[REASON]"] = "invalid parameters in upload request"; + args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["[REASON]"] = "Error in upload request. Please contact " + "support@lindenlab.com for help fixing this problem."; gViewerWindow->alertXml("CannotUploadReason", args); break; - case 402: - //(result["message"].asString() == "insufficient funds") - LLFloaterBuyCurrency::buyCurrency("Uploading costs", gGlobalEconomy->getPriceUpload()); - break; case 500: default: - args["[FILE]"] = mPostData["inventory_type"].asString(); - args["[REASON]"] = "the server is experiencing unexpected difficulties"; + args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["[REASON]"] = "The server is experiencing unexpected " + "difficulties. Please try again later."; gViewerWindow->alertXml("CannotUploadReason", args); break; } @@ -59,139 +87,373 @@ void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reaso } //virtual -void LLNewAgentInventoryResponder::result(const LLSD& result) +void LLAssetUploadResponder::result(const LLSD& content) { - lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; + lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl; - if (!result["success"]) + std::string state = content["state"]; + if (state == "upload") + { + uploadUpload(content); + } + else if (state == "complete") + { + // rename file in VFS with new asset id + if (mFileName.empty()) + { + // rename the file in the VFS to the actual asset id + gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType); + } + uploadComplete(content); + } + else + { + uploadFailure(content); + } +} + +void LLAssetUploadResponder::uploadUpload(const LLSD& content) +{ + std::string uploader = content["uploader"]; + if (mFileName.empty()) + { + LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this); + } + else + { + LLHTTPClient::postFile(uploader, mFileName, this); + }
+} + +void LLAssetUploadResponder::uploadFailure(const LLSD& content) +{ + std::string reason = content["state"]; + // deal with money errors + if (reason == "insufficient funds") + { + LLFloaterBuyCurrency::buyCurrency("Uploading costs", gGlobalEconomy->getPriceUpload()); + } + else { LLStringBase<char>::format_map_t args; - args["[FILE]"] = mPostData["inventory_type"].asString(); - args["[REASON]"] = "the server is experiencing unexpected difficulties"; + args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["[REASON]"] = content["message"].asString(); gViewerWindow->alertXml("CannotUploadReason", args); - return; } +} + +void LLAssetUploadResponder::uploadComplete(const LLSD& content) +{ +} + +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} + +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name) +: LLAssetUploadResponder(post_data, file_name) +{ +} + +//virtual +void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) +{ + lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; - std::string uploader = result["uploader"]; LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString().c_str()); LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString().c_str()); - // request succeeded - if (!uploader.empty()) + + // Update money and ownership credit information + // since it probably changed on the server + if (asset_type == LLAssetType::AT_TEXTURE || + asset_type == LLAssetType::AT_SOUND || + asset_type == LLAssetType::AT_ANIMATION) { - LLHTTPClient::postFile(uploader, mUUID, asset_type, this); + gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_MoneyData); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); + gAgent.sendReliableMessage(); + + LLString::format_map_t args; + args["[AMOUNT]"] = llformat("%d",gGlobalEconomy->getPriceUpload()); + LLNotifyBox::showXml("UploadPayment", args); } - // upload succeeded - else - { - // rename the file in the VFS to the actual asset id - gVFS->renameFile(mUUID, asset_type, result["new_asset"].asUUID(), asset_type); - // TODO: only request for textures, sound, and animation uploads - // Update money and ownership credit information - // since it probably changed on the server - if (mPostData["asset_type"].asString() == "texture" || - mPostData["asset_type"].asString() == "sound" || - mPostData["asset_type"].asString() == "animatn") + // Actually add the upload to viewer inventory + llinfos << "Adding " << content["new_inventory_item"].asUUID() << " " + << content["new_asset"].asUUID() << " to inventory." << llendl; + if(mPostData["folder_id"].asUUID().notNull()) + { + LLPermissions perm; + U32 next_owner_perm; + perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); + if (mPostData["inventory_type"].asString() == "snapshot") { - gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_MoneyData); - gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); - gAgent.sendReliableMessage(); - - LLString::format_map_t args; - args["[AMOUNT]"] = llformat("%d",gGlobalEconomy->getPriceUpload()); - LLNotifyBox::showXml("UploadPayment", args); + next_owner_perm = PERM_ALL; } - // Actually add the upload to viewer inventory - llinfos << "Adding " << result["new_inventory_item"].asUUID() << " " - << result["new_asset"].asUUID() << " to inventory." << llendl; - if(mPostData["folder_id"].asUUID().notNull()) + else { - LLPermissions perm; - U32 next_owner_perm; - perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); - if (mPostData["inventory_type"].asString() == "snapshot") + next_owner_perm = PERM_MOVE | PERM_TRANSFER; + } + perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); + S32 creation_date_now = time_corrected(); + LLPointer<LLViewerInventoryItem> item + = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(), + mPostData["folder_id"].asUUID(), + perm, + content["new_asset"].asUUID(), + asset_type, + inventory_type, + mPostData["name"].asString(), + mPostData["description"].asString(), + LLSaleInfo::DEFAULT, + LLInventoryItem::II_FLAGS_NONE, + creation_date_now); + gInventory.updateItem(item); + gInventory.notifyObservers(); + + // Show the preview panel for textures and sounds to let + // user know that the image (or snapshot) arrived intact. + LLInventoryView* view = LLInventoryView::getActiveInventory(); + if(view) + { + LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); + + view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); + if((LLAssetType::AT_TEXTURE == asset_type) + || (LLAssetType::AT_SOUND == asset_type)) { - next_owner_perm = PERM_ALL; + view->getPanel()->openSelected(); } - else + //LLInventoryView::dumpSelectionInformation((void*)view); + // restore keyboard focus + gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + } + } + else + { + llwarns << "Can't find a folder to put it in" << llendl; + } + + // remove the "Uploading..." message + LLUploadDialog::modalUploadFinished(); + + // *FIX: This is a pretty big hack. What this does is check the + // file picker if there are any more pending uploads. If so, + // upload that file. + const char* next_file = LLFilePicker::instance().getNextFile(); + if(next_file) + { + const char* name = LLFilePicker::instance().getDirname(); + + LLString asset_name = name; + LLString::replaceNonstandardASCII( asset_name, '?' ); + LLString::replaceChar(asset_name, '|', '?'); + LLString::stripNonprintable(asset_name); + LLString::trim(asset_name); + + char* asset_name_str = (char*)asset_name.c_str(); + char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists + if( !end_p ) + { + end_p = asset_name_str + strlen( asset_name_str ); /*Flawfinder: ignore*/ + } + + S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); + + asset_name = asset_name.substr( 0, len ); + + upload_new_resource(next_file, asset_name, asset_name, + 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); + } +} + + +LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} + +LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, + const std::string& file_name) +: LLAssetUploadResponder(post_data, file_name) +{ +} + +//virtual +void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content) +{ + llinfos << "LLUpdateAgentInventoryResponder::result from capabilities" << llendl; + LLUUID item_id = mPostData["item_id"]; + + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(item_id); + if(!item) + { + llwarns << "Inventory item for " << mVFileID + << " is no longer in agent inventory." << llendl; + return; + } + + // Update viewer inventory item + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->setAssetUUID(content["new_asset"].asUUID()); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + + llinfos << "Inventory item " << item->getName() << " saved into " + << content["new_asset"].asString() << llendl; + + LLInventoryType::EType inventory_type = new_item->getInventoryType(); + switch(inventory_type) + { + case LLInventoryType::IT_NOTECARD: { - next_owner_perm = PERM_MOVE | PERM_TRANSFER; + + // Update the UI with the new asset. + LLPreviewNotecard* nc; + nc = (LLPreviewNotecard*)LLPreview::find(new_item->getUUID()); + if(nc) + { + // *HACK: we have to delete the asset in the VFS so + // that the viewer will redownload it. This is only + // really necessary if the asset had to be modified by + // the uploader, so this can be optimized away in some + // cases. A better design is to have a new uuid if the + // script actually changed the asset. + if(nc->hasEmbeddedInventory()) + { + gVFS->removeFile( + content["new_asset"].asUUID(), + LLAssetType::AT_NOTECARD); + } + nc->refreshFromInventory(); + } } - perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); - S32 creation_date_now = time_corrected(); - LLPointer<LLViewerInventoryItem> item - = new LLViewerInventoryItem(result["new_inventory_item"].asUUID(), - mPostData["folder_id"].asUUID(), - perm, - result["new_asset"].asUUID(), - asset_type, - inventory_type, - mPostData["name"].asString(), - mPostData["description"].asString(), - LLSaleInfo::DEFAULT, - LLInventoryItem::II_FLAGS_NONE, - creation_date_now); - gInventory.updateItem(item); - gInventory.notifyObservers(); - - // Show the preview panel for textures and sounds to let - // user know that the image (or snapshot) arrived intact. - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) + break; + case LLInventoryType::IT_LSL: { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); - - view->getPanel()->setSelection(result["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); - if((LLAssetType::AT_TEXTURE == asset_type) - || (LLAssetType::AT_SOUND == asset_type)) + // Find our window and close it if requested. + LLPreviewLSL* preview = (LLPreviewLSL*)LLPreview::find(item_id); + if (preview) { - view->getPanel()->openSelected(); + // Bytecode save completed + if (content["compiled"]) + { + preview->callbackLSLCompileSucceeded(); + } + else + { + preview->callbackLSLCompileFailed(content["errors"]); + } } - //LLInventoryView::dumpSelectionInformation((void*)view); - // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); } - } - else - { - llwarns << "Can't find a folder to put it in" << llendl; - } + break; + case LLInventoryType::IT_WEARABLE: + default: + break; + } +} - // remove the "Uploading..." message - LLUploadDialog::modalUploadFinished(); - - // *NOTE: This is a pretty big hack. What this does is check - // the file picker if there are any more pending uploads. If - // so, upload that file. - const char* next_file = LLFilePicker::instance().getNextFile(); - if(next_file) - { - const char* name = LLFilePicker::instance().getDirname(); - LLString asset_name = name; - LLString::replaceNonstandardASCII( asset_name, '?' ); - LLString::replaceChar(asset_name, '|', '?'); - LLString::stripNonprintable(asset_name); - LLString::trim(asset_name); +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} - char* asset_name_str = (char*)asset_name.c_str(); - char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists - if( !end_p ) +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, + const std::string& file_name) +: LLAssetUploadResponder(post_data, file_name) +{ +} + +//virtual +void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) +{ + llinfos << "LLUpdateTaskInventoryResponder::result from capabilities" << llendl; + LLUUID item_id = mPostData["item_id"]; + LLUUID task_id = mPostData["task_id"]; + + LLViewerObject* object = gObjectList.findObject(task_id); + if (!object) + { + llwarns << "LLUpdateTaskInventoryResponder::uploadComplete task " << task_id + << " no longer exist." << llendl; + return; + } + LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(item_id); + if (!item) + { + llwarns << "LLUpdateTaskInventoryResponder::uploadComplete item " + << item_id << " is no longer in task " << task_id + << "'s inventory." << llendl; + return; + } + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + // Update Viewer inventory + object->updateViewerInventoryAsset(new_item, content["new_asset"]); + dialog_refresh_all(); + + LLInventoryType::EType inventory_type = new_item->getInventoryType(); + switch(inventory_type) + { + case LLInventoryType::IT_NOTECARD: { - end_p = asset_name_str + strlen( asset_name_str ); /*Flawfinder: ignore*/ - } - - S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); - asset_name = asset_name.substr( 0, len ); + // Update the UI with the new asset. + LLPreviewNotecard* nc; + nc = (LLPreviewNotecard*)LLPreview::find(new_item->getUUID()); + if(nc) + { + // *HACK: we have to delete the asset in the VFS so + // that the viewer will redownload it. This is only + // really necessary if the asset had to be modified by + // the uploader, so this can be optimized away in some + // cases. A better design is to have a new uuid if the + // script actually changed the asset. + if(nc->hasEmbeddedInventory()) + { + gVFS->removeFile( + content["new_asset"].asUUID(), + LLAssetType::AT_NOTECARD); + } - upload_new_resource(next_file, asset_name, asset_name, - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); - } + nc->refreshFromInventory(); + } + } + break; + case LLInventoryType::IT_LSL: + { + LLLiveLSLEditor* preview = LLLiveLSLEditor::find(item_id, task_id); + if (preview) + { + // Bytecode save completed + if (content["compiled"]) + { + preview->callbackLSLCompileSucceeded( + task_id, + item_id, + mPostData["is_script_running"]); + } + else + { + preview->callbackLSLCompileFailed(content["errors"]); + } + } + } + break; + case LLInventoryType::IT_WEARABLE: + default: + break; } } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index b4d5377601..ef8cd3834a 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -1,26 +1,65 @@ -/** - * @file llmapresponders.h - * @brief Processes responses received for asset upload requests. - * - * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. - * $License$ - */ +// llassetuploadresponders.h +// Copyright 2006, Linden Research, Inc. +// Processes responses received for asset upload requests. -#ifndef LL_LLNEWAGENTINVENTORYRESPONDER_H -#define LL_LLNEWAGENTINVENTORYRESPONDER_H +#ifndef LL_LLASSETUPLOADRESPONDER_H +#define LL_LLASSETUPLOADRESPONDER_H #include "llhttpclient.h" -class LLNewAgentInventoryResponder : public LLHTTPClient::Responder +// Abstract class for supporting asset upload +// via capabilities +class LLAssetUploadResponder : public LLHTTPClient::Responder { public: - LLNewAgentInventoryResponder(const LLUUID& uuid, const LLSD& post_data); - void error(U32 statusNum, const std::string& reason); + LLAssetUploadResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLAssetUploadResponder(const LLSD& post_data, const std::string& file_name); + ~LLAssetUploadResponder(); + virtual void error(U32 statusNum, const std::string& reason); virtual void result(const LLSD& content); + virtual void uploadUpload(const LLSD& content); + virtual void uploadComplete(const LLSD& content); + virtual void uploadFailure(const LLSD& content); -private: - LLUUID mUUID; +protected: LLSD mPostData; + LLUUID mVFileID; + LLAssetType::EType mAssetType; + std::string mFileName; }; -#endif // LL_LLNEWAGENTINVENTORYRESPONDER_H +class LLNewAgentInventoryResponder : public LLAssetUploadResponder +{ +public: + LLNewAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name); + virtual void uploadComplete(const LLSD& content); +}; + +class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder +{ +public: + LLUpdateAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLUpdateAgentInventoryResponder(const LLSD& post_data, + const std::string& file_name); + virtual void uploadComplete(const LLSD& content); +}; + +class LLUpdateTaskInventoryResponder : public LLAssetUploadResponder +{ +public: + LLUpdateTaskInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLUpdateTaskInventoryResponder(const LLSD& post_data, + const std::string& file_name); + virtual void uploadComplete(const LLSD& content); +}; + +#endif // LL_LLASSETUPLOADRESPONDER_H diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index f82978c5fc..7eaac8887c 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -39,6 +39,8 @@ #include "llvfs.h" #include "viewer.h" +#include "llassetuploadresponders.h" + ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- @@ -206,6 +208,23 @@ void LLFloaterPostcard::onClickCancel(void* data) } } +class LLSendPostcardResponder : public LLAssetUploadResponder +{ +public: + LLSendPostcardResponder(const LLSD &post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type): + LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + } + // *TODO define custom uploadFailed here so it's not such a generic message + void LLSendPostcardResponder::uploadComplete(const LLSD& content) + { + // we don't care about what the server returns from this post, just clean up the UI + LLUploadDialog::modalUploadFinished(); + } +}; + // static void LLFloaterPostcard::onClickSend(void* data) { @@ -230,12 +249,31 @@ void LLFloaterPostcard::onClickSend(void* data) if (self->mJPEGImage.notNull()) { - // upload the image self->mTransactionID.generate(); self->mAssetID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID()); LLVFile::writeFile(self->mJPEGImage->getData(), self->mJPEGImage->getDataSize(), gVFS, self->mAssetID, LLAssetType::AT_IMAGE_JPEG); - - gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)self, FALSE); + + // upload the image + std::string url = gAgent.getRegion()->getCapability("SendPostcard"); + if(!url.empty()) + { + llinfos << "Send Postcard via capability" << llendl; + LLSD body = LLSD::emptyMap(); + // the capability already encodes: agent ID, region ID + body["pos-global"] = self->mPosTakenGlobal.getValue(); + body["to"] = self->childGetValue("to_form").asString(); + body["from"] = self->childGetValue("from_form").asString(); + body["name"] = self->childGetValue("name_form").asString(); + body["subject"] = self->childGetValue("subject_form").asString(); + body["msg"] = self->childGetValue("msg_form").asString(); + body["allow-publish"] = self->childGetValue("allow_publish_check").asBoolean(); + body["mature-publish"] = self->childGetValue("mature_check").asBoolean(); + LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, self->mAssetID, LLAssetType::AT_IMAGE_JPEG)); + } + else + { + gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)self, FALSE); + } LLUploadDialog::modalUploadDialog("Uploading...\n\nPostcard"); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 84c99db8da..62f5fd21d5 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -44,6 +44,7 @@ #include "lltooldraganddrop.h" #include "llfloatermap.h" #include "lluiconstants.h" +#include "lluploaddialog.h" #include "llcallingcard.h" #include "llviewerobjectlist.h" #include "llagent.h" @@ -61,6 +62,7 @@ #include "llvieweruictrlfactory.h" #include "viewer.h" +#include "llassetuploadresponders.h" const U32 INCLUDE_SCREENSHOT = 0x01 << 0; @@ -96,7 +98,8 @@ LLFloaterReporter::LLFloaterReporter( mDeselectOnClose( FALSE ), mPicking( FALSE), mPosition(), - mCopyrightWarningSeen( FALSE ) + mCopyrightWarningSeen( FALSE ), + mResourceDatap(new LLResourceData()) { if (report_type == BUG_REPORT) { @@ -147,9 +150,9 @@ LLFloaterReporter::LLFloaterReporter( gReporterInstances.addData(report_type, this); - // Upload a screenshot, but don't draw this floater. + // Take a screenshot, but don't draw this floater. setVisible(FALSE); - uploadScreenshot(); + takeScreenshot(); setVisible(TRUE); // Default text to be blank @@ -211,6 +214,7 @@ LLFloaterReporter::~LLFloaterReporter() std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() ); mMCDList.clear(); + delete mResourceDatap; gDialogVisible = FALSE; } @@ -344,7 +348,7 @@ void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, if ( self->mReportType != BUG_REPORT ) { self->childSetText("abuser_name_edit", names[0] ); - + self->mAbuserID = ids[0]; self->refresh(); @@ -355,31 +359,59 @@ void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, void LLFloaterReporter::onClickSend(void *userdata) { LLFloaterReporter *self = (LLFloaterReporter *)userdata; + + if (self->mPicking) + { + closePickTool(self); + } - // only do this for abuse reports - if ( self->mReportType != BUG_REPORT ) + if(self->validateReport()) { - if ( ! self->mCopyrightWarningSeen ) + // only show copyright alert for abuse reports + if ( self->mReportType != BUG_REPORT ) { - LLString details_lc = self->childGetText("details_edit"); - LLString::toLower( details_lc ); - LLString summary_lc = self->childGetText("summary_edit"); - LLString::toLower( summary_lc ); - if ( details_lc.find( "copyright" ) != std::string::npos || - summary_lc.find( "copyright" ) != std::string::npos ) + if ( ! self->mCopyrightWarningSeen ) { - gViewerWindow->alertXml("HelpReportAbuseContainsCopyright"); - self->mCopyrightWarningSeen = TRUE; - return; + LLString details_lc = self->childGetText("details_edit"); + LLString::toLower( details_lc ); + LLString summary_lc = self->childGetText("summary_edit"); + LLString::toLower( summary_lc ); + if ( details_lc.find( "copyright" ) != std::string::npos || + summary_lc.find( "copyright" ) != std::string::npos ) + { + gViewerWindow->alertXml("HelpReportAbuseContainsCopyright"); + self->mCopyrightWarningSeen = TRUE; + return; + }; }; }; - }; - if (self->mPicking) - { - closePickTool(self); + LLUploadDialog::modalUploadDialog("Uploading...\n\nReport"); + // *TODO don't upload image if checkbox isn't checked + std::string url = gAgent.getRegion()->getCapability("SendUserReport"); + std::string sshot_url = gAgent.getRegion()->getCapability("SendUserReportWithScreenshot"); + if(!url.empty() || !sshot_url.empty()) + { + self->sendReportViaCaps(url, sshot_url, self->gatherReport()); + self->close(); + } + else + { + if(self->childGetValue("screen_check")) + { + self->childDisable("send_btn"); + self->childDisable("cancel_btn"); + // the callback from uploading the image calls sendReportViaLegacy() + self->uploadImage(); + } + else + { + self->sendReportViaLegacy(self->gatherReport()); + LLUploadDialog::modalUploadFinished(); + self->close(); + } + } } - self->sendReport(); } @@ -532,10 +564,9 @@ void LLFloaterReporter::setPickedObjectProperties(const char *object_name, const childSetText("owner_name", owner_name); } -void LLFloaterReporter::sendReport() + +bool LLFloaterReporter::validateReport() { - LLViewerRegion *regionp = gAgent.getRegion(); - if (!regionp) return; // Ensure user selected a category from the list LLSD category_sd = childGetValue("category_combo"); U8 category = (U8)category_sd.asInteger(); @@ -549,7 +580,7 @@ void LLFloaterReporter::sendReport() { gViewerWindow->alertXml("HelpReportBugSelectCategory"); } - return; + return false; } if ( mReportType != BUG_REPORT ) @@ -557,13 +588,13 @@ void LLFloaterReporter::sendReport() if ( childGetText("abuser_name_edit").empty() ) { gViewerWindow->alertXml("HelpReportAbuseAbuserNameEmpty"); - return; + return false; }; if ( childGetText("abuse_location_edit").empty() ) { gViewerWindow->alertXml("HelpReportAbuseAbuserLocationEmpty"); - return; + return false; }; }; @@ -577,7 +608,7 @@ void LLFloaterReporter::sendReport() { gViewerWindow->alertXml("HelpReportBugSummaryEmpty"); } - return; + return false; }; if ( childGetText("details_edit") == mDefaultSummary ) @@ -590,53 +621,19 @@ void LLFloaterReporter::sendReport() { gViewerWindow->alertXml("HelpReportBugDetailsEmpty"); } - return; + return false; }; + return true; +} + +LLSD LLFloaterReporter::gatherReport() +{ + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) return LLSD(); // *TODO handle this failure case more gracefully // reset flag in case the next report also contains this text mCopyrightWarningSeen = FALSE; - U32 check_flags = 0; - if (childGetValue("screen_check")) - { - check_flags |= INCLUDE_SCREENSHOT; - } - - LLMessageSystem *msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UserReport); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ReportData); - msg->addU8Fast(_PREHASH_ReportType, (U8) mReportType); - msg->addU8(_PREHASH_Category, category); - msg->addVector3Fast(_PREHASH_Position, mPosition); - msg->addU8Fast(_PREHASH_CheckFlags, (U8) check_flags); - - // only send a screenshot ID if we're asked too and the email is - // going to LL - Estate Owners cannot see the screenshot asset - LLSD screenshot_id = LLUUID::null; - if (childGetValue("screen_check")) - { - if ( mReportType != BUG_REPORT ) - { - if ( gEmailToEstateOwner == FALSE ) - { - screenshot_id = childGetValue("screenshot"); - } - } - else - { - screenshot_id = childGetValue("screenshot"); - }; - }; - msg->addUUIDFast(_PREHASH_ScreenshotID, screenshot_id); - msg->addUUIDFast(_PREHASH_ObjectID, mObjectID); - - msg->addUUID("AbuserID", mAbuserID ); - msg->addString("AbuseRegionName", ""); - msg->addUUID("AbuseRegionID", LLUUID::null); - std::ostringstream summary; if (!gInProductionGrid) { @@ -684,7 +681,6 @@ void LLFloaterReporter::sendReport() << " {" << childGetText("abuser_name_edit") << "} " // name of abuse entered in report (chosen using LLAvatarPicker) << " \"" << childGetValue("summary_edit").asString() << "\""; // summary as entered }; - msg->addStringFast(_PREHASH_Summary, summary.str().c_str()); std::ostringstream details; if (mReportType != BUG_REPORT) @@ -709,7 +705,6 @@ void LLFloaterReporter::sendReport() }; details << childGetValue("details_edit").asString(); - msg->addStringFast(_PREHASH_Details, details.str() ); char version_string[MAX_STRING]; /* Flawfinder: ignore */ snprintf(version_string, /* Flawfinder: ignore */ @@ -722,120 +717,204 @@ void LLFloaterReporter::sendReport() gSysCPU.getFamily().c_str(), gGLManager.mGLRenderer.c_str(), gGLManager.mDriverVersionVendorString.c_str()); - msg->addString("VersionString", version_string); - msg->sendReliable(regionp->getHost()); + // only send a screenshot ID if we're asked to and the email is + // going to LL - Estate Owners cannot see the screenshot asset + LLUUID screenshot_id = LLUUID::null; + if (childGetValue("screen_check")) + { + if ( mReportType != BUG_REPORT ) + { + if ( gEmailToEstateOwner == FALSE ) + { + screenshot_id = childGetValue("screenshot"); + } + } + else + { + screenshot_id = childGetValue("screenshot"); + }; + }; - close(); + LLSD report = LLSD::emptyMap(); + report["report-type"] = (U8) mReportType; + report["category"] = childGetValue("category_combo"); + report["position"] = mPosition.getValue(); + report["check-flags"] = (U8)0; // this is not used + report["screenshot-id"] = screenshot_id; + report["object-id"] = mObjectID; + report["abuser-id"] = mAbuserID; + report["abuse-region-name"] = ""; + report["abuse-region-id"] = LLUUID::null; + report["summary"] = summary.str(); + report["version-string"] = version_string; + report["details"] = details.str(); + return report; } +void LLFloaterReporter::sendReportViaLegacy(const LLSD & report) +{ + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) return; + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UserReport); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ReportData); + msg->addU8Fast(_PREHASH_ReportType, report["report-type"].asInteger()); + msg->addU8(_PREHASH_Category, report["category"].asInteger()); + msg->addVector3Fast(_PREHASH_Position, LLVector3(report["position"])); + msg->addU8Fast(_PREHASH_CheckFlags, report["check-flags"].asInteger()); + msg->addUUIDFast(_PREHASH_ScreenshotID, report["screenshot-id"].asUUID()); + msg->addUUIDFast(_PREHASH_ObjectID, report["object-id"].asUUID()); + msg->addUUID("AbuserID", report["abuser-id"].asUUID()); + msg->addString("AbuseRegionName", report["abuse-region-name"].asString()); + msg->addUUID("AbuseRegionID", report["abuse-region-id"].asUUID()); + + msg->addStringFast(_PREHASH_Summary, report["summary"].asString().c_str()); + msg->addString("VersionString", report["version-string"]); + msg->addStringFast(_PREHASH_Details, report["details"] ); + + msg->sendReliable(regionp->getHost()); +} -void LLFloaterReporter::uploadScreenshot() +class LLUserReportScreenshotResponder : public LLAssetUploadResponder +{ +public: + LLUserReportScreenshotResponder(const LLSD & post_data, + const LLUUID & vfile_id, + LLAssetType::EType asset_type): + LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + } + void uploadFailed(const LLSD& content) + { + // *TODO pop up a dialog so the user knows their report screenshot didn't make it + LLUploadDialog::modalUploadFinished(); + } + void uploadComplete(const LLSD& content) + { + // we don't care about what the server returns from this post, just clean up the UI + LLUploadDialog::modalUploadFinished(); + } +}; + +class LLUserReportResponder : public LLHTTPClient::Responder +{ +public: + LLUserReportResponder(): LLHTTPClient::Responder() {} + + void error(U32 status, const std::string& reason) + { + // *TODO do some user messaging here + LLUploadDialog::modalUploadFinished(); + } + void result(const LLSD& content) + { + // we don't care about what the server returns + LLUploadDialog::modalUploadFinished(); + } +}; + +void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) +{ + if(childGetValue("screen_check").asBoolean() && !sshot_url.empty()) + { + // try to upload screenshot + LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report, + mResourceDatap->mAssetInfo.mUuid, + mResourceDatap->mAssetInfo.mType)); + } + else + { + // screenshot not wanted or we don't have screenshot cap + LLHTTPClient::post(url, report, new LLUserReportResponder()); + } +} + +void LLFloaterReporter::takeScreenshot() { const S32 IMAGE_WIDTH = 1024; const S32 IMAGE_HEIGHT = 768; - LLString filename("report_screenshot.bmp"); - if( !gViewerWindow->saveSnapshot( filename, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE ) ) + LLPointer<LLImageRaw> raw = new LLImageRaw; + if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, TRUE, FALSE)) { + llwarns << "Unable to take screenshot" << llendl; return; } + LLPointer<LLImageJ2C> upload_data = LLViewerImageList::convertToUploadFile(raw); - // Generate the temporary filename - std::string temp_filename = gDirUtilp->getTempFilename(); - - // try to create the upload file - if (!LLViewerImageList::createUploadFile(filename, - temp_filename, - IMG_CODEC_BMP )) + // create a resource data + mResourceDatap->mInventoryType = LLInventoryType::IT_NONE; + mResourceDatap->mAssetInfo.mTransactionID.generate(); + mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + if (BUG_REPORT == mReportType) { - llwarns << "Unable to upload report screenshot " << filename << ":\n\n" << LLImageBase::getLastError() << "\n" << llendl; - if(LLFile::remove(temp_filename.c_str()) == -1) - { - lldebugs << "unable to remove temp file" << llendl; - } - LLFilePicker::instance().reset(); + mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE; + mResourceDatap->mPreferredLocation = LLAssetType::EType(-1); + } + else if (COMPLAINT_REPORT == mReportType) + { + mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE; + mResourceDatap->mPreferredLocation = LLAssetType::EType(-2); } else { - // create a resource data - LLResourceData* data = NULL; - data = new LLResourceData; - data->mInventoryType = LLInventoryType::IT_NONE; - data->mAssetInfo.mTransactionID.generate(); - data->mAssetInfo.mUuid = data->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID()); - if (BUG_REPORT == mReportType) - { - //data->mAssetInfo.mType = LLAssetType::AT_BUG_REPORT_SCREENSHOT; - data->mAssetInfo.mType = LLAssetType::AT_TEXTURE; - data->mPreferredLocation = LLAssetType::EType(-1); - } - else if (COMPLAINT_REPORT == mReportType) - { - //data->mAssetInfo.mType = LLAssetType::AT_COMPLAINT_REPORT_SCREENSHOT; - data->mAssetInfo.mType = LLAssetType::AT_TEXTURE; - data->mPreferredLocation = LLAssetType::EType(-2); - } - else - { - llwarns << "Unknown LLFloaterReporter type" << llendl; - } - data->mAssetInfo.mCreatorID = gAgentID; - data->mAssetInfo.setName("screenshot_name"); - data->mAssetInfo.setDescription("screenshot_descr"); - - llinfos << "*** Uploading: " << llendl; - llinfos << "Type: " << LLAssetType::lookup(data->mAssetInfo.mType) << llendl; - llinfos << "File: " << filename << llendl; - llinfos << "Dest: " << temp_filename << llendl; - llinfos << "Name: " << data->mAssetInfo.getName() << llendl; - llinfos << "Desc: " << data->mAssetInfo.getDescription() << llendl; - - gAssetStorage->storeAssetData(temp_filename.c_str(), - data->mAssetInfo.mTransactionID, - data->mAssetInfo.mType, - LLFloaterReporter::uploadDoneCallback, - (void*)data, TRUE); + llwarns << "Unknown LLFloaterReporter type" << llendl; + } + mResourceDatap->mAssetInfo.mCreatorID = gAgentID; + mResourceDatap->mAssetInfo.setName("screenshot_name"); + mResourceDatap->mAssetInfo.setDescription("screenshot_descr"); + + // store in VFS + LLVFile::writeFile(upload_data->getData(), + upload_data->getDataSize(), + gVFS, + mResourceDatap->mAssetInfo.mUuid, + mResourceDatap->mAssetInfo.mType); + + // store in the image list so it doesn't try to fetch from the server + LLViewerImage* image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid, TRUE); + image_in_list->createGLTexture(0, raw); + gImageList.addImage(image_in_list); + + // the texture picker then uses that texture + LLTexturePicker* texture = LLUICtrlFactory::getTexturePickerByName(this, "screenshot"); + if (texture) + { + texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid); + texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid); + texture->setCaption("Screenshot"); } + +} + +void LLFloaterReporter::uploadImage() +{ + llinfos << "*** Uploading: " << llendl; + llinfos << "Type: " << LLAssetType::lookup(mResourceDatap->mAssetInfo.mType) << llendl; + llinfos << "UUID: " << mResourceDatap->mAssetInfo.mUuid << llendl; + llinfos << "Name: " << mResourceDatap->mAssetInfo.getName() << llendl; + llinfos << "Desc: " << mResourceDatap->mAssetInfo.getDescription() << llendl; + + gAssetStorage->storeAssetData(mResourceDatap->mAssetInfo.mTransactionID, + mResourceDatap->mAssetInfo.mType, + LLFloaterReporter::uploadDoneCallback, + (void*)mResourceDatap, TRUE); } // static void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result) // StoreAssetData callback (fixed) { - LLResourceData* data = (LLResourceData*)user_data; + LLUploadDialog::modalUploadFinished(); - if(result >= 0) - { - EReportType report_type = UNKNOWN_REPORT; - if (data->mPreferredLocation == -1) - { - report_type = BUG_REPORT; - } - else if (data->mPreferredLocation == -2) - { - report_type = COMPLAINT_REPORT; - } - else - { - llwarns << "Unknown report type : " << data->mPreferredLocation << llendl; - } + LLResourceData* data = (LLResourceData*)user_data; - LLFloaterReporter *self = getReporter(report_type); - if (self) - { - LLTexturePicker* texture = LLUICtrlFactory::getTexturePickerByName(self, "screenshot"); - if (texture) - { - texture->setImageAssetID(uuid); - texture->setDefaultImageAssetID(uuid); - texture->setCaption("Screenshot"); - } - self->mScreenID = uuid; - llinfos << "Got screen shot " << uuid << llendl; - } - } - else // if(result >= 0) + if(result < 0) { LLStringBase<char>::format_map_t args; args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result)); @@ -844,8 +923,31 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, std::string err_msg("There was a problem uploading a report screenshot"); err_msg += " due to the following reason: " + args["[REASON]"]; llwarns << err_msg << llendl; + return; + } + + EReportType report_type = UNKNOWN_REPORT; + if (data->mPreferredLocation == -1) + { + report_type = BUG_REPORT; } - delete data; + else if (data->mPreferredLocation == -2) + { + report_type = COMPLAINT_REPORT; + } + else + { + llwarns << "Unknown report type : " << data->mPreferredLocation << llendl; + } + + LLFloaterReporter *self = getReporter(report_type); + if (self) + { + self->mScreenID = uuid; + llinfos << "Got screen shot " << uuid << llendl; + self->sendReportViaLegacy(self->gatherReport()); + } + self->close(); } diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 795ef45e53..e8483b98ef 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -21,6 +21,7 @@ class LLViewerObject; class LLAgent; class LLToolObjPicker; class LLMeanCollisionData; +struct LLResourceData; // these flags are used to label info requests to the server const U32 BUG_REPORT_REQUEST = 0x01 << 0; @@ -51,7 +52,6 @@ enum EReportType CS_REQUEST_REPORT = 4 }; - class LLFloaterReporter : public LLFloater { @@ -87,11 +87,16 @@ public: static void processRegionInfo(LLMessageSystem* msg); void setPickedObjectProperties(const char *object_name, const char *owner_name); - void uploadScreenshot(); private: + void takeScreenshot(); + void sendReportViaCaps(std::string url); + void uploadImage(); + bool validateReport(); void setReporterID(); - void sendReport(); + LLSD gatherReport(); + void sendReportViaLegacy(const LLSD & report); + void sendReportViaCaps(std::string url, std::string sshot_url, const LLSD & report); void setPosBox(const LLVector3d &pos); void enableControls(BOOL own_avatar); void getObjectInfo(const LLUUID& object_id); @@ -108,6 +113,7 @@ private: BOOL mCopyrightWarningSeen; std::list<LLMeanCollisionData*> mMCDList; LLString mDefaultSummary; + LLResourceData* mResourceDatap; }; #endif diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 34f394610f..c178d0d416 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -163,18 +163,8 @@ BOOL LLFloaterTOS::postBuild() gResponsePtr = LLIamHere::build( this ); LLHTTPClient::get( childGetValue( "real_url" ).asString(), gResponsePtr ); }; - #else - LLTextEditor *Editor = LLUICtrlFactory::getTextEditorByName(this, "tos_text"); - if (Editor) - { - Editor->setHandleEditKeysDirectly( TRUE ); - Editor->setEnabled( FALSE ); - Editor->setReadOnlyFgColor(LLColor4::white); - Editor->setWordWrap(TRUE); - Editor->setFocus(TRUE); - } - childSetValue("tos_text", LLSD(mMessage)); #endif + return TRUE; } diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 938976241b..862dbcf377 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -22,6 +22,7 @@ // newview #include "llagent.h" // todo: remove +#include "llassetuploadresponders.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -38,6 +39,7 @@ #include "llviewerinventory.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" +#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" // busycount #include "viewer.h" // gVFS @@ -1101,13 +1103,31 @@ void LLPreviewGesture::saveIfNeeded() LLInventoryItem* item = getItem(); if (item) { - LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); - LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid); - - const BOOL temp_file = FALSE; - - gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, temp_file); - + std::string agent_url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory"); + std::string task_url = gAgent.getRegion()->getCapability("UpdateGestureTaskInventory"); + if (mObjectUUID.isNull() && !agent_url.empty()) + { + // Saving into agent inventory + LLSD body; + body["item_id"] = mItemUUID; + LLHTTPClient::post(agent_url, body, + new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE)); + } + else if (!mObjectUUID.isNull() && !task_url.empty()) + { + // Saving into task inventory + LLSD body; + body["task_id"] = mObjectUUID; + body["item_id"] = mItemUUID; + LLHTTPClient::post(task_url, body, + new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE)); + } + else if (gAssetStorage) + { + LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); + LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid); + gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE); + } } // If this gesture is active, then we need to update the in-memory diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 6b8cc626ee..154ce5b07c 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -13,6 +13,7 @@ #include "llinventory.h" #include "llagent.h" +#include "llassetuploadresponders.h" #include "llviewerwindow.h" #include "llbutton.h" #include "llinventorymodel.h" @@ -219,6 +220,22 @@ const LLInventoryItem* LLPreviewNotecard::getDragItem() return NULL; } +bool LLPreviewNotecard::hasEmbeddedInventory() +{ + LLViewerTextEditor* editor = NULL; + editor = LLViewerUICtrlFactory::getViewerTextEditorByName( + this, + "Notecard Editor"); + if (!editor) return false; + return editor->hasEmbeddedInventory(); +} + +void LLPreviewNotecard::refreshFromInventory() +{ + lldebugs << "LLPreviewNotecard::refreshFromInventory()" << llendl; + loadAsset(); +} + void LLPreviewNotecard::loadAsset() { // request the asset. @@ -348,7 +365,7 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, LLInventoryItem* item = preview->getItem(); BOOL modifiable = item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); - previewEditor->setEnabled(modifiable); + preview->setEnabled(modifiable); delete[] buffer; preview->mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -453,14 +470,43 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem) LLInventoryItem* item = getItem(); // save it out to database if (item) - { - - LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID, - tid, copyitem); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD, - &onSaveComplete, - (void*)info, - FALSE); + { + std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory"); + std::string task_url = gAgent.getRegion()->getCapability("UpdateNotecardTaskInventory"); + if (mObjectUUID.isNull() && !agent_url.empty()) + { + // Saving into agent inventory + mAssetStatus = PREVIEW_ASSET_LOADING; + setEnabled(FALSE); + LLSD body; + body["item_id"] = mItemUUID; + llinfos << "Saving notecard " << mItemUUID + << " into agent inventory via " << agent_url << llendl; + LLHTTPClient::post(agent_url, body, + new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD)); + } + else if (!mObjectUUID.isNull() && !task_url.empty()) + { + // Saving into task inventory + mAssetStatus = PREVIEW_ASSET_LOADING; + setEnabled(FALSE); + LLSD body; + body["task_id"] = mObjectUUID; + body["item_id"] = mItemUUID; + llinfos << "Saving notecard " << mItemUUID << " into task " + << mObjectUUID << " via " << task_url << llendl; + LLHTTPClient::post(task_url, body, + new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD)); + } + else if (gAssetStorage) + { + LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID, + tid, copyitem); + gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD, + &onSaveComplete, + (void*)info, + FALSE); + } } } return true; diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index 3bb3da5f54..730c56833a 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -50,6 +50,14 @@ public: const LLInventoryItem* getDragItem(); + // return true if there is any embedded inventory. + bool hasEmbeddedInventory(); + + // After saving a notecard, the tcp based upload system will + // change the asset, therefore, we need to re-fetch it from the + // asset system. :( + void refreshFromInventory(); + protected: virtual void loadAsset(); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 479f1b1812..a7d29a6591 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -11,6 +11,7 @@ #include "llpreviewscript.h" #include "llassetstorage.h" +#include "llassetuploadresponders.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -832,6 +833,33 @@ LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, } } +// virtual +void LLPreviewLSL::callbackLSLCompileSucceeded() +{ + llinfos << "LSL Bytecode saved" << llendl; + mScriptEd->mErrorList->addSimpleItem("Compile successful!"); + mScriptEd->mErrorList->addSimpleItem("Save complete."); + closeIfNeeded(); +} + +// virtual +void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) +{ + llinfos << "Compile failed!" << llendl; + + const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); + LLScrollListItem* item = NULL; + for(LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); + line++) + { + item = new LLScrollListItem(); + item->addColumn(line->asString(), err_font); + mScriptEd->mErrorList->addItem(item); + } + mScriptEd->selectFirstError(); + closeIfNeeded(); +} void LLPreviewLSL::loadAsset() { @@ -893,6 +921,17 @@ BOOL LLPreviewLSL::canClose() return mScriptEd->canClose(); } +void LLPreviewLSL::closeIfNeeded() +{ + // Find our window and close it if requested. + getWindow()->decBusyCount(); + mPendingUploads--; + if (mPendingUploads <= 0 && mCloseAfterSave) + { + close(); + } +} + //override the llpreview open which attempts to load asset, load after xml ui made void LLPreviewLSL::open() /*Flawfinder: ignore*/ { @@ -914,152 +953,152 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save) self->saveIfNeeded(); } - // Save needs to compile the text in the buffer. If the compile // succeeds, then save both assets out to the database. If the compile // fails, go ahead and save the text anyway so that the user doesn't // get too fucked. void LLPreviewLSL::saveIfNeeded() { - // llinfos << "LLPreviewLSL::save()" << llendl; - if(!mScriptEd->mEditor->isPristine()) + // llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl; + if(mScriptEd->mEditor->isPristine()) { - mPendingUploads = 0; - mScriptEd->mErrorList->deleteAllItems(); - mScriptEd->mEditor->makePristine(); - - // We need to update the asset information - LLTransactionID tid; - LLAssetID uuid; - tid.generate(); - uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - char uuid_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ - uuid.toString(uuid_string); - char filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(filename, LL_MAX_PATH, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - FILE* fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ - if(!fp) - { - llwarns << "Unable to write to " << filename << llendl; - LLScrollListItem* item = new LLScrollListItem(); - item->addColumn("Error writing to local file. Is your hard drive full?", LLFontGL::sSansSerifSmall); - mScriptEd->mErrorList->addItem(item); - return; - } + return; + } - LLString utf8text = mScriptEd->mEditor->getText(); - //fprintf(fp, "%s|%s\n", LLAssetType::lookup(LLAssetType::AT_LSL_TEXT), - //uuid_string); - //fprintf(fp,"{\n%s}\n", text.c_str()); - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; + mPendingUploads = 0; + mScriptEd->mErrorList->deleteAllItems(); + mScriptEd->mEditor->makePristine(); - // also write it out to the vfs for upload - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_TEXT, LLVFile::APPEND); - S32 size = utf8text.length() + 1; + // save off asset into file + LLTransactionID tid; + tid.generate(); + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string filename = llformat("%s.lsl", filepath.c_str()); - file.setMaxSize(size); - file.write((U8*)utf8text.c_str(), size); + FILE* fp = LLFile::fopen(filename.c_str(), "wb"); + if(!fp) + { + llwarns << "Unable to write to " << filename << llendl; + LLScrollListItem* item = new LLScrollListItem(); + item->addColumn("Error writing to local file. Is your hard drive full?", LLFontGL::sSansSerifSmall); + mScriptEd->mErrorList->addItem(item); + return; + } - LLInventoryItem *inv_item = getItem(); + LLString utf8text = mScriptEd->mEditor->getText(); + fputs(utf8text.c_str(), fp); + fclose(fp); + fp = NULL; - // save it out to database - if(gAssetStorage && inv_item) + LLInventoryItem *inv_item = getItem(); + // save it out to asset server + std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgentInventory"); + if(inv_item) + { + getWindow()->incBusyCount(); + mPendingUploads++; + if (!url.empty()) { - getWindow()->incBusyCount(); - mPendingUploads++; - LLScriptSaveInfo* info = NULL; + uploadAssetViaCaps(url, filename, mItemUUID); + } + else if (gAssetStorage) + { + uploadAssetLegacy(filename, mItemUUID, tid); + } + } +} - LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); +void LLPreviewLSL::uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& item_id) +{ + llinfos << "Update Agent Inventory via capability" << llendl; + LLSD body; + body["item_id"] = item_id; + LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename)); +} - info = new LLScriptSaveInfo(mItemUUID, - descEditor->getText(), - tid); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_LSL_TEXT, &LLPreviewLSL::onSaveComplete, info); - } +void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, + const LLUUID& item_id, + const LLTransactionID& tid) +{ + LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); + LLScriptSaveInfo* info = new LLScriptSaveInfo(item_id, + descEditor->getText(), + tid); + gAssetStorage->storeAssetData(filename.c_str(), tid, + LLAssetType::AT_LSL_TEXT, + &LLPreviewLSL::onSaveComplete, + info); - char dst_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(dst_filename, LL_MAX_PATH, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - char err_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(err_filename, LL_MAX_PATH, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - LLScrollListItem* item = NULL; - const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); - if(!lscript_compile(filename, dst_filename, err_filename, gAgent.isGodlike())) - { - llinfos << "Compile failed!" << llendl; - //char command[256]; - //sprintf(command, "type %s\n", err_filename); - //system(command); + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string dst_filename = llformat("%s.lso", filepath.c_str()); + std::string err_filename = llformat("%s.out", filepath.c_str()); - // load the error file into the error scrolllist - if(NULL != (fp = LLFile::fopen(err_filename, "r"))) /*Flawfinder: ignore*/ + LLScrollListItem* item = NULL; + const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); + if(!lscript_compile(filename.c_str(), + dst_filename.c_str(), + err_filename.c_str(), + gAgent.isGodlike())) + { + llinfos << "Compile failed!" << llendl; + //char command[256]; + //sprintf(command, "type %s\n", err_filename); + //system(command); + + // load the error file into the error scrolllist + FILE* fp = LLFile::fopen(err_filename.c_str(), "r"); + if(fp) + { + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + LLString line; + while(!feof(fp)) { - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - LLString line; - while(!feof(fp)) + fgets(buffer, MAX_STRING, fp); + if(feof(fp)) { - - fgets(buffer, MAX_STRING, fp); - if(feof(fp)) - { - break; - } - else if(!buffer) - { - continue; - } - else - { - line.assign(buffer); - LLString::stripNonprintable(line); - item = new LLScrollListItem(); - item->addColumn(line, err_font); - mScriptEd->mErrorList->addItem(item); - } + break; } - fclose(fp); - mScriptEd->selectFirstError(); - } - } - else - { - llinfos << "Compile worked!" << llendl; - if(gAssetStorage) - { - // move the compiled file into the vfs for transport - FILE* fp = LLFile::fopen(dst_filename, "rb"); /*Flawfinder: ignore*/ - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_BYTECODE, LLVFile::APPEND); - - fseek(fp, 0, SEEK_END); - S32 size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - file.setMaxSize(size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((size = fread(copy_buf, 1, buf_size, fp))) + else if(!buffer) { - file.write(copy_buf, size); + continue; + } + else + { + line.assign(buffer); + LLString::stripNonprintable(line); + item = new LLScrollListItem(); + item->addColumn(line, err_font); + mScriptEd->mErrorList->addItem(item); } - fclose(fp); - fp = NULL; - getWindow()->incBusyCount(); - mPendingUploads++; - LLUUID* this_uuid = new LLUUID(mItemUUID); - gAssetStorage->storeAssetData(tid, - LLAssetType::AT_LSL_BYTECODE, - &LLPreviewLSL::onSaveBytecodeComplete, - (void**)this_uuid); } + fclose(fp); + mScriptEd->selectFirstError(); } - - // get rid of any temp files left lying around - LLFile::remove(filename); - LLFile::remove(err_filename); - LLFile::remove(dst_filename); } + else + { + llinfos << "Compile worked!" << llendl; + if(gAssetStorage) + { + getWindow()->incBusyCount(); + mPendingUploads++; + LLUUID* this_uuid = new LLUUID(mItemUUID); + gAssetStorage->storeAssetData(dst_filename.c_str(), + tid, + LLAssetType::AT_LSL_BYTECODE, + &LLPreviewLSL::onSaveBytecodeComplete, + (void**)this_uuid); + } + } + + // get rid of any temp files left lying around + LLFile::remove(filename.c_str()); + LLFile::remove(err_filename.c_str()); + LLFile::remove(dst_filename.c_str()); } @@ -1333,6 +1372,35 @@ void LLLiveLSLEditor::loadAsset() loadAsset(FALSE); } +// virtual +void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, + const LLUUID& item_id, + bool is_script_running) +{ + lldebugs << "LSL Bytecode saved" << llendl; + mScriptEd->mErrorList->addSimpleItem("Compile successful!"); + mScriptEd->mErrorList->addSimpleItem("Save complete."); + closeIfNeeded(); +} + +// virtual +void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) +{ + lldebugs << "Compile failed!" << llendl; + const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); + LLScrollListItem* item = NULL; + for(LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); + line++) + { + item = new LLScrollListItem(); + item->addColumn(line->asString(), err_font); + mScriptEd->mErrorList->addItem(item); + } + mScriptEd->selectFirstError(); + closeIfNeeded(); +} + void LLLiveLSLEditor::loadAsset(BOOL is_new) { //llinfos << "LLLiveLSLEditor::loadAsset()" << llendl; @@ -1676,18 +1744,16 @@ void LLLiveLSLEditor::saveIfNeeded() // set up the save on the local machine. mScriptEd->mEditor->makePristine(); LLTransactionID tid; - LLAssetID uuid; tid.generate(); - uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - mItem->setAssetUUID(uuid); + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string filename = llformat("%s.lsl", filepath.c_str()); + + mItem->setAssetUUID(asset_id); mItem->setTransactionID(tid); // write out the data, and store it in the asset database - char uuid_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ - uuid.toString(uuid_string); - char filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(filename, LL_MAX_PATH, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - FILE* fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ + FILE* fp = LLFile::fopen(filename.c_str(), "wb"); if(!fp) { llwarns << "Unable to write to " << filename << llendl; @@ -1699,63 +1765,69 @@ void LLLiveLSLEditor::saveIfNeeded() LLString utf8text = mScriptEd->mEditor->getText(); fputs(utf8text.c_str(), fp); fclose(fp); - - LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(this, "running"); + fp = NULL; - // save it out to database - if(gAssetStorage) + // save it out to asset server + std::string url = gAgent.getRegion()->getCapability("UpdateScriptTaskInventory"); + getWindow()->incBusyCount(); + mPendingUploads++; + BOOL is_running = LLUICtrlFactory::getCheckBoxByName(this, "running")->get(); + if (!url.empty()) { - // write it out to the vfs for upload - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_TEXT, LLVFile::APPEND); - S32 size = utf8text.length() + 1; - - file.setMaxSize(size); - file.write((U8*)utf8text.c_str(), size); - - getWindow()->incBusyCount(); - mPendingUploads++; - LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID, - mItem, - runningCheckbox->get()); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_LSL_TEXT, &onSaveTextComplete, (void*)data, FALSE); + uploadAssetViaCaps(url, filename, mObjectID, + mItemID, is_running); } - -#if LL_WINDOWS - // This major hack was inserted because sometimes compilation - // would fail because it couldn't open this file... I decided - // to make a loop until open was successful. This seems to be - // a problem specific to ntfs. - fp = NULL; - const U32 MAX_TRIES = 20; - U32 tries = MAX_TRIES; - while((!fp) && --tries) + else if (gAssetStorage) { - ms_sleep(17); - fp = LLFile::fopen(filename, "r"); /*Flawfinder: ignore*/ - if(!fp) - { - llwarns << "Trying to open the source file " << filename - << " again" << llendl; - } - else - { - fclose(fp); - } + uploadAssetLegacy(filename, object, tid, is_running); } - fp = NULL; -#endif +} + +void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& task_id, + const LLUUID& item_id, + BOOL is_running) +{ + llinfos << "Update Task Inventory via capability" << llendl; + LLSD body; + body["task_id"] = task_id; + body["item_id"] = item_id; + body["is_script_running"] = is_running; + LLHTTPClient::post(url, body, + new LLUpdateTaskInventoryResponder(body, filename)); +} + +void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, + LLViewerObject* object, + const LLTransactionID& tid, + BOOL is_running) +{ + LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID, + mItem, + is_running); + gAssetStorage->storeAssetData(filename.c_str(), tid, + LLAssetType::AT_LSL_TEXT, + &onSaveTextComplete, + (void*)data, + FALSE); + + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string dst_filename = llformat("%s.lso", filepath.c_str()); + std::string err_filename = llformat("%s.out", filepath.c_str()); - char dst_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(dst_filename, LL_MAX_PATH, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - char err_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(err_filename, LL_MAX_PATH, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ LLScrollListItem* item = NULL; const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); - if(!lscript_compile(filename, dst_filename, err_filename, gAgent.isGodlike())) + FILE *fp; + if(!lscript_compile(filename.c_str(), + dst_filename.c_str(), + err_filename.c_str(), + gAgent.isGodlike())) { // load the error file into the error scrolllist llinfos << "Compile failed!" << llendl; - if(NULL != (fp = LLFile::fopen(err_filename, "r"))) /*Flawfinder: ignore*/ + if(NULL != (fp = LLFile::fopen(err_filename.c_str(), "r"))) { char buffer[MAX_STRING]; /*Flawfinder: ignore*/ LLString line; @@ -1797,33 +1869,14 @@ void LLLiveLSLEditor::saveIfNeeded() { llinfos << "LLLiveLSLEditor::saveAsset " << mItem->getAssetUUID() << llendl; - - // move the compiled file into the vfs for transport - FILE* fp = LLFile::fopen(dst_filename, "rb"); /*Flawfinder: ignore*/ - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_BYTECODE, LLVFile::APPEND); - - fseek(fp, 0, SEEK_END); - S32 size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - file.setMaxSize(size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((size = fread(copy_buf, 1, buf_size, fp))) - { - file.write(copy_buf, size); - } - fclose(fp); - fp = NULL; - getWindow()->incBusyCount(); mPendingUploads++; LLLiveLSLSaveData* data = NULL; data = new LLLiveLSLSaveData(mObjectID, mItem, - runningCheckbox->get()); - gAssetStorage->storeAssetData(tid, + is_running); + gAssetStorage->storeAssetData(dst_filename.c_str(), + tid, LLAssetType::AT_LSL_BYTECODE, &LLLiveLSLEditor::onSaveBytecodeComplete, (void*)data); @@ -1832,11 +1885,12 @@ void LLLiveLSLEditor::saveIfNeeded() } // get rid of any temp files left lying around - LLFile::remove(filename); - LLFile::remove(err_filename); - LLFile::remove(dst_filename); + LLFile::remove(filename.c_str()); + LLFile::remove(err_filename.c_str()); + LLFile::remove(dst_filename.c_str()); // If we successfully saved it, then we should be able to check/uncheck the running box! + LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(this, "running"); runningCheckbox->setLabel(ENABLED_RUNNING_CHECKBOX_LABEL); runningCheckbox->setEnabled(TRUE); } @@ -1912,13 +1966,10 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status)); gViewerWindow->alertXml("CompileQueueSaveBytecode", args); } - char uuid_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ - data->mItem->getAssetUUID().toString(uuid_string); - char dst_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ - snprintf(dst_filename, LL_MAX_PATH, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - LLFile::remove(dst_filename); - snprintf(dst_filename, LL_MAX_PATH, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ - LLFile::remove(dst_filename); + + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString()); + std::string dst_filename = llformat("%s.lso", filepath.c_str()); + LLFile::remove(dst_filename.c_str()); delete data; } @@ -1927,6 +1978,16 @@ BOOL LLLiveLSLEditor::canClose() return (mScriptEd->canClose()); } +void LLLiveLSLEditor::closeIfNeeded() +{ + getWindow()->decBusyCount(); + mPendingUploads--; + if (mPendingUploads <= 0 && mCloseAfterSave) + { + close(); + } +} + // static void LLLiveLSLEditor::onLoad(void* userdata) { @@ -1970,6 +2031,13 @@ void LLLiveLSLEditor::hide(const LLUUID& script_id, const LLUUID& object_id) delete instance; } } +// static +LLLiveLSLEditor* LLLiveLSLEditor::find(const LLUUID& script_id, const LLUUID& object_id) +{ + LLUUID xored_id = script_id ^ object_id; + return sInstances.getIfThere(xored_id); +} + // static void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 9b2beb9ce9..5b15fda222 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -116,15 +116,24 @@ class LLPreviewLSL : public LLPreview public: LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid ); + virtual void callbackLSLCompileSucceeded(); + virtual void callbackLSLCompileFailed(const LLSD& compile_errors); /*virtual*/ void open(); /*Flawfinder: ignore*/ protected: virtual BOOL canClose(); + void closeIfNeeded(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void loadAsset(); void saveIfNeeded(); + void uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& item_id); + void uploadAssetLegacy(const std::string& filename, + const LLUUID& item_id, + const LLTransactionID& tid); static void onLoad(void* userdata); static void onSave(void* userdata, BOOL close_after_save); @@ -158,17 +167,33 @@ public: static LLLiveLSLEditor* show(const LLUUID& item_id, const LLUUID& object_id); static void hide(const LLUUID& item_id, const LLUUID& object_id); + static LLLiveLSLEditor* find(const LLUUID& item_id, const LLUUID& object_id); static void processScriptRunningReply(LLMessageSystem* msg, void**); - + + virtual void callbackLSLCompileSucceeded(const LLUUID& task_id, + const LLUUID& item_id, + bool is_script_running); + virtual void callbackLSLCompileFailed(const LLSD& compile_errors); + protected: virtual BOOL canClose(); + void closeIfNeeded(); virtual void draw(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void loadAsset(); void loadAsset(BOOL is_new); void saveIfNeeded(); + void uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& task_id, + const LLUUID& item_id, + BOOL is_running); + void uploadAssetLegacy(const std::string& filename, + LLViewerObject* object, + const LLTransactionID& tid, + BOOL is_running); static void onLoad(void* userdata); static void onSave(void* userdata, BOOL close_after_save); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e6c6576ae1..f8cc68d683 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -833,6 +833,7 @@ BOOL idle_startup() case USERSERVER_SHAKTI: case USERSERVER_DURGA: case USERSERVER_SOMA: + case USERSERVER_VAAK: case USERSERVER_GANGA: case USERSERVER_UMA: { @@ -2557,6 +2558,7 @@ void login_show() LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_GANGA].mLabel, USERSERVER_GANGA ); LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_UMA].mLabel, USERSERVER_UMA ); LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SOMA].mLabel, USERSERVER_SOMA ); + LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_VAAK].mLabel, USERSERVER_VAAK ); } // Callback for when login screen is closed. Option 0 = connect, option 1 = quit. diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9ac566b02b..a638d99381 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -273,6 +273,7 @@ BOOL enable_save_as(void *); // Edit menu void handle_dump_group_info(void *); +void handle_dump_capabilities_info(void *); void handle_dump_focus(void*); void handle_region_dump_settings(void*); @@ -716,6 +717,8 @@ void init_client_menu(LLMenuGL* menu) &handle_region_dump_settings, NULL)); sub->append(new LLMenuItemCallGL("Group Info to Debug Console", &handle_dump_group_info, NULL, NULL)); + sub->append(new LLMenuItemCallGL("Capabilities Info to Debug Console", + &handle_dump_capabilities_info, NULL, NULL)); sub->createJumpKeys(); } @@ -2451,6 +2454,14 @@ void handle_dump_group_info(void *) //llinfos << "insig " << gAgent.mGroupInsigniaID << llendl; } +void handle_dump_capabilities_info(void *) +{ + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + regionp->logActiveCapabilities(); + } +} void handle_dump_focus(void *) { @@ -5689,7 +5700,7 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty llinfos << "Desc: " << desc << llendl; lldebugs << "Folder: " << gInventory.findCategoryUUIDForType(destination_folder_type) << llendl; lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; - std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); + std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); if (!url.empty()) { llinfos << "New Agent Inventory via capability" << llendl; @@ -5703,7 +5714,7 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty std::ostringstream llsdxml; LLSDSerialize::toXML(body, llsdxml); lldebugs << "posting body to capability: " << llsdxml.str() << llendl; - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(uuid, body)); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); } else { diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 189b314e55..f62949cadf 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -46,6 +46,10 @@ LLUserServerData gUserServerDomainName[USERSERVER_COUNT] = "userserver.ganga.lindenlab.com", "https://login.ganga.lindenlab.com/cgi-bin/login.cgi", "http://ganga-secondlife.webdev.lindenlab.com/helpers/" }, + { "Vaak", + "userserver.vaak.lindenlab.com", + "https://login.vaak.lindenlab.com/cgi-bin/login.cgi", + "http://vaak-secondlife.webdev.lindenlab.com/helpers/" }, { "Uma", "userserver.uma.lindenlab.com", "https://login.uma.lindenlab.com/cgi-bin/login.cgi", diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index d461369d02..9eb2d9fcdd 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -23,6 +23,7 @@ enum EUserServerDomain USERSERVER_SHAKTI, USERSERVER_SOMA, USERSERVER_GANGA, + USERSERVER_VAAK, USERSERVER_UMA, USERSERVER_LOCAL, USERSERVER_OTHER, // IP address set via -user or other command line option diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6a20aa4a95..a09ce3011f 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2323,41 +2323,45 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) LLUUID task_id; msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id); LLViewerObject* object = gObjectList.findObject(task_id); - if(object) + if(!object) { - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); - LLFilenameAndTask* ft = new LLFilenameAndTask; - ft->mTaskID = task_id; - msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, MAX_STRING, ft->mFilename); - if(!ft->mFilename[0]) + llwarns << "LLViewerObject::processTaskInv object " + << task_id << " does not exist." << llendl; + return; + } + + msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); + LLFilenameAndTask* ft = new LLFilenameAndTask; + ft->mTaskID = task_id; + msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, MAX_STRING, ft->mFilename); + if(!ft->mFilename[0]) + { + lldebugs << "Task has no inventory" << llendl; + // mock up some inventory to make a drop target. + if(object->mInventory) { - lldebugs << "Task has no inventory" << llendl; - // mock up some inventory to make a drop target. - if(object->mInventory) - { - object->mInventory->clear(); // will deref and delete it - } - else - { - object->mInventory = new InventoryObjectList(); - } - LLPointer<LLInventoryObject> obj; - obj = new LLInventoryObject(object->mID, LLUUID::null, - LLAssetType::AT_CATEGORY, - "Contents"); - object->mInventory->push_front(obj); - object->doInventoryCallback(); - delete ft; - return; + object->mInventory->clear(); // will deref and delete it } - gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename).c_str(), - ft->mFilename, LL_PATH_CACHE, - object->mRegionp->getHost(), - TRUE, - &LLViewerObject::processTaskInvFile, - (void**)ft, - LLXferManager::HIGH_PRIORITY); + else + { + object->mInventory = new InventoryObjectList(); + } + LLPointer<LLInventoryObject> obj; + obj = new LLInventoryObject(object->mID, LLUUID::null, + LLAssetType::AT_CATEGORY, + "Contents"); + object->mInventory->push_front(obj); + object->doInventoryCallback(); + delete ft; + return; } + gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename).c_str(), + ft->mFilename, LL_PATH_CACHE, + object->mRegionp->getHost(), + TRUE, + &LLViewerObject::processTaskInvFile, + (void**)ft, + LLXferManager::HIGH_PRIORITY); } void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code) @@ -2582,6 +2586,18 @@ LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& ass return rv; } +void LLViewerObject::updateViewerInventoryAsset( + const LLViewerInventoryItem* item, + const LLUUID& new_asset) +{ + LLPointer<LLViewerInventoryItem> task_item = + new LLViewerInventoryItem(item); + task_item->setAssetUUID(new_asset); + + // do the internal logic + doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false); +} + void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) { if (getVolume()) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index d8b5a14897..80d3240904 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -363,6 +363,11 @@ public: LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id); S16 getInventorySerial() const { return mInventorySerialNum; } + // These functions does viewer-side only object inventory modifications + void updateViewerInventoryAsset( + const LLViewerInventoryItem* item, + const LLUUID& new_asset); + // This function will make sure that we refresh the inventory. void dirtyInventory(); BOOL isInventoryDirty() { return mInventoryDirty; } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 5235410156..262c7d8ed7 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1260,8 +1260,19 @@ void LLViewerRegion::setSeedCapability(const std::string& url) LLSD capabilityNames = LLSD::emptyArray(); capabilityNames.append("MapLayer"); capabilityNames.append("MapLayerGod"); - capabilityNames.append("NewAgentInventory"); + capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("EventQueueGet"); + capabilityNames.append("UpdateGestureAgentInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); + capabilityNames.append("UpdateScriptAgentInventory"); + capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptTaskInventory"); + capabilityNames.append("SendPostcard"); + capabilityNames.append("ViewerStartAuction"); + capabilityNames.append("ParcelGodReserveForNewbie"); + capabilityNames.append("SendUserReport"); + capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("RequestTextureDownload"); LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this)); } @@ -1304,3 +1315,16 @@ std::string LLViewerRegion::getCapability(const std::string& name) const return iter->second; } +void LLViewerRegion::logActiveCapabilities() const +{ + CapabilityMap::const_iterator iter; + for (iter = mCapabilities.begin(); iter != mCapabilities.end(); iter++) + { + if (!iter->second.empty()) + { + // llinfos << "Active capability is " << iter->first << llendl; + llinfos << iter->first << " URL is " << iter->second << llendl; + } + } +} + diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index b3392baf81..1dc1b3af20 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -169,6 +169,7 @@ public: void setSeedCapability(const std::string& url); void setCapability(const std::string& name, const std::string& url); std::string getCapability(const std::string& name) const; + void logActiveCapabilities() const; const LLHost &getHost() const { return mHost; } const U64 &getHandle() const { return mHandle; } diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 7d04f04528..259fa09309 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -53,6 +53,9 @@ public: LLEmbeddedItems(const LLViewerTextEditor* editor); ~LLEmbeddedItems(); void clear(); + + // return true if there are no embedded items. + bool empty(); void bindEmbeddedChars(const LLFontGL* font); void unbindEmbeddedChars(const LLFontGL* font); @@ -115,6 +118,13 @@ void LLEmbeddedItems::clear() removeEmbeddedItem(*nextiter); } mEmbeddedUsedChars.clear(); + mEmbeddedIndexedChars.clear(); +} + +bool LLEmbeddedItems::empty() +{ + removeUnusedChars(); + return mEmbeddedUsedChars.empty(); } // Inserts a new unique entry @@ -1367,10 +1377,11 @@ S32 LLViewerTextEditor::insertEmbeddedItem( S32 pos, LLInventoryItem* item ) bool LLViewerTextEditor::importStream(std::istream& str) { - LLNotecard nc(MAX_NOTECARD_SIZE); + LLNotecard nc(LLNotecard::MAX_SIZE); bool success = nc.importStream(str); if (success) { + mEmbeddedItemList->clear(); const std::vector<LLPointer<LLInventoryItem> >& items = nc.getItems(); mEmbeddedItemList->addItems(items); // Actually set the text @@ -1396,6 +1407,11 @@ void LLViewerTextEditor::copyInventory(LLInventoryItem* item) item); } +bool LLViewerTextEditor::hasEmbeddedInventory() +{ + return (!(mEmbeddedItemList->empty())); +} + //////////////////////////////////////////////////////////////////////////// BOOL LLViewerTextEditor::importBuffer( const LLString& buffer ) @@ -1406,7 +1422,7 @@ BOOL LLViewerTextEditor::importBuffer( const LLString& buffer ) BOOL LLViewerTextEditor::exportBuffer( LLString& buffer ) { - LLNotecard nc(MAX_NOTECARD_SIZE); + LLNotecard nc(LLNotecard::MAX_SIZE); std::vector<LLPointer<LLInventoryItem> > embedded_items; mEmbeddedItemList->getEmbeddedItemList(embedded_items); diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h index 99e971b33c..de57b68e7d 100644 --- a/indra/newview/llviewertexteditor.h +++ b/indra/newview/llviewertexteditor.h @@ -67,7 +67,14 @@ public: // If this starts a line, you need to prepend a newline. void copyInventory(LLInventoryItem* item); - + + // returns true if there is embedded inventory. + // *HACK: This is only useful because the notecard verifier may + // change the asset if there is embedded inventory. This mechanism + // should be changed to get a different asset id from the verifier + // rather than checking if a re-load is necessary. Phoenix 2007-02-27 + bool hasEmbeddedInventory(); + protected: // Embedded object operations virtual llwchar pasteEmbeddedItem(llwchar ext_char); diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 522e9c9a56..9e85e293d4 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -15,11 +15,13 @@ #include "llquantize.h" #include "llagent.h" +#include "llassetuploadresponders.h" #include "llviewerwindow.h" #include "llfloatercustomize.h" #include "llinventorymodel.h" #include "llviewerimagelist.h" #include "llviewerinventory.h" +#include "llviewerregion.h" #include "llvoavatar.h" #include "llwearable.h" @@ -886,11 +888,28 @@ void LLWearable::saveNewAsset() // save it out to database if( gAssetStorage ) { - LLWearableSaveData* data = new LLWearableSaveData; - data->mType = mType; - gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), - &LLWearable::onSaveNewAssetComplete, - (void*)data); + /* + std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); + if (!url.empty()) + { + llinfos << "Update Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType(getAssetType()); + body["asset_type"] = LLAssetType::lookup(getAssetType()); + body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); + body["name"] = getName(); + body["description"] = getDescription(); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); + } + else + { + } + */ + LLWearableSaveData* data = new LLWearableSaveData; + data->mType = mType; + gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), + &LLWearable::onSaveNewAssetComplete, + (void*)data); } } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 301ab310d9..2c04a34da8 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -324,12 +324,15 @@ class DarwinManifest(ViewerManifest): volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() # Copy everything in to the mounted .dmg - for s,d in {self.get_dst_prefix():("Second Life " + self.args['grid']).strip()+ ".app", - "lsl_guide.html":"Linden Scripting Language Guide.html", - "releasenotes.txt":"Release Notes.txt", - "installers/darwin/mac_image_hidden":".hidden", - "installers/darwin/mac_image_background.tga":"background.tga", - "installers/darwin/mac_image_DS_Store":".DS_Store"}.items(): + # TODO change name of .app once mac_updater can handle it. + for s,d in { + self.get_dst_prefix():"Second Life.app", + "lsl_guide.html":"Linden Scripting Language Guide.html", + "releasenotes.txt":"Release Notes.txt", + "installers/darwin/mac_image_hidden":".hidden", + "installers/darwin/mac_image_background.tga":"background.tga", + "installers/darwin/mac_image_DS_Store":".DS_Store"}.items(): + print "Copying to dmg", s, d self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) |