예제 #1
0
void
MultipartBlobImpl::GetInternalStream(nsIInputStream** aStream,
                                     ErrorResult& aRv)
{
  *aStream = nullptr;

  nsCOMPtr<nsIMultiplexInputStream> stream =
    do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
  if (NS_WARN_IF(!stream)) {
    aRv.Throw(NS_ERROR_FAILURE);
    return;
  }

  uint32_t i;
  for (i = 0; i < mBlobImpls.Length(); i++) {
    nsCOMPtr<nsIInputStream> scratchStream;
    BlobImpl* blobImpl = mBlobImpls.ElementAt(i).get();

    blobImpl->GetInternalStream(getter_AddRefs(scratchStream), aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return;
    }

    aRv = stream->AppendStream(scratchStream);
    if (NS_WARN_IF(aRv.Failed())) {
      return;
    }
  }

  stream.forget(aStream);
}
예제 #2
0
void
MultipartBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
                                          ErrorResult& aRv)
{
  if (!mIsFromNsIFile || mBlobImpls.Length() == 0) {
    BlobImplBase::GetMozFullPathInternal(aFilename, aRv);
    return;
  }

  BlobImpl* blobImpl = mBlobImpls.ElementAt(0).get();
  if (!blobImpl) {
    BlobImplBase::GetMozFullPathInternal(aFilename, aRv);
    return;
  }

  blobImpl->GetMozFullPathInternal(aFilename, aRv);
}
nsresult
nsFileControlFrame::DnDListener::GetBlobImplForWebkitDirectory(nsIDOMFileList* aFileList,
                                                               BlobImpl** aBlobImpl)
{
  *aBlobImpl = nullptr;

  HTMLInputElement* inputElement =
    HTMLInputElement::FromContent(mFrame->GetContent());
  bool webkitDirPicker =
    Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
    inputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory);
  if (!webkitDirPicker) {
    return NS_OK;
  }

  if (!aFileList) {
    return NS_ERROR_FAILURE;
  }

  FileList* files = static_cast<FileList*>(aFileList);
  // webkitdirectory doesn't care about the length of the file list but
  // only about the first item on it.
  uint32_t len = files->Length();
  if (len) {
    File* file = files->Item(0);
    if (file) {
      BlobImpl* impl = file->Impl();
      if (impl && impl->IsDirectory()) {
        RefPtr<BlobImpl> retVal = impl;
        retVal.swap(*aBlobImpl);
        return NS_OK;
      }
    }
  }

  return NS_ERROR_FAILURE;
}
예제 #4
0
파일: row.cpp 프로젝트: 913862627/wt
void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen)
{
	if (varnum < 1 || varnum > mDescrArea->sqld)
		throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range."));
	if (value == 0)
		throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected."));

	int16_t len;
	XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
	switch (var->sqltype & ~1)
	{
		case SQL_TEXT :
			if (ivType == ivString)
			{
				std::string* svalue = (std::string*)value;
				len = (int16_t)svalue->length();
				if (len > var->sqllen) len = var->sqllen;
				strncpy(var->sqldata, svalue->c_str(), len);
				while (len < var->sqllen) var->sqldata[len++] = ' ';
			}
			else if (ivType == ivByte)
			{
				if (userlen > var->sqllen) userlen = var->sqllen;
				memcpy(var->sqldata, value, userlen);
				while (userlen < var->sqllen) var->sqldata[userlen++] = ' ';
			}
			else if (ivType == ivDBKey)
			{
				IBPP::DBKey* key = (IBPP::DBKey*)value;
				key->GetKey(var->sqldata, var->sqllen);
			}
			else if (ivType == ivBool)
			{
				var->sqldata[0] = *(bool*)value ? 'T' : 'F';
				len = 1;
				while (len < var->sqllen) var->sqldata[len++] = ' ';
			}
			else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_VARYING :
			if (ivType == ivString)
			{
				std::string* svalue = (std::string*)value;
				len = (int16_t)svalue->length();
				if (len > var->sqllen) len = var->sqllen;
				*(int16_t*)var->sqldata = (int16_t)len;
				strncpy(var->sqldata+2, svalue->c_str(), len);
			}
			else if (ivType == ivByte)
			{
				if (userlen > var->sqllen) userlen = var->sqllen;
				*(int16_t*)var->sqldata = (int16_t)userlen;
				memcpy(var->sqldata+2, value, userlen);
			}
			else if (ivType == ivBool)
			{
				*(int16_t*)var->sqldata = (int16_t)1;
				var->sqldata[2] = *(bool*)value ? 'T' : 'F';
			}
			else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_SHORT :
			if (ivType == ivBool)
			{
				*(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0);
			}
			else if (ivType == ivInt16)
			{
				*(int16_t*)var->sqldata = *(int16_t*)value;
			}
			else if (ivType == ivInt32)
			{
				if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16)
					throw LogicExceptionImpl("RowImpl::SetValue",
						_("Out of range numeric conversion !"));
				*(int16_t*)var->sqldata = (int16_t)*(int32_t*)value;
			}
			else if (ivType == ivInt64)
			{
				if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16)
					throw LogicExceptionImpl("RowImpl::SetValue",
						_("Out of range numeric conversion !"));
				*(int16_t*)var->sqldata = (int16_t)*(int64_t*)value;
			}
			else if (ivType == ivFloat)
			{
				// This SQL_SHORT is a NUMERIC(x,y), scale it !
				double multiplier = consts::dscales[-var->sqlscale];
				*(int16_t*)var->sqldata =
					(int16_t)floor(*(float*)value * multiplier + 0.5);
			}
			else if (ivType == ivDouble)
			{
				// This SQL_SHORT is a NUMERIC(x,y), scale it !
				double multiplier = consts::dscales[-var->sqlscale];
				*(int16_t*)var->sqldata =
					(int16_t)floor(*(double*)value * multiplier + 0.5);
			}
			else throw WrongTypeImpl("RowImpl::SetValue",  var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_LONG :
			if (ivType == ivBool)
			{
				*(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0;
			}
			else if (ivType == ivInt16)
			{
				*(ISC_LONG*)var->sqldata = *(int16_t*)value;
			}
			else if (ivType == ivInt32)
			{
				*(ISC_LONG*)var->sqldata = *(ISC_LONG*)value;
			}
			else if (ivType == ivInt64)
			{
				if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32)
					throw LogicExceptionImpl("RowImpl::SetValue",
						_("Out of range numeric conversion !"));
				*(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value;
			}
			else if (ivType == ivFloat)
			{
				// This SQL_LONG is a NUMERIC(x,y), scale it !
				double multiplier = consts::dscales[-var->sqlscale];
				*(ISC_LONG*)var->sqldata =
					(ISC_LONG)floor(*(float*)value * multiplier + 0.5);
			}
			else if (ivType == ivDouble)
			{
				// This SQL_LONG is a NUMERIC(x,y), scale it !
				double multiplier = consts::dscales[-var->sqlscale];
				*(ISC_LONG*)var->sqldata =
					(ISC_LONG)floor(*(double*)value * multiplier + 0.5);
			}
			else throw WrongTypeImpl("RowImpl::SetValue",  var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_INT64 :
			if (ivType == ivBool)
			{
				*(int64_t*)var->sqldata = *(bool*)value ? 1 : 0;
			}
			else if (ivType == ivInt16)
			{
				*(int64_t*)var->sqldata = *(int16_t*)value;
			}
			else if (ivType == ivInt32)
			{
				*(int64_t*)var->sqldata = *(int32_t*)value;
			}
			else if (ivType == ivInt64)
			{
				*(int64_t*)var->sqldata = *(int64_t*)value;
			}
			else if (ivType == ivFloat)
			{
				// This SQL_INT64 is a NUMERIC(x,y), scale it !
				double multiplier = consts::dscales[-var->sqlscale];
				*(int64_t*)var->sqldata =
					(int64_t)floor(*(float*)value * multiplier + 0.5);
			}
			else if (ivType == ivDouble)
			{
				// This SQL_INT64 is a NUMERIC(x,y), scale it !
				double multiplier = consts::dscales[-var->sqlscale];
				*(int64_t*)var->sqldata =
					(int64_t)floor(*(double*)value * multiplier + 0.5);
			}
			else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_FLOAT :
			if (ivType != ivFloat || var->sqlscale != 0)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
									_("Incompatible types."));
			*(float*)var->sqldata = *(float*)value;
			break;

		case SQL_DOUBLE :
			if (ivType != ivDouble)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			if (var->sqlscale != 0)
			{
				// Round to scale of NUMERIC(x,y)
				double multiplier = consts::dscales[-var->sqlscale];
				*(double*)var->sqldata =
					floor(*(double*)value * multiplier + 0.5) / multiplier;
			}
			else *(double*)var->sqldata = *(double*)value;
			break;

		case SQL_TIMESTAMP :
			if (ivType != ivTimestamp)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value);
			break;

		case SQL_TYPE_DATE :
			if (ivType != ivDate)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value);
			break;

		case SQL_TYPE_TIME :
			if (ivType != ivTime)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
											_("Incompatible types."));
			encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value);
			break;

		case SQL_BLOB :
			if (ivType == ivBlob)
			{
				BlobImpl* blob = (BlobImpl*)value;
				blob->GetId((ISC_QUAD*)var->sqldata);
			}
			else if (ivType == ivString)
			{
				BlobImpl blob(mDatabase, mTransaction);
				blob.Save(*(std::string*)value);
				blob.GetId((ISC_QUAD*)var->sqldata);
			}
			else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_ARRAY :
			if (ivType != ivArray)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			{
				ArrayImpl* array = (ArrayImpl*)value;
				array->GetId((ISC_QUAD*)var->sqldata);
				// When an array has been affected to a column, we want to reset
				// its ID. This way, the next WriteFrom() on the same Array object
				// will allocate a new ID. This protects against storing the same
				// array ID in multiple columns or rows.
				array->ResetId();
			}
			break;

		default : throw LogicExceptionImpl("RowImpl::SetValue",
						_("The field uses an unsupported SQL type !"));
	}

	if (var->sqltype & 1) *var->sqlind = 0;		// Remove the 0 flag
}
예제 #5
0
파일: row.cpp 프로젝트: 913862627/wt
void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue)
{
	if (varnum < 1 || varnum > mDescrArea->sqld)
		throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range."));

	void* value;
	int len;
	XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);

	// When there is no value (SQL NULL)
	if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0;

	switch (var->sqltype & ~1)
	{
		case SQL_TEXT :
			if (ivType == ivString)
			{
				// In case of ivString, 'void* retvalue' points to a std::string where we
				// will directly store the data.
				std::string* str = (std::string*)retvalue;
				str->erase();
				str->append(var->sqldata, var->sqllen);
				value = retvalue;	// value != 0 means 'not null'
			}
			else if (ivType == ivByte)
			{
				// In case of ivByte, void* retvalue points to an int where we
				// will store the len of the available data
				if (retvalue != 0) *(int*)retvalue = var->sqllen;
				value = var->sqldata;
			}
			else if (ivType == ivDBKey)
			{
				IBPP::DBKey* key = (IBPP::DBKey*)retvalue;
				key->SetKey(var->sqldata, var->sqllen);
				value = retvalue;
			}
			else if (ivType == ivBool)
			{
				mBools[varnum-1] = 0;
				if (var->sqllen >= 1)
				{
					char c = var->sqldata[0];
					if (c == 't' || c == 'T' || c == 'y' || c == 'Y' ||	c == '1')
						mBools[varnum-1] = 1;
				}
				value = &mBools[varnum-1];
			}
			else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_VARYING :
			if (ivType == ivString)
			{
				// In case of ivString, 'void* retvalue' points to a std::string where we
				// will directly store the data.
				std::string* str = (std::string*)retvalue;
				str->erase();
				str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata);
				value = retvalue;
			}
			else if (ivType == ivByte)
			{
				// In case of ivByte, void* retvalue points to an int where we
				// will store the len of the available data
				if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata;
				value = var->sqldata+2;
			}
			else if (ivType == ivBool)
			{
				mBools[varnum-1] = 0;
				len = *(int16_t*)var->sqldata;
				if (len >= 1)
				{
					char c = var->sqldata[2];
					if (c == 't' || c == 'T' || c == 'y' || c == 'Y' ||	c == '1')
						mBools[varnum-1] = 1;
				}
				value = &mBools[varnum-1];
			}
			else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_SHORT :
			if (ivType == ivInt16)
			{
				value = var->sqldata;
			}
			else if (ivType == ivBool)
			{
				if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0;
				else mBools[varnum-1] = 1;
				value = &mBools[varnum-1];
			}
			else if (ivType == ivInt32)
			{
				mInt32s[varnum-1] = *(int16_t*)var->sqldata;
				value = &mInt32s[varnum-1];
			}
			else if (ivType == ivInt64)
			{
				mInt64s[varnum-1] = *(int16_t*)var->sqldata;
				value = &mInt64s[varnum-1];
			}
			else if (ivType == ivFloat)
			{
				// This SQL_SHORT is a NUMERIC(x,y), scale it !
				double divisor = consts::dscales[-var->sqlscale];
				mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor);

				value = &mFloats[varnum-1];
			}
			else if (ivType == ivDouble)
			{
				// This SQL_SHORT is a NUMERIC(x,y), scale it !
				double divisor = consts::dscales[-var->sqlscale];
				mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor;
				value = &mNumerics[varnum-1];
			}
			else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_LONG :
			if (ivType == ivInt32)
			{
				value = var->sqldata;
			}
			else if (ivType == ivBool)
			{
				if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0;
				else mBools[varnum-1] = 1;
				value = &mBools[varnum-1];
			}
			else if (ivType == ivInt16)
			{
				int32_t tmp = *(int32_t*)var->sqldata;
				if (tmp < consts::min16 || tmp > consts::max16)
					throw LogicExceptionImpl("RowImpl::GetValue",
						_("Out of range numeric conversion !"));
				mInt16s[varnum-1] = (int16_t)tmp;
				value = &mInt16s[varnum-1];
			}
			else if (ivType == ivInt64)
			{
				mInt64s[varnum-1] = *(int32_t*)var->sqldata;
				value = &mInt64s[varnum-1];
			}
			else if (ivType == ivFloat)
			{
				// This SQL_LONG is a NUMERIC(x,y), scale it !
				double divisor = consts::dscales[-var->sqlscale];
				mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor);
				value = &mFloats[varnum-1];
			}
			else if (ivType == ivDouble)
			{
				// This SQL_LONG is a NUMERIC(x,y), scale it !
				double divisor = consts::dscales[-var->sqlscale];
				mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor;
				value = &mNumerics[varnum-1];
			}
			else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_INT64 :
			if (ivType == ivInt64)
			{
				value = var->sqldata;
			}
			else if (ivType == ivBool)
			{
				if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0;
				else mBools[varnum-1] = 1;
				value = &mBools[varnum-1];
			}
			else if (ivType == ivInt16)
			{
				int64_t tmp = *(int64_t*)var->sqldata;
				if (tmp < consts::min16 || tmp > consts::max16)
					throw LogicExceptionImpl("RowImpl::GetValue",
						_("Out of range numeric conversion !"));
				mInt16s[varnum-1] = (int16_t)tmp;
				value = &mInt16s[varnum-1];
			}
			else if (ivType == ivInt32)
			{
				int64_t tmp = *(int64_t*)var->sqldata;
				if (tmp < consts::min32 || tmp > consts::max32)
					throw LogicExceptionImpl("RowImpl::GetValue",
						_("Out of range numeric conversion !"));
				mInt32s[varnum-1] = (int32_t)tmp;
				value = &mInt32s[varnum-1];
			}
			else if (ivType == ivFloat)
			{
				// This SQL_INT64 is a NUMERIC(x,y), scale it !
				double divisor = consts::dscales[-var->sqlscale];
				mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor);
				value = &mFloats[varnum-1];
			}
			else if (ivType == ivDouble)
			{
				// This SQL_INT64 is a NUMERIC(x,y), scale it !
				double divisor = consts::dscales[-var->sqlscale];
				mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor;
				value = &mNumerics[varnum-1];
			}
			else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;

		case SQL_FLOAT :
			if (ivType != ivFloat)
				throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			value = var->sqldata;
			break;

		case SQL_DOUBLE :
			if (ivType != ivDouble)
				throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			if (var->sqlscale != 0)
			{
				// Round to scale y of NUMERIC(x,y)
				double multiplier = consts::dscales[-var->sqlscale];
				mNumerics[varnum-1] =
					floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier;
				value = &mNumerics[varnum-1];
			}
			else value = var->sqldata;
			break;

		case SQL_TIMESTAMP :
			if (ivType != ivTimestamp)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata);
			value = retvalue;
			break;

		case SQL_TYPE_DATE :
			if (ivType != ivDate)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata);
			value = retvalue;
			break;

		case SQL_TYPE_TIME :
			if (ivType != ivTime)
				throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
										_("Incompatible types."));
			decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata);
			value = retvalue;
			break;

		case SQL_BLOB :
			if (ivType == ivBlob)
			{
				BlobImpl* blob = (BlobImpl*)retvalue;
				blob->SetId((ISC_QUAD*)var->sqldata);
				value = retvalue;
			}
			else if (ivType == ivString)
			{
				BlobImpl blob(mDatabase, mTransaction);
				blob.SetId((ISC_QUAD*)var->sqldata);
				std::string* str = (std::string*)retvalue;
				blob.Load(*str);
				value = retvalue;
			}
			else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
										_("Incompatible types."));
			break;
			
		case SQL_ARRAY :
			if (ivType != ivArray)
				throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
											_("Incompatible types."));
			{
				ArrayImpl* array = (ArrayImpl*)retvalue;
				array->SetId((ISC_QUAD*)var->sqldata);
				value = retvalue;
			}
			break;

		default : throw LogicExceptionImpl("RowImpl::GetValue",
						_("Found an unknown sqltype !"));
	}

	return value;
}
예제 #6
0
already_AddRefed<BlobImpl>
MultipartBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
                               const nsAString& aContentType,
                               ErrorResult& aRv)
{
  // If we clamped to nothing we create an empty blob
  nsTArray<nsRefPtr<BlobImpl>> blobImpls;

  uint64_t length = aLength;
  uint64_t skipStart = aStart;

  // Prune the list of blobs if we can
  uint32_t i;
  for (i = 0; length && skipStart && i < mBlobImpls.Length(); i++) {
    BlobImpl* blobImpl = mBlobImpls[i].get();

    uint64_t l = blobImpl->GetSize(aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    if (skipStart < l) {
      uint64_t upperBound = std::min<uint64_t>(l - skipStart, length);

      nsRefPtr<BlobImpl> firstBlobImpl =
        blobImpl->CreateSlice(skipStart, upperBound,
                              aContentType, aRv);
      if (NS_WARN_IF(aRv.Failed())) {
        return nullptr;
      }

      // Avoid wrapping a single blob inside an MultipartBlobImpl
      if (length == upperBound) {
        return firstBlobImpl.forget();
      }

      blobImpls.AppendElement(firstBlobImpl);
      length -= upperBound;
      i++;
      break;
    }
    skipStart -= l;
  }

  // Now append enough blobs until we're done
  for (; length && i < mBlobImpls.Length(); i++) {
    BlobImpl* blobImpl = mBlobImpls[i].get();

    uint64_t l = blobImpl->GetSize(aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    if (length < l) {
      nsRefPtr<BlobImpl> lastBlobImpl =
        blobImpl->CreateSlice(0, length, aContentType, aRv);
      if (NS_WARN_IF(aRv.Failed())) {
        return nullptr;
      }

      blobImpls.AppendElement(lastBlobImpl);
    } else {
      blobImpls.AppendElement(blobImpl);
    }
    length -= std::min<uint64_t>(l, length);
  }

  // we can create our blob now
  nsRefPtr<BlobImpl> impl =
    new MultipartBlobImpl(blobImpls, aContentType);
  return impl.forget();
}
예제 #7
0
nsresult
FetchDriver::BasicFetch()
{
  nsAutoCString url;
  mRequest->GetURL(url);
  nsCOMPtr<nsIURI> uri;
  nsresult rv = NS_NewURI(getter_AddRefs(uri),
                 url,
                 nullptr,
                 nullptr);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    return rv;
  }

  nsAutoCString scheme;
  rv = uri->GetScheme(scheme);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    return rv;
  }

  if (scheme.LowerCaseEqualsLiteral("about")) {
    if (url.EqualsLiteral("about:blank")) {
      nsRefPtr<InternalResponse> response =
        new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
      ErrorResult result;
      response->Headers()->Append(NS_LITERAL_CSTRING("content-type"),
                                  NS_LITERAL_CSTRING("text/html;charset=utf-8"),
                                  result);
      MOZ_ASSERT(!result.Failed());
      nsCOMPtr<nsIInputStream> body;
      rv = NS_NewCStringInputStream(getter_AddRefs(body), EmptyCString());
      if (NS_WARN_IF(NS_FAILED(rv))) {
        FailWithNetworkError();
        return rv;
      }

      response->SetBody(body);
      BeginResponse(response);
      return SucceedWithResponse();
    }
    return FailWithNetworkError();
  }

  if (scheme.LowerCaseEqualsLiteral("blob")) {
    nsRefPtr<BlobImpl> blobImpl;
    rv = NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl));
    BlobImpl* blob = static_cast<BlobImpl*>(blobImpl.get());
    if (NS_WARN_IF(NS_FAILED(rv))) {
      FailWithNetworkError();
      return rv;
    }

    nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
    ErrorResult result;
    uint64_t size = blob->GetSize(result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    nsAutoString sizeStr;
    sizeStr.AppendInt(size);
    response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), NS_ConvertUTF16toUTF8(sizeStr), result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    nsAutoString type;
    blob->GetType(type);
    response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), NS_ConvertUTF16toUTF8(type), result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    nsCOMPtr<nsIInputStream> stream;
    blob->GetInternalStream(getter_AddRefs(stream), result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    response->SetBody(stream);
    BeginResponse(response);
    return SucceedWithResponse();
  }

  if (scheme.LowerCaseEqualsLiteral("data")) {
    nsAutoCString method;
    mRequest->GetMethod(method);
    if (method.LowerCaseEqualsASCII("get")) {
      nsresult rv;
      nsCOMPtr<nsIProtocolHandler> dataHandler =
        do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "data", &rv);

      if (NS_WARN_IF(NS_FAILED(rv))) {
        return FailWithNetworkError();
      }

      nsCOMPtr<nsIChannel> channel;
      rv = dataHandler->NewChannel(uri, getter_AddRefs(channel));
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return FailWithNetworkError();
      }

      nsCOMPtr<nsIInputStream> stream;
      rv = channel->Open(getter_AddRefs(stream));
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return FailWithNetworkError();
      }

      // nsDataChannel will parse the data URI when it is Open()ed and set the
      // correct content type and charset.
      nsAutoCString contentType;
      if (NS_SUCCEEDED(channel->GetContentType(contentType))) {
        nsAutoCString charset;
        if (NS_SUCCEEDED(channel->GetContentCharset(charset)) && !charset.IsEmpty()) {
          contentType.AppendLiteral(";charset=");
          contentType.Append(charset);
        }
      } else {
        NS_WARNING("Could not get content type from data channel");
      }

      nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
      ErrorResult result;
      response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, result);
      if (NS_WARN_IF(result.Failed())) {
        FailWithNetworkError();
        return result.StealNSResult();
      }

      response->SetBody(stream);
      BeginResponse(response);
      return SucceedWithResponse();
    }

    return FailWithNetworkError();
  }

  if (scheme.LowerCaseEqualsLiteral("http") ||
      scheme.LowerCaseEqualsLiteral("https") ||
      scheme.LowerCaseEqualsLiteral("app")) {
    return HttpFetch();
  }

  return FailWithNetworkError();
}
예제 #8
0
already_AddRefed<FileSystemEntry>
DataTransferItem::GetAsEntryWithPrincipal(nsIPrincipal* aPrincipal,
                                          ErrorResult& aRv)
{
  RefPtr<File> file = GetAsFileWithPrincipal(aPrincipal, aRv);
  if (NS_WARN_IF(aRv.Failed()) || !file) {
    return nullptr;
  }

  nsCOMPtr<nsIGlobalObject> global;
  // This is annoying, but DataTransfer may have various things as parent.
  nsCOMPtr<EventTarget> target =
    do_QueryInterface(mDataTransfer->GetParentObject());
  if (target) {
    global = target->GetOwnerGlobal();
  } else {
    nsCOMPtr<nsIDOMEvent> event =
      do_QueryInterface(mDataTransfer->GetParentObject());
    if (event) {
      global = event->InternalDOMEvent()->GetParentObject();
    }
  }

  if (!global) {
    return nullptr;
  }

  RefPtr<FileSystem> fs = FileSystem::Create(global);
  RefPtr<FileSystemEntry> entry;
  BlobImpl* impl = file->Impl();
  MOZ_ASSERT(impl);

  if (impl->IsDirectory()) {
    nsAutoString fullpath;
    impl->GetMozFullPathInternal(fullpath, aRv);
    if (aRv.Failed()) {
      aRv.SuppressException();
      return nullptr;
    }

    nsCOMPtr<nsIFile> directoryFile;
    nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(fullpath),
                                        true, getter_AddRefs(directoryFile));
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return nullptr;
    }

    RefPtr<Directory> directory = Directory::Create(global, directoryFile);
    entry = new FileSystemDirectoryEntry(global, directory, fs);
  } else {
    entry = new FileSystemFileEntry(global, file, fs);
  }

  Sequence<RefPtr<FileSystemEntry>> entries;
  if (!entries.AppendElement(entry, fallible)) {
    return nullptr;
  }

  fs->CreateRoot(entries);
  return entry.forget();
}
예제 #9
0
nsresult
FetchDriver::BasicFetch()
{
  nsAutoCString url;
  mRequest->GetURL(url);
  nsCOMPtr<nsIURI> uri;
  nsresult rv = NS_NewURI(getter_AddRefs(uri),
                 url,
                 nullptr,
                 nullptr);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    return rv;
  }

  nsAutoCString scheme;
  rv = uri->GetScheme(scheme);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    return rv;
  }

  if (scheme.LowerCaseEqualsLiteral("about")) {
    if (url.EqualsLiteral("about:blank")) {
      nsRefPtr<InternalResponse> response =
        new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
      ErrorResult result;
      response->Headers()->Append(NS_LITERAL_CSTRING("content-type"),
                                  NS_LITERAL_CSTRING("text/html;charset=utf-8"),
                                  result);
      MOZ_ASSERT(!result.Failed());
      nsCOMPtr<nsIInputStream> body;
      rv = NS_NewCStringInputStream(getter_AddRefs(body), EmptyCString());
      if (NS_WARN_IF(NS_FAILED(rv))) {
        FailWithNetworkError();
        return rv;
      }

      response->SetBody(body);
      BeginResponse(response);
      return SucceedWithResponse();
    }
    return FailWithNetworkError();
  }

  if (scheme.LowerCaseEqualsLiteral("blob")) {
    nsRefPtr<BlobImpl> blobImpl;
    rv = NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl));
    BlobImpl* blob = static_cast<BlobImpl*>(blobImpl.get());
    if (NS_WARN_IF(NS_FAILED(rv))) {
      FailWithNetworkError();
      return rv;
    }

    nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
    ErrorResult result;
    uint64_t size = blob->GetSize(result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    nsAutoString sizeStr;
    sizeStr.AppendInt(size);
    response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), NS_ConvertUTF16toUTF8(sizeStr), result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    nsAutoString type;
    blob->GetType(type);
    response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), NS_ConvertUTF16toUTF8(type), result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    nsCOMPtr<nsIInputStream> stream;
    blob->GetInternalStream(getter_AddRefs(stream), result);
    if (NS_WARN_IF(result.Failed())) {
      FailWithNetworkError();
      return result.StealNSResult();
    }

    response->SetBody(stream);
    BeginResponse(response);
    return SucceedWithResponse();
  }

  if (scheme.LowerCaseEqualsLiteral("data")) {
    nsAutoCString method;
    mRequest->GetMethod(method);
    if (method.LowerCaseEqualsASCII("get")) {
      // Use nsDataHandler directly so that we can extract the content type.
      // XXX(nsm): Is there a way to acquire the charset without such tight
      // coupling with the DataHandler? nsIProtocolHandler does not provide
      // anything similar.
      nsAutoCString contentType, contentCharset, dataBuffer, hashRef;
      bool isBase64;
      rv = nsDataHandler::ParseURI(url,
                                   contentType,
                                   contentCharset,
                                   isBase64,
                                   dataBuffer,
                                   hashRef);
      if (NS_SUCCEEDED(rv)) {
        ErrorResult result;
        nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
        if (!contentCharset.IsEmpty()) {
          contentType.Append(";charset=");
          contentType.Append(contentCharset);
        }

        response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, result);
        if (!result.Failed()) {
          nsCOMPtr<nsIInputStream> stream;
          rv = NS_NewCStringInputStream(getter_AddRefs(stream), dataBuffer);
          if (NS_SUCCEEDED(rv)) {
            response->SetBody(stream);
            BeginResponse(response);
            return SucceedWithResponse();
          }
        }
      }
    }

    return FailWithNetworkError();
  }

  if (scheme.LowerCaseEqualsLiteral("http") ||
      scheme.LowerCaseEqualsLiteral("https") ||
      scheme.LowerCaseEqualsLiteral("app")) {
    return HttpFetch();
  }

  return FailWithNetworkError();
}
  NS_DECL_ISUPPORTS

  NS_IMETHOD CollectReports(nsIHandleReportCallback* aCallback,
                            nsISupports* aData, bool aAnonymize) override
  {
    if (!gDataTable) {
      return NS_OK;
    }

    nsDataHashtable<nsPtrHashKey<BlobImpl>, uint32_t> refCounts;

    // Determine number of URLs per BlobImpl, to handle the case where it's > 1.
    for (auto iter = gDataTable->Iter(); !iter.Done(); iter.Next()) {
      if (iter.UserData()->mObjectType != DataInfo::eBlobImpl) {
        continue;
      }

      BlobImpl* blobImpl = iter.UserData()->mBlobImpl;
      MOZ_ASSERT(blobImpl);

      refCounts.Put(blobImpl, refCounts.Get(blobImpl) + 1);
    }

    for (auto iter = gDataTable->Iter(); !iter.Done(); iter.Next()) {
      nsCStringHashKey::KeyType key = iter.Key();
      DataInfo* info = iter.UserData();

      if (iter.UserData()->mObjectType == DataInfo::eBlobImpl) {
        BlobImpl* blobImpl = iter.UserData()->mBlobImpl;
        MOZ_ASSERT(blobImpl);

        NS_NAMED_LITERAL_CSTRING(desc,
          "A blob URL allocated with URL.createObjectURL; the referenced "
          "blob cannot be freed until all URLs for it have been explicitly "
          "invalidated with URL.revokeObjectURL.");
        nsAutoCString path, url, owner, specialDesc;
        uint64_t size = 0;
        uint32_t refCount = 1;
        DebugOnly<bool> blobImplWasCounted;

        blobImplWasCounted = refCounts.Get(blobImpl, &refCount);
        MOZ_ASSERT(blobImplWasCounted);
        MOZ_ASSERT(refCount > 0);

        bool isMemoryFile = blobImpl->IsMemoryFile();

        if (isMemoryFile) {
          ErrorResult rv;
          size = blobImpl->GetSize(rv);
          if (NS_WARN_IF(rv.Failed())) {
            rv.SuppressException();
            size = 0;
          }
        }

        path = isMemoryFile ? "memory-blob-urls/" : "file-blob-urls/";
        BuildPath(path, key, info, aAnonymize);

        if (refCount > 1) {
          nsAutoCString addrStr;

          addrStr = "0x";
          addrStr.AppendInt((uint64_t)(BlobImpl*)blobImpl, 16);

          path += " ";
          path.AppendInt(refCount);
          path += "@";
          path += addrStr;

          specialDesc = desc;
          specialDesc += "\n\nNOTE: This blob (address ";
          specialDesc += addrStr;
          specialDesc += ") has ";
          specialDesc.AppendInt(refCount);
          specialDesc += " URLs.";
          if (isMemoryFile) {
            specialDesc += " Its size is divided ";
            specialDesc += refCount > 2 ? "among" : "between";
            specialDesc += " them in this report.";
          }
        }

        const nsACString& descString = specialDesc.IsEmpty()
            ? static_cast<const nsACString&>(desc)
            : static_cast<const nsACString&>(specialDesc);
        if (isMemoryFile) {
          aCallback->Callback(EmptyCString(),
              path,
              KIND_OTHER,
              UNITS_BYTES,
              size / refCount,
              descString,
              aData);
        } else {
          aCallback->Callback(EmptyCString(),
              path,
              KIND_OTHER,
              UNITS_COUNT,
              1,
              descString,
              aData);
        }
        continue;
      }

      // Just report the path for the DOMMediaStream or MediaSource.
      nsAutoCString path;
      path = iter.UserData()->mObjectType == DataInfo::eMediaSource
               ? "media-source-urls/" : "dom-media-stream-urls/";
      BuildPath(path, key, info, aAnonymize);

      NS_NAMED_LITERAL_CSTRING(desc,
        "An object URL allocated with URL.createObjectURL; the referenced "
        "data cannot be freed until all URLs for it have been explicitly "
        "invalidated with URL.revokeObjectURL.");

      aCallback->Callback(EmptyCString(), path, KIND_OTHER, UNITS_COUNT, 1,
                          desc, aData);
    }

    return NS_OK;
  }