예제 #1
0
static ZTuple sGetProp(const ZNode& iNode, const string& iPropName)
 	{
 	ZTuple propT;

	if (iPropName == "D:resourcetype")
		{
		if (iNode.CanHaveChildren())
			propT.SetTuple(iPropName, ZTuple().SetNull("D:collection"));
		else
			propT.SetNull(iPropName);
		}
	else if (iPropName == "D:getcontenttype")
		{
		ZTupleValue theValue;
		if (iNode.GetProp("MIMEType", theValue))
			{
			string theMIMEType;
			if (theValue.GetString(theMIMEType))
				propT.SetString(iPropName, theMIMEType);
			}
		}
	else if (iPropName == "D:creationdate")
		{
		ZTupleValue theValue;
		if (iNode.GetProp("TimeCreated", theValue))
			{
			if (ZTime theTime = theValue.GetTime())
				propT.SetString(iPropName, sAsString_WebDAV(theTime));
			}
		}
	else if (iPropName == "D:getlastmodified")
		{
		ZTupleValue theValue;
		if (iNode.GetProp("TimeModified", theValue))
			{
			if (ZTime theTime = theValue.GetTime())
				propT.SetString(iPropName, sAsString_WebDAV(theTime));
			}
		}
	else if (iPropName == "D:getcontentlength")
		{
		ZTupleValue theValue;
		if (iNode.GetProp("ContentLength", theValue))
			{
			int64 theLength;
			if (theValue.GetInt64(theLength))
	 			propT.SetString(iPropName, ZString::sFromUInt64(theLength));
			}
		}

 	return propT;
 	}
예제 #2
0
bool ZWebDAV::sHandle_GET(const ZTrail& iPrefix, ZNode iRoot, const ZStreamR&, const ZStreamW& iStreamW, const ZTuple& iHeader, const ZTrail& iTrail, const ZTuple& iParam)
	{
	ZNode theNode = iRoot.Trail(iTrail);

	ZHTTP::Response r;
	r.Set("date", sAsString_WebDAV(ZTime::sNow()));

	if (iHeader.Has("range"))
		{
		if (const ZLog::S& s = ZLog::S(ZLog::eInfo, "ZWebDAV"))
			s << "GET with range:\n" << iHeader;
		}

	if (theNode.Exists())
		{
		r.SetResult(200);
		if (theNode.CanHaveChildren())
			{
			r.Set("Content-Type", "text/html; charset=\"utf-8\"");
			r.Set("Transfer-Encoding", "chunked");
			r.Send(iStreamW);

			ZHTTP::StreamW_Chunked chunkedStream(iStreamW);
			ZStrimW_StreamUTF8 theStrimW(chunkedStream);
			ZStrimW_ML s(false, theStrimW);
			s.Begin("html");
				s.Begin("title");
					s << theNode.Name();
				s.End("title");
				s.Begin("body");
					for (ZNodeIter i = theNode; i; i.Advance())
						{
						s.Begin("p");
							s.Begin("a");
								if (i.Current().CanHaveChildren())
									{
									s.Attr("href", ZHTTP::sEncodeComponent(i.Current().Name()) + "/");
									s << i.Current().Name() << "/";
									}
								else
									{
									s.Attr("href", ZHTTP::sEncodeComponent(i.Current().Name()));
									s << i.Current().Name();
									}
							s.End("a");
						s.End("p");
						}
				s.End("body");
			
			s.End("html");
			}
		else if (ZRef<ZStreamerRPos> theStreamer = theNode.OpenRPos())
			{
			const ZStreamRPos& theStreamRPos = theStreamer->GetStreamRPos();
			uint64 sentSize = theStreamRPos.GetSize();

			if (ZTupleValue rangeParam = iHeader.GetValue("range"))
				{
				vector<pair<size_t, size_t> > ranges;
				if (!ZHTTP::sOrganizeRanges(sentSize, rangeParam, ranges))
					{
					iStreamW.WriteString("HTTP/1.1 406 Unsatisfiable range\r\n\r\n");
					return false;
					}
				r.SetResult(206, "Partial Content");

				r.Set("Content-Range", ZString::sFormat("bytes %d-%d/%d", ranges.front().first, ranges.front().second - 1, sentSize));

				theStreamRPos.SetPosition(ranges.front().first);
				sentSize = ranges.front().second - ranges.front().first;
				}
			else
				{
				r.SetResult(200);
				}
			
			string theMIMEType = "application/octet-stream";
			ZTupleValue theMIMEValue;
			if (theNode.GetProp("MIMEType", theMIMEValue))
				{
				string asString;
				if (theMIMEValue.GetString(asString))
					theMIMEType = asString;
				}
			r.Set("Content-Type", theMIMEType);

			ZTupleValue theValue;
			if (theNode.GetProp("lastModified", theValue))
				{
				if (ZTime theTime = theValue.GetTime())
					r.Set("Last-Modified", sAsString_WebDAV(theTime));
				}

			r.Set("Content-Transfer-Encoding", "binary");
			r.Set("Content-Length", ZString::sFromUInt64(sentSize));

			r.Send(iStreamW);

			iStreamW.CopyFrom(theStreamRPos, sentSize);
			}
		}
	else
		{
		r.SetResult(404);
		r.Send(iStreamW);
		r.Set("Content-Length", 0);
		}
	return true;
	}
예제 #3
0
static void sSimpleTupleValueToStrim(const ZStrimW& s, const ZTupleValue& iTV,
                                     size_t iLevel, const ZUtil_Tuple::Options& iOptions)
{
    switch (iTV.TypeOf())
    {
    case eZType_Null:
        s.Write("Null");
        break;
    case eZType_Type:
    {
        s.Write("Type(");
        s.Write(ZTypeAsString(iTV.GetType()));
        s.Write(")");
        break;
    }
    case eZType_ID:
    {
        s.Writef("ID(0x%0llX)", iTV.GetID());
        if (iOptions.fIDsHaveDecimalVersionComment)
            s.Writef(" /* %lld */", iTV.GetID());
        break;
    }
    case eZType_Int8:
        s.Writef("int8(%d)", iTV.GetInt8());
        break;
    case eZType_Int16:
        s.Writef("int16(%d)", iTV.GetInt16());
        break;
    case eZType_Int32:
        s.Writef("int32(%d)", iTV.GetInt32());
        break;
    case eZType_Int64:
        s.Writef("int64(0x%0llX)", iTV.GetInt64());
        break;
    case eZType_Bool:
    {
        if (iTV.GetBool())
            s.Write("true");
        else
            s.Write("false");
        break;
    }
    case eZType_Float:
    {
        // 9 decimal digits are necessary and sufficient for single precision IEEE 754.
        // "What Every Computer Scientist Should Know About Floating Point", Goldberg, 1991.
        // <http://docs.sun.com/source/806-3568/ncg_goldberg.html>
        s.Writef("float(%.9g)", iTV.GetFloat());
        break;
    }
    case eZType_Double:
    {
        // 17 decimal digits are necessary and sufficient for double precision IEEE 754.
        s.Writef("double(%.17g)", iTV.GetDouble());
        break;
    }
    case eZType_Time:
    {
        // For the moment I'm just writing times as a count of seconds, putting
        // the broken-out Gregorian version in a comment. Later we can improve
        // the parsing of dates, and then we can write them in human readable form.
        if (ZTime theTime = iTV.GetTime())
        {
            s.Writef("time(%.17g)", theTime.fVal);
            if (iOptions.fTimesHaveUserLegibleComment)
            {
                s << " /*" << ZUtil_Time::sAsStringUTC(theTime, "%Y-%m-%dZ%H:%M:");
                // We've got about 10 significant digits in year (-10,000 to +10,000),
                // month, day, hour, minutes, and seconds, and no more than 17 in a double.
                // To get a leading zero in the seconds' tens column we add 100
                // to the count of seconds, so to get up to 7 digits in the fraction we
                // need to allow ten digits overall.
                s << ZString::sFormat("%.10g", 100.0 + fmod(theTime.fVal, 60)).substr(1);
                s << "*/";
            };
        }
        else
        {
            // We're now allowing empty parens to represent invalid times.
            s.Write("time()");
        }
        break;
    }
    case eZType_Pointer:
        s.Writef("pointer(%08X)", iTV.GetPointer());
        break;
    case eZType_Rect:
    {
        const ZRectPOD& theRect = iTV.GetRect();
        s.Writef("Rect(%d, %d, %d, %d)",
                 theRect.left,
                 theRect.top,
                 theRect.right,
                 theRect.bottom);
        break;
    }
    case eZType_Point:
    {
        const ZPointPOD& thePoint = iTV.GetPoint();
        s.Writef("Point(%d, %d)",
                 thePoint.h,
                 thePoint.v);
        break;
    }
    case eZType_String:
    {
        const string& theString = iTV.GetString();
        if (iOptions.fBreakStrings && iOptions.DoIndentation())
        {
            if (string::npos != theString.find_first_of("\n\r"))
            {
                // We put a newline after the opening """, which will be
                // ignored by sFromStrim, so the first line of theString
                // will be in column zero.
                s << "\"\"\"\n";
                ZStrimU_String strim_String(theString);
                ZStrimR_Boundary strim_Boundary("\"\"\"", strim_String);
                for (;;)
                {
                    s.CopyAllFrom(strim_Boundary);
                    if (!strim_Boundary.HitBoundary())
                    {
                        // We've returned without having hit the boundary, so we're done.
                        break;
                    }
                    strim_Boundary.Reset();

                    // Close the triple quotes.
                    s << "\"\"\"";
                    // A space to separate the triple-quote from the single quote
                    s << " ";
                    // An open quote
                    s << "\"";
                    // Three escaped quotes.
                    s << "\\\"\\\"\\\"";
                    // A close quote.
                    s << "\"";
                    // Another space, for symmetry
                    s << " ";
                    // And re-open triple quotes again.
                    s << "\"\"\"";
                    // With a newline, so the text will again
                    // start in column zero.
                    s << "\n";
                }
                s << "\"\"\"";
                break;
            }
        }
        string delimiter = "\"";
        bool quoteQuotes = true;
        if (string::npos != theString.find('"') && string::npos == theString.find('\''))
        {
            delimiter = "'";
            quoteQuotes = false;
        }

        s.Write(delimiter);

        ZStrimW_Escapify::Options theOptions;
        theOptions.fQuoteQuotes = quoteQuotes;
        theOptions.fEscapeHighUnicode = false;

        ZStrimW_Escapify(theOptions, s).Write(theString);

        s.Write(delimiter);
        break;
    }
    case eZType_RefCounted:
        s.Writef("RefCounted(%08X)", iTV.GetRefCounted().GetObject());
        break;
    case eZType_Raw:
    case eZType_Tuple:
    case eZType_Vector:
    {
        ZDebugStopf(0,
                    ("sSimpleTupleValueToStrim should only be called on simple tuple values"));
        break;
    }
    default:
    {
        ZDebugStopf(0, ("Unrecognized type %d", iTV.TypeOf()));
        break;
    }
    }
}