Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

for http/1.1

  • Loading branch information...
commit 45b2ca8942243571e560de95ac5f1b6bf8b59fad 1 parent 4435501
iptton iptton authored
1,386 graphics.graffle
View
@@ -0,0 +1,1386 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGrafflePro</string>
+ <string>138.33.0.157554</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {780, 740.016}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>CanvasSize</key>
+ <string>{780, 740.016}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2012-01-10 10:18:40 +0800</string>
+ <key>Creator</key>
+ <string>ippan</string>
+ <key>DisplayScale</key>
+ <string>1 0/72 in = 1.0000 in</string>
+ <key>FileType</key>
+ <string>flat</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>40</integer>
+ <key>Info</key>
+ <integer>1</integer>
+ </dict>
+ <key>ID</key>
+ <integer>53</integer>
+ <key>Points</key>
+ <array>
+ <string>{244.488, 395.016}</string>
+ <string>{244.488, 360.016}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>51</integer>
+ <key>Info</key>
+ <integer>2</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>51</integer>
+ </dict>
+ <key>ID</key>
+ <integer>52</integer>
+ <key>Points</key>
+ <array>
+ <string>{244.488, 475.016}</string>
+ <string>{244.488, 440.016}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>50</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{212.988, 395.016}, {63, 45}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>51</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+Connected}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{201.8, 475.016}, {85.3755, 45}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>50</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+Connecting}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>40</integer>
+ <key>Info</key>
+ <integer>3</integer>
+ </dict>
+ <key>ID</key>
+ <integer>48</integer>
+ <key>Points</key>
+ <array>
+ <string>{276.223, 257.957}</string>
+ <string>{297, 297}</string>
+ <string>{275.988, 337.516}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>42</integer>
+ <key>Info</key>
+ <integer>3</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>36</integer>
+ </dict>
+ <key>ID</key>
+ <integer>46</integer>
+ <key>Points</key>
+ <array>
+ <string>{244.488, 239.016}</string>
+ <string>{244.488, 193.016}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>42</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>43</integer>
+ </dict>
+ <key>ID</key>
+ <integer>45</integer>
+ <key>Points</key>
+ <array>
+ <string>{244.488, 646.516}</string>
+ <string>{244.488, 600.016}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>37</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>42</integer>
+ <key>Info</key>
+ <integer>4</integer>
+ </dict>
+ <key>ID</key>
+ <integer>44</integer>
+ <key>Points</key>
+ <array>
+ <string>{212.738, 337.083}</string>
+ <string>{189, 296}</string>
+ <string>{212.724, 257.94}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>40</integer>
+ <key>Info</key>
+ <integer>4</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{212.988, 555.016}, {63, 45}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>43</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+Initial}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{212.988, 239.516}, {63, 36}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>42</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>RoundRect</string>
+ <key>Style</key>
+ <dict/>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+PackageFound}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>50</integer>
+ </dict>
+ <key>ID</key>
+ <integer>41</integer>
+ <key>Points</key>
+ <array>
+ <string>{244.488, 554.516}</string>
+ <string>{244.488, 520.016}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>43</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{212.988, 315.016}, {63, 45}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>40</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+HeaderFound}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{233.988, 647.016}, {21, 21}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>37</integer>
+ <key>Shape</key>
+ <string>Circle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>Group</string>
+ <key>Graphics</key>
+ <array>
+ <dict>
+ <key>Bounds</key>
+ <string>{{233.988, 167.016}, {21, 21}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>35</integer>
+ <key>Shape</key>
+ <string>Circle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{229.488, 162.516}, {30, 30}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>36</integer>
+ <key>Shape</key>
+ <string>Circle</string>
+ <key>Style</key>
+ <dict/>
+ </dict>
+ </array>
+ <key>ID</key>
+ <integer>34</integer>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>8</integer>
+ <key>Info</key>
+ <integer>3</integer>
+ </dict>
+ <key>ID</key>
+ <integer>31</integer>
+ <key>Points</key>
+ <array>
+ <string>{426, 223}</string>
+ <string>{454, 261}</string>
+ <string>{426, 303}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>17</integer>
+ <key>Info</key>
+ <integer>3</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>3</integer>
+ </dict>
+ <key>ID</key>
+ <integer>30</integer>
+ <key>Points</key>
+ <array>
+ <string>{394.5, 205}</string>
+ <string>{394.5, 158.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>17</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>27</integer>
+ <key>Info</key>
+ <integer>1</integer>
+ </dict>
+ <key>ID</key>
+ <integer>29</integer>
+ <key>Points</key>
+ <array>
+ <string>{394.5, 452}</string>
+ <string>{394.5, 405.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>4</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>17</integer>
+ </dict>
+ <key>ID</key>
+ <integer>28</integer>
+ <key>Points</key>
+ <array>
+ <string>{363, 303}</string>
+ <string>{327, 262}</string>
+ <string>{363, 223}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>8</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{363, 360.5}, {63, 45}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>27</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+Initial}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{363, 205}, {63, 36}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>17</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>RoundRect</string>
+ <key>Style</key>
+ <dict/>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+PackageFound}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>8</integer>
+ <key>Info</key>
+ <integer>1</integer>
+ </dict>
+ <key>ID</key>
+ <integer>11</integer>
+ <key>Points</key>
+ <array>
+ <string>{394.5, 360.5}</string>
+ <string>{394.5, 325.5}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>StickArrow</string>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>27</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{363, 280.5}, {63, 45}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>8</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg936\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset134 STHeiti;}
+{\colortbl;\red255\green255\blue255;}
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ri-380\qc
+
+\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
+HeaderFound}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{384, 452.5}, {21, 21}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4</integer>
+ <key>Shape</key>
+ <string>Circle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>Group</string>
+ <key>Graphics</key>
+ <array>
+ <dict>
+ <key>Bounds</key>
+ <string>{{384, 132.5}, {21, 21}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>24</integer>
+ <key>Shape</key>
+ <string>Circle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{379.5, 128}, {30, 30}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>3</integer>
+ <key>Shape</key>
+ <string>Circle</string>
+ <key>Style</key>
+ <dict/>
+ </dict>
+ </array>
+ <key>ID</key>
+ <integer>1</integer>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict/>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>2</integer>
+ <key>ImageCounter</key>
+ <integer>3</integer>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>图层 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>AutoLayout</key>
+ <integer>2</integer>
+ <key>LayoutType</key>
+ <integer>0</integer>
+ <key>LineLength</key>
+ <real>0.10000000149011612</real>
+ <key>circoMinDist</key>
+ <real>1</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>twopi</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiRankSep</key>
+ <real>80.040000915527344</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2012-01-10 10:38:06 +0800</string>
+ <key>Modifier</key>
+ <string>ippan</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>OutlineStyle</key>
+ <string>Brainstorming/Circles</string>
+ <key>PageBreaks</key>
+ <string>NO</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>coded</string>
+ <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgVMCgUoDhg==</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <true/>
+ <key>QuickLookPreview</key>
+ <data>
+ JVBERi0xLjMKJcTl8uXrp/Og0MTGCjUgMCBvYmoKPDwgL0xlbmd0aCA2IDAgUiAvRmls
+ dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGtmsmKJrkRx+/5FPkCnZNacgPjgwf7
+ MLehG3w2ZTemmTKM5/3Bv1As0rdUdQ1jmqJT8UmhiL9iU2T+Ov88/zqv/NvyPh91nf/7
+ r/nv83/mH378Lc0vv82p/fvtZf60LtvMX9quK+X5OFeZvqxpT7Lm61TXbUnrvs/7eix7
+ ht3rXNO6XHvdoKXl2OvRKduVl7wfZY5127kvdb3q9DKX61pyPY95O9mSPedyXsuxpTJS
+ ynJepULRdTPrjnNZy7bNzn0KSkhQTlsXcrLOue+pLPVc2c8lcMoT/V7mr6DzE3/fFK8f
+ Pzco1/nzj6Ca2uCT/BdIvYCJ4TSlkpciCgw4pXIuWdQM5FI9lkOg8HVz2sqyC9Adp4lT
+ WaoAHZoMFNN3XOc4BXfHCalMgsAp5BxwSnlfNgE6cAqKy9n1e5k/Y2ZiZOuMJVVs4cpV
+ DKUuta7NUNZ9WVEc2roUZjDLKNuFule6OABbt3Fa25VqA+BYzlwTRrAt9VpPBEpLOrZr
+ oJzHsh6bGIquEwM783IdlVnGvVNCguLrQk4B3Ljv67lsNaWpXCaBU57oJ4byjj2oWuC1
+ LZvIKTZiyqdyLbto0yl1X4poHHCkbV2q4CniqTDYQ102wTME7hRXa1zncCTn7gAhlUkQ
+ cIScAxyppKUKni7BHBSXs+un9uD0OZ+PZpDx+1szyIeaQeg95f3RDPJ+bwad4nqP60zv
+ Kbi73khlEoTeIeegdz7VDELvKSiP+n3IDOa6qRlMgxlU3PvWDOp+bwb1eDCDmSNpZoCV
+ mt06BXs3rxjXuRkE94DDJZj6OpOzmZ1z3+7NoDol4Aj91AwiwZT9RHeONLWAkLFwG/0y
+ 11xIH3i8kyrppW7Hko8DYt6nKgbPSsKL/JSUj6yU0U7uwEE6m6Szq+xiz5yqSKCj6RdG
+ 25LLKct1ctklLBsrHeguslJ+0tHd8+R0m2VyCn/WuAp9M9N5RONl/rfIho6OzjvhRBaK
+ 7W4SRlBPnwcIG2ESXDLHfTQN2wCzM/hKlvUKXgH63KD3MyhZZgrv9iTRlD2VOsCmBNEy
+ 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
+ zTkZhXZpy5l9AnK+OZBdnNOuu8RQVcLy6Jq0fUXjkIlBC9EjQa663zc7X1GJbeY/rriT
+ Os58bmS3RMeuyhvMlkKDQgtMGKGMk2jyaHoUTnZI8opXk6iBzn1EUxQfWBnyThnhD9pw
+ BkEL+Jw7eBmCIcMActAeZz1QJAE7L940NxVFBGPvOECxAwqo7hF+mWhJ3BOfXYY5PXs/
+ 6rEpU9k9y6W8ejhxuvr42p3XbO2W2t73yTs/Sg55BR/v/YR29vd+8U473kJYKVDIduLL
+ 2lqSEdp7fSlDL5gKMt60lvjKT8Cz4rTwdkZWaqlaCKR3raW1l6p8cyNH7xIwkurFWw0y
+ 0aqkziYIze2GUZ+KqEonUt7MslJYq6yuRmwoSrosPA810aTovFGqtou/L9R6boTSKB1O
+ vuUzL3OUiPpja4mmSPiYTZG3ZOJ1HVr59EkcrH35qA1A/Zob8K0/aOMOMZbhXFxrJzlm
+ ztZBbO/nzN8NbpfFIX9jPJS0rg/S+5GFyi5IgHKHJMeAUehtxud8zJsKF9pn3sTXb7y/
+ 49Ow3+NO3YV+ffTbttOTGySv0ig9n3wY1tz0Ix+EeWTwaIOLeuOMV35R/sTX/hJQ2qdy
+ Po3iddHqTxtF1Al8CsdBWDnmY2KWMW4rMOCv7787bWVDyGK1IUx0mxrS+Uad0reS17jo
+ YJ/6vZvMxu5aNwOXucgrKHGPdmUJKq8itQWnQhUcY9Tdx10g+YheVqD79MG6WD418HrS
+ tnFhHGS+FPGzGraKdVKG//w/pf7e7wplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKMzk3
+ MwplbmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZSAvUGFyZW50IDQgMCBSIC9SZXNv
+ dXJjZXMgNyAwIFIgL0NvbnRlbnRzIDUgMCBSIC9NZWRpYUJveCBbMCAwIDUyNiA3NDAu
+ MDE2XQo+PgplbmRvYmoKNyAwIG9iago8PCAvUHJvY1NldCBbIC9QREYgL1RleHQgXSAv
+ Q29sb3JTcGFjZSA8PCAvQ3MxIDggMCBSIC9DczIgOSAwIFIgPj4gL0ZvbnQgPDwKL0Yx
+ LjEgMTAgMCBSID4+ID4+CmVuZG9iagoxMiAwIG9iago8PCAvTGVuZ3RoIDEzIDAgUiAv
+ TiAzIC9BbHRlcm5hdGUgL0RldmljZVJHQiAvRmlsdGVyIC9GbGF0ZURlY29kZSA+Pgpz
+ dHJlYW0KeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZu
+ NuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731v
+ dt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7
+ d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFki
+ fEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d
+ 9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZ
+ Lg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8w
+ Dh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+
+ KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNX
+ R5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7P
+ LrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwvi
+ YG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8
+ F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEc
+ dod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfE
+ p0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UUKZW5kc3RyZWFtCmVuZG9iagoxMyAw
+ IG9iago3MzcKZW5kb2JqCjggMCBvYmoKWyAvSUNDQmFzZWQgMTIgMCBSIF0KZW5kb2Jq
+ CjE0IDAgb2JqCjw8IC9MZW5ndGggMTUgMCBSIC9OIDEgL0FsdGVybmF0ZSAvRGV2aWNl
+ R3JheSAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGFUk9IFFEc/s02EoSI
+ QYV4iHcKCZUprKyg2nZ1WZVtW5XSohhn37qjszPTm9k1xZMEXaI8dQ+iY3Ts0KGbl6LA
+ rEvXIKkgCDx16PvN7OoohG95O9/7/f1+33tEbZ2m7zspQVRzQ5UrpaduTk2Lgx8pRR3U
+ TlimFfjpYnGMseu5kr+719Zn0tiy3se1dvv2PbWVZWAh6i22txD6IZFmAB+ZnyhlgLPA
+ HZav2D4BPFgOrBrwI6IDD5q5MNPRnHSlsi2RU+aiKCqvYjtJrvv5uca+i7WJg/5cj2bW
+ jr2z6qrRTNS090ShvA+uRBnPX1T2bDUUpw3jnEhDGinyrtXfK0zHEZErEEoGUjVkuZ9q
+ Tp114HUYu126k+P49hClPslgqIm16bKZHYV9AHYqy+wQ8AXo8bJiD+eBe2H/W1HDk8An
+ YT9kh3nWrR/2F65T4HuEPTXgzhSuxfHaih9eLQFD91QjaIxzTcTT1zlzpIjvMdQZmPdG
+ OaYLMXeWqhM3gDthH1mqZgqxXfuu6iXuewJ30+M70Zs5C1ygHElysRXZFNA8CVgUfYuw
+ SQ48Ps4eVeB3qJjAHLmJ3M0o9x7VERtno1KBVnqNV8ZP47nxxfhlbBjPgH6sdtd7fP/p
+ 4xV117Y+PPmNetw5rr2dG1VhVnFlC93/xzKEj9knOabB06FZWGvYduQPmsxMsAwoxH8F
+ Ppf6khNV3NXu7bhFEsxQPixsJbpLVG4p1Oo9g0qsHCvYAHZwksQsWhy4U2u6OXh32CJ6
+ bflNV7Lrhv769nr72vIebcqoKSgTzbNEZpSxW6Pk3Xjb/WaREZ84Or7nvYpayf5JRRA/
+ hTlaKvIUVfRWUNbEb2cOfhu2flw/pef1Qf08CT2tn9Gv6KMRvgx0Sc/Cc1Efo0nwsGkh
+ 4hKgioMz1E5UY40D4inx8rRbZJH9D0AZ/WYKZW5kc3RyZWFtCmVuZG9iagoxNSAwIG9i
+ ago3MDQKZW5kb2JqCjkgMCBvYmoKWyAvSUNDQmFzZWQgMTQgMCBSIF0KZW5kb2JqCjQg
+ MCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9NZWRpYUJveCBbMCAwIDYxMiA3OTJdIC9Db3Vu
+ dCAxIC9LaWRzIFsgMyAwIFIgXSA+PgplbmRvYmoKMTYgMCBvYmoKPDwgL1R5cGUgL0Nh
+ dGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdlcyA0IDAgUiA+PgplbmRvYmoKMiAwIG9i
+ ago8PCAvTGFzdCAxNyAwIFIgL0ZpcnN0IDE4IDAgUiA+PgplbmRvYmoKMTggMCBvYmoK
+ PDwgL1BhcmVudCAxOSAwIFIgL0NvdW50IDAgL0Rlc3QgWyAzIDAgUiAvWFlaIDAgNzQw
+ LjAxNiAwIF0gL1RpdGxlIChyZXF1ZXN0U3RhdGUpCj4+CmVuZG9iagoxOSAwIG9iago8
+ PCA+PgplbmRvYmoKMTcgMCBvYmoKPDwgL1BhcmVudCAxOSAwIFIgL0NvdW50IDAgL0Rl
+ c3QgWyAzIDAgUiAvWFlaIDAgNzQwLjAxNiAwIF0gL1RpdGxlIChyZXF1ZXN0U3RhdGUp
+ Cj4+CmVuZG9iagoyMiAwIG9iago8PCAvTGVuZ3RoIDIzIDAgUiAvTGVuZ3RoMSA1MzI0
+ IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4Ab1YfVhU15l/z7n3nuEbhpnh
+ IiDMMILKACMzfCgxiMwMAQHBbxBRRgWxymoUUfEjamrjamL6bJo0TWtrbNDYJHVA28WY
+ rGnT3afP7ppmN90km026tvsRa2vzbGLS7aaM+zt3ZhCTut2/ei/33PfrvL/zvuc9Z+5h
+ YNuOHkqgA6SQfd3ggJ2MyzSDiH+nd+uG/ggf/1Mi5dSGzbt7I3zyr4nEK309wfURnn6P
+ d2UfBBGeleM9ra9/YFeET5bv5s1b1kX1yT8CP6M/uGtrRE/v4m3/s2B/T4S3Pi/5rdt6
+ onrWTqS9pkAon0T6GR3Y8x7Vht+jq6CJDsxDE73s8yXBZcPwWNizNItsEHB0TiA7fPyO
+ 90Inb8PmneWvrlmTOvdjpijXIKFL5X0Fxrti/6Zb4VsDykfKKvBJhr1UoJ+y6tYAkZoF
+ /VvKRxMaqZWXZX412dhS0tliPG0kWCupeGusBfRCUlgz+BbwTeAXgG4C3Qi6AXQj6CXo
+ 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
+ NdZand8vZxA2zVhrOchdBuXJ2sc/JSiRmUfjbFjgkQ5Y4JgpubptKL9cZkOFlJfy/BQ+
+ lTmbA4t3zO2e4Tc7K1sWlKcHeOua/vkbe8MfjHfVlWYW+hv6X5UZkHWxCihx+BbEPpqI
+ ueHGShMyohE1OQqGxRXdAydyUxBbXd6n33/6W9dPsn/fc3Zo8NxuVrfjNOpveFv7wYOj
+ e7FRM/IgU65I9b0Mv3bEwqJBxCLAPqrL3TWFYfCe+pyK+Y5pqWl5VVn1vLXFXZxeHV/b
+ c/gCfBVREZuD3FnJOZqaZB1juaMpZvUlODUZ+0EKJkFuPd5xD1ZNlTXjHmaTRVyB7Hgr
+ vDavzXklZerMosySotWrA5s3fzk7odpU7GZfrr5ypRr+/VTKrbxV5v2izPuoamOySvHv
+ OrRx8B5ZIVgcWJDO/FJWYfbarLncg5M883LrZxI/18g7M0/Ou8xJOh55CWwv1LZyWfOC
+ NteSpQ09Gwc2/i+aBFG2CmVuZHN0cmVhbQplbmRvYmoKMjMgMCBvYmoKMzM0OQplbmRv
+ YmoKMjEgMCBvYmoKPDwgL1R5cGUgL0ZvbnREZXNjcmlwdG9yIC9Bc2NlbnQgODYwIC9D
+ YXBIZWlnaHQgNzY0IC9EZXNjZW50IC0xNDAgL0ZsYWdzIDMyCi9Gb250QkJveCBbLTIg
+ LTE0MCAxMDExIDg2MF0gL0ZvbnROYW1lIC9QWlVMSlArU1RIZWl0aSAvSXRhbGljQW5n
+ bGUgMCAvU3RlbVYKMCAvTWF4V2lkdGggMTA1MCAvWEhlaWdodCA1NzMgL0ZvbnRGaWxl
+ MiAyMiAwIFIgPj4KZW5kb2JqCjI0IDAgb2JqClsgMzYgMzYgODEzIDM5IDM5IDQ4NSA0
+ MSBbIDY4MyAyMjYgXSA0OSA0OSA1OTIgNjYgNjYgNjgzIDY4IFsgNjQ3IDY4NSA2NTAK
+ XSA3MiA3MiA2NzMgNzQgNzQgMjAwIDc2IFsgNTAyIDIwMCBdIDc5IFsgNjEwIDY1NSBd
+ IDgzIDgzIDMwMSA4NSBbIDMzOSA2MDgKXSBdCmVuZG9iagoyNSAwIG9iago8PCAvTGVu
+ Z3RoIDI2IDAgUiAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAFjYKASYASb
+ wwQkmRlYUMxkReFh47ABBdkZOBg4gTQXEHMDMQ8DL5DkY+AHkgwMAkAsyCAEABBpAKwK
+ ZW5kc3RyZWFtCmVuZG9iagoyNiAwIG9iago1OQplbmRvYmoKMjAgMCBvYmoKPDwgL1R5
+ cGUgL0ZvbnQgL1N1YnR5cGUgL0NJREZvbnRUeXBlMiAvQmFzZUZvbnQgL1BaVUxKUCtT
+ VEhlaXRpIC9DSURTeXN0ZW1JbmZvCjw8IC9SZWdpc3RyeSAoQWRvYmUpIC9PcmRlcmlu
+ ZyAoR0IxKSAvU3VwcGxlbWVudCAyID4+IC9Gb250RGVzY3JpcHRvciAyMSAwIFIKL1cg
+ MjQgMCBSIC9EVyAxMDAwIC9DSURUb0dJRE1hcCAyNSAwIFIgPj4KZW5kb2JqCjEwIDAg
+ b2JqCjw8IC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMCAvRW5jb2RpbmcgL0lkZW50
+ aXR5LUggL0Jhc2VGb250IC9QWlVMSlArU1RIZWl0aQovRGVzY2VuZGFudEZvbnRzIFsg
+ MjAgMCBSIF0gPj4KZW5kb2JqCjI3IDAgb2JqCihNYWMgT1MgWCAxMC42LjggUXVhcnR6
+ IFBERkNvbnRleHQpCmVuZG9iagoyOCAwIG9iagooRDoyMDEyMDExMDAyMzg0N1owMCcw
+ MCcpCmVuZG9iagoxIDAgb2JqCjw8IC9Qcm9kdWNlciAyNyAwIFIgL0NyZWF0aW9uRGF0
+ ZSAyOCAwIFIgL01vZERhdGUgMjggMCBSID4+CmVuZG9iagp4cmVmCjAgMjkKMDAwMDAw
+ MDAwMCA2NTUzNSBmIAowMDAwMDEwOTI1IDAwMDAwIG4gCjAwMDAwMDYyMTYgMDAwMDAg
+ biAKMDAwMDAwNDA4OSAwMDAwMCBuIAowMDAwMDA2MDY3IDAwMDAwIG4gCjAwMDAwMDAw
+ MjIgMDAwMDAgbiAKMDAwMDAwNDA2OSAwMDAwMCBuIAowMDAwMDA0MTk3IDAwMDAwIG4g
+ CjAwMDAwMDUxNjcgMDAwMDAgbiAKMDAwMDAwNjAzMSAwMDAwMCBuIAowMDAwMDEwNzA1
+ IDAwMDAwIG4gCjAwMDAwMDAwMDAgMDAwMDAgbiAKMDAwMDAwNDMwNyAwMDAwMCBuIAow
+ MDAwMDA1MTQ3IDAwMDAwIG4gCjAwMDAwMDUyMDMgMDAwMDAgbiAKMDAwMDAwNjAxMSAw
+ MDAwMCBuIAowMDAwMDA2MTUwIDAwMDAwIG4gCjAwMDAwMDYzODcgMDAwMDAgbiAKMDAw
+ MDAwNjI2NCAwMDAwMCBuIAowMDAwMDA2MzY1IDAwMDAwIG4gCjAwMDAwMTA0OTEgMDAw
+ MDAgbiAKMDAwMDAwOTk0OCAwMDAwMCBuIAowMDAwMDA2NDg4IDAwMDAwIG4gCjAwMDAw
+ MDk5MjcgMDAwMDAgbiAKMDAwMDAxMDE2OCAwMDAwMCBuIAowMDAwMDEwMzM3IDAwMDAw
+ IG4gCjAwMDAwMTA0NzIgMDAwMDAgbiAKMDAwMDAxMDgzMSAwMDAwMCBuIAowMDAwMDEw
+ ODgzIDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgMjkgL1Jvb3QgMTYgMCBSIC9JbmZv
+ IDEgMCBSIC9JRCBbIDxiOTQzNmRmNzlhN2M1ZTQwNWU2MDRjNDEzNTQwZmM1Yz4KPGI5
+ NDM2ZGY3OWE3YzVlNDA1ZTYwNGM0MTM1NDBmYzVjPiBdID4+CnN0YXJ0eHJlZgoxMTAw
+ MAolJUVPRgoxIDAgb2JqCjw8L0F1dGhvciAoaXBwYW4pL0NyZWF0aW9uRGF0ZSAoRDoy
+ MDEyMDExMDAyMTgwMFopL0NyZWF0b3IgKE9tbmlHcmFmZmxlIFByb2Zlc3Npb25hbCA1
+ LjMuNikvTW9kRGF0ZSAoRDoyMDEyMDExMDAyMzgwMFopL1Byb2R1Y2VyIDI3IDAgUiAv
+ VGl0bGUgKGdyYXBoaWNzKT4+CmVuZG9iagp4cmVmCjEgMQowMDAwMDExNzM4IDAwMDAw
+ IG4gCnRyYWlsZXIKPDwvSUQgWzxiOTQzNmRmNzlhN2M1ZTQwNWU2MDRjNDEzNTQwZmM1
+ Yz4gPGI5NDM2ZGY3OWE3YzVlNDA1ZTYwNGM0MTM1NDBmYzVjPl0gL0luZm8gMSAwIFIg
+ L1ByZXYgMTEwMDAgL1Jvb3QgMTYgMCBSIC9TaXplIDI5Pj4Kc3RhcnR4cmVmCjExOTA5
+ CiUlRU9GCg==
+ </data>
+ <key>QuickLookThumbnail</key>
+ <data>
+ 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
+ </data>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>requestState</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array/>
+ <key>Frame</key>
+ <string>{{86, 157}, {1074, 804}}</string>
+ <key>ListView</key>
+ <false/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>138</integer>
+ <key>VisibleRegion</key>
+ <string>{{1, 10}, {779, 695}}</string>
+ <key>Zoom</key>
+ <real>1</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>requestState</string>
+ <real>1</real>
+ <real>0.0</real>
+ </array>
+ </array>
+ </dict>
+ <key>saveQuickLookFiles</key>
+ <string>YES</string>
+</dict>
+</plist>
7 qiconnectiondata.h
View
@@ -31,7 +31,7 @@ class QiConnectionData {
setResponseRawData(p.responseRawData);
}
- int socketId;
+ long id;
int number;
int returnCode;
QString protocol;
@@ -46,16 +46,21 @@ class QiConnectionData {
QByteArray unChunkResponse;
QByteArray requestRawDataToSend;
+ QByteArray requestBody;
+
+ QByteArray responseBody;
void setRequestHeader(QByteArray name,QByteArray value);
void setRequestHeader(QByteArray headerBa);
+ bool appendRequestBody(QByteArray newContent);
QByteArray getRequestHeader(QByteArray name)const;
QByteArray getRequestHeader()const;
QByteArray getRequestBody()const;
void setResponseHeader(QByteArray header);
void setResponseBody(QByteArray body);
+ bool appendResponseBody(QByteArray newContent);
QByteArray getResponseHeader(QByteArray name)const;
QByteArray getResponseHeader()const;
QByteArray getResponseBody()const;
59 qiconnectiondatadata.cpp
View
@@ -2,8 +2,9 @@
#include <QDebug>
#include <QStringList>
-QiConnectionData::QiConnectionData(int socketDescriptor):socketId(socketDescriptor){
- qDebug()<<"PipeData contructed:"<<socketId;
+QiConnectionData::QiConnectionData(int socketDescriptor){
+ qDebug()<<"PipeData contructed:";
+ id=-1;
returnCode = -1;
}
@@ -83,6 +84,9 @@ void QiConnectionData::setRequestHeader(QByteArray header){
allRequestHeaders["Host"] = value;
allRequestHeaders["Port"] = "80";
}
+
+ host = allRequestHeaders["Host"];
+ port = allRequestHeaders["Port"].toInt();
}else{
allRequestHeaders[name] = value;
}
@@ -168,7 +172,58 @@ QByteArray QiConnectionData::getRequestBody()const{
return QByteArray();
}
+bool QiConnectionData::appendResponseBody(QByteArray newContent){
+ responseBody.append(newContent);
+ if(this->getResponseHeader("Transfer-Encoding").toLower() == "chunked"){
+ // TODO .. move to single function
+ QByteArray theBody = responseBody;
+ //theBody.replace("\r\n","\n");
+ long i=0;
+ long l=theBody.length();
+ while(i<=l){//need to valid chunk here?
+ qDebug()<<"chunked:"<<i<<" "<<l;
+ int beginOfLength=theBody.indexOf('\n',i);
+ if(beginOfLength == -1){
+ beginOfLength = theBody.indexOf('\r\n',i);
+ }
+ if(beginOfLength==-1){
+ return false;
+ }
+ int endOfLength = theBody.indexOf('\n',beginOfLength);
+ if(endOfLength==-1){
+ endOfLength = theBody.indexOf('\r\n',beginOfLength);
+ if(endOfLength == -1){
+ return false;
+ }
+ }
+ bool isChunkValid;
+ int chunkSize = theBody.mid(beginOfLength,endOfLength-beginOfLength).toInt(&isChunkValid,16);
+ if(chunkSize==0){
+ return true;
+ }
+ // don't do this until comfirm reponse done
+ /*
+ if(chunkSize+endOfLength+1<=l){
+ connectionData->unChunkResponse.append(theBody.mid(endOfLength+1,chunkSize));
+ }
+ */
+ if(!isChunkValid){
+ return false;
+ }
+ i = chunkSize+endOfLength+1;
+ if(i>l){
+ return false;
+ }
+ }
+ }else{
+ return (this->getResponseHeader("Content-Length").toLong() <= responseBody.length());
+ }
+}
+bool QiConnectionData::appendRequestBody(QByteArray newContent){
+ requestBody.append(newContent);
+ requestRawDataToSend.append(newContent);
+}
void QiConnectionData::setRequestRawData(QByteArray request){//only for copy Ctor
2  qiddlerpipetablemodel.cpp
View
@@ -89,7 +89,7 @@ void QiddlerPipeTableModel::addItem(ConnectionData_ptr p){
this->beginInsertRows(index(pipeNumber-1, 0),pipeNumber-1,pipeNumber-1);
//TODO thread safe?
- pipesMap.value(p1->socketId,p1);
+ pipesMap.value(p1->id,p1);
pipesVector.append(p1);
//QModelIndex index1 = index(pipeNumber-1, 0);
285 qipipe.cpp
View
@@ -10,9 +10,12 @@
#include <QDebug>
#include <QNetworkProxy>
#include <QTcpSocket>
+#ifdef Q_OS_WIN
#include "qiwinhttp.h"
+#endif
#include <QByteArray>
#include <qglobal.h>
+#include "qiproxyserver.h"
static void isInMain(QString info){
if(QThread::currentThread() == QApplication::instance()->thread()){
@@ -34,8 +37,8 @@ QiPipe::~QiPipe(){
void QiPipe::run(){
qp = new QiPipe_Private(_socketDescriptor);
connect(qp,SIGNAL(connected(ConnectionData_ptr)),this,SIGNAL(connected(ConnectionData_ptr)));
- connect(qp,SIGNAL(completed(ConnectionData_ptr)),this,SIGNAL(completed(ConnectionData_ptr)));
- connect(qp,SIGNAL(error(ConnectionData_ptr)),this,SIGNAL(error(ConnectionData_ptr)));
+ connect(qp,SIGNAL(finishSuccess(ConnectionData_ptr)),this,SIGNAL(completed(ConnectionData_ptr)));
+ connect(qp,SIGNAL(finishedWithError(ConnectionData_ptr)),this,SIGNAL(error(ConnectionData_ptr)));
}
//===========QiPipe_Private
QiPipe_Private::QiPipe_Private(int descriptor):requestSocket(NULL),responseSocket(NULL){
@@ -45,11 +48,6 @@ QiPipe_Private::QiPipe_Private(int descriptor):requestSocket(NULL),responseSocke
// setup request socket
requestSocket = new QTcpSocket();
-
- connectionData = QSharedPointer<QiConnectionData>(new QiConnectionData);
- //connectionArray.push_back(connectionData);
- connectionData->socketId = descriptor;
-
connect(requestSocket,SIGNAL(readyRead()),this,SLOT(onRequestReadReady()));
connect(requestSocket,SIGNAL(disconnected()),this,SLOT(onRequestClose()));
connect(requestSocket,SIGNAL(aboutToClose()),this,SLOT(onRequestClose()));
@@ -81,64 +79,75 @@ void QiPipe_Private::onRequestReadReady(){
QMutexLocker locker(&mutex);
Q_UNUSED(locker);
- //isInMain("onRequestReadReady");
-
QByteArray newReqData = requestSocket->readAll();
//qDebug()<<"onRequestReady:"<<pipeData->socketId<<" newContent:"<<newReqData;
- //update raw data?
- requestRawData.append(newReqData);
+ //update request buffer
+ requestBuffer.append(newReqData);
parseRequest(newReqData);
}
+
+// 检查请求数据中是否有header,如果有header则检查请求包是否完整,并重置requestBuffer
void QiPipe_Private::parseRequest(const QByteArray &newContent){
- if(requestState != HeaderFound){// no header parse one more time
- parseRequestHeader(newContent);
- }
- if(requestState != HeaderFound){// stile no request header return
- return;
- }else{// check if go whole request package
- QByteArray contentLenght = connectionData->getRequestHeader("Content-Length");
- requestContentLength = contentLenght.toInt();
- if(requestContentLength == 0){
- // no body to send
- requestState = PackageFound;
- }else{
- // need body
- qDebug()<<"length="<<requestContentLength<<" ba="<<contentLenght;
- int bufferBodyLength = requestRawData.length() - (requestHeaderSpliterSize + requestHeaderSpliterIndex);
- requestBodyRemain = requestContentLength - bufferBodyLength;
- if(requestBodyRemain <= 0){
- requestState = PackageFound;
- }
+ if(requestState != HeaderFound){// no header, parse one more time ( state = Initial || PackageFound
+ parseRequestHeader(newContent);//如果获取新header,则放入bufferConnectionArray
+ if(requestState != HeaderFound){
+ return;
}
}
// parse body
// is need to count request length?
- if(responseState == Connected){
- connectionData->requestRawDataToSend.append(newContent);
- responseSocket->write(connectionData->requestRawDataToSend);
- responseSocket->flush();
+ // 检查是否已获取所有数据
+ QByteArray contentLenght = currentConnectionData->getRequestHeader("Content-Length");
+ requestContentLength = contentLenght.toInt();
+ if(requestContentLength == 0){
+ // no body to send
+ requestState = PackageFound;
}else{
- if(responseState != BodyParsing){//TODO...
+ // need body
+ qDebug()<<"req content-length="<<requestContentLength<<" remain="<<requestBodyRemain;
+ int bufferBodyLength = requestBuffer.length() - (requestHeaderSpliterSize + requestHeaderSpliterIndex);
+ requestBodyRemain = requestContentLength - bufferBodyLength;
+ if(requestBodyRemain <= 0){
+ requestState = PackageFound;
+ }
+ //TODO?
+ }
+ if(responseState == Initial && requestState!= PackageFound){
+ //为后续逻辑简化,第一个请求仅当收到一个完整的包才开始发送
+ return;
+ }
+ if(responseState != Initial && responseState != Connecting){
+ //同一个socket中发起n个请求的情况
+ //条件是:当第二个同域请求发起时,有已经连接成功并返回数据的数据
+ //所以这里可以简单处理
+ if(currentConnectionData->getRequestHeader("Host") == "127.0.0.1" && currentConnectionData->getRequestHeader("Port")=="8889"){//避免死循环
+ requestSocket->abort();
+ emit(finishSuccess(currentConnectionData));
+ return;
}
- responseState = Initial;
- responseRawData.clear();
- connectionData->requestRawDataToSend.append(requestRawData.mid(requestHeaderSpliterIndex+requestHeaderSpliterSize));
- //QString reqSig = connectionData->requestMethod+" "+connectionData->path+" "+connectionData->protocol;
- connectionData->host = connectionData->getRequestHeader("Host");
- if(connectionData->getRequestHeader("Host") == "127.0.0.1" && connectionData->getRequestHeader("Port")=="8889"){//避免死循环
+ responseSocket->write(newContent);
+ responseSocket->flush();
+ }else if(responseState == Initial){
+ if(!currentSendingConnectionData){
+ currentSendingConnectionData = bufferConnectionArray.at(0);
+ bufferConnectionArray.remove(0);
+ }
+
+ if(currentConnectionData->getRequestHeader("Host") == "127.0.0.1" && currentConnectionData->getRequestHeader("Port")=="8889"){//避免死循环
//TODO
QByteArray byteToWrite;
- QString s = "hello Qiddler";
+ QString s = "hello script<script src='a7.js'></a><script src='a6.js'></a><script src='a5.js'></a><script src='a4.js'></a><script src='a3.js'></a><script src='a2.js'></a>";
int count = s.length();
byteToWrite.append(QString("HTTP/1.1 200 OK\r\nServer: Qiddler\r\nContent-Type: text/html\r\nContent-Length: %1\r\n\r\n").arg(count));
byteToWrite.append(s);
requestSocket->write(byteToWrite);
requestSocket->flush();
requestSocket->abort();
- emit(completed(connectionData));
+ emit(finishSuccess(currentConnectionData));
return;
}else{
+ responseState = Connecting;
responseSocket = new QTcpSocket();
connect(responseSocket,SIGNAL(connected()),SLOT(onResponseConnected()));
connect(responseSocket,SIGNAL(readyRead()),SLOT(onResponseReadReady()));
@@ -156,43 +165,61 @@ void QiPipe_Private::parseRequest(const QByteArray &newContent){
}
#endif
- qDebug()<<"CONNECT TO "<<connectionData->getRequestHeader("Host")<<" "<<connectionData->getRequestHeader("Port");
+ qDebug()<<"CONNECT TO "<<currentConnectionData->getRequestHeader("Host")<<" "<<currentConnectionData->getRequestHeader("Port");
//responseSocket->setProxy(QNetworkProxy(QNetworkProxy::HttpProxy,"127.0.0.1",8888));
- responseSocket->connectToHost(connectionData->getRequestHeader("Host"),connectionData->getRequestHeader("Port").toInt());
+ responseSocket->connectToHost(currentConnectionData->getRequestHeader("Host"),currentConnectionData->getRequestHeader("Port").toInt());
}
}
}
+
+
void QiPipe_Private::parseRequestHeader(const QByteArray &newContent){
Q_UNUSED(newContent);
QByteArray header;
- int indexOfRN = requestRawData.indexOf(QByteArray("\r\n\r\n"));
- int indexOfN = requestRawData.indexOf(QByteArray("\n\n"));
+ int indexOfRN = requestBuffer.indexOf(QByteArray("\r\n\r\n"));
+ int indexOfN = requestBuffer.indexOf(QByteArray("\n\n"));
if(indexOfRN!=-1){
requestHeaderSpliterSize = 4;
requestHeaderSpliterIndex = indexOfRN;
- header = requestRawData.left(indexOfRN);
}else if(indexOfN!=-1){
requestHeaderSpliterSize = 2;
requestHeaderSpliterIndex = indexOfN;
- header = requestRawData.left(indexOfN);
}else{
return;
}
+ header = requestBuffer.left(requestHeaderSpliterIndex);
+
+ //cut header part from buffer
+ if(requestBuffer.size()>=requestHeaderSpliterIndex+requestHeaderSpliterSize){
+ requestBuffer.remove(0,requestHeaderSpliterIndex+requestHeaderSpliterSize);
+ }else{
+ // seems will never enter here
+ Q_ASSERT_X(false,"parseRequestHeader","invalid header length?");
+ requestBuffer.clear();
+ }
//TODO use setRequestState
requestState = HeaderFound;
// create new QiConnectionData (will sharedpoiter do clear for old pointer? anwser:YES)
- connectionData = QSharedPointer<QiConnectionData>(new QiConnectionData());
- connectionData->setRequestHeader(header);
- emit connected(connectionData);
+
+ ConnectionData_ptr newConnectionData = ConnectionData_ptr(new QiConnectionData());
+ newConnectionData->setRequestHeader(header);
+ newConnectionData->id = QiProxyServer::nextConnectionId();
+ currentConnectionData = newConnectionData;
+ bufferConnectionArray.append(newConnectionData);
+
+ emit connected(newConnectionData);
}
+
void QiPipe_Private::onRequestError(){
- emit(error(connectionData));
+ emit finishedWithError(currentConnectionData);
}
+
+
void QiPipe_Private::onResponseConnected(){
// need?
@@ -201,23 +228,25 @@ void QiPipe_Private::onResponseConnected(){
responseState = Connected;
// save the server ip address
- connectionData->serverIP = responseSocket->peerAddress().toString();
+ currentSendingConnectionData->serverIP = responseSocket->peerAddress().toString();
// emit connect signal
//qDebug()<<"send this:\n"<<responseSocket->peerName()<<responseSocket->peerPort()<<connectionData->requestRawDataToSend;
- qint64 n = responseSocket->write(connectionData->requestRawDataToSend);
- connectionData->requestRawDataToSend.remove(0,n);
+ while(currentSendingConnectionData->requestRawDataToSend.size()>0){
+ qint64 n = responseSocket->write(currentSendingConnectionData->requestRawDataToSend);
+ responseSocket->flush();
+ if(n==-1){
+ qDebug()<<"write error !!!!!";
+ break;
+ }
+ currentSendingConnectionData->requestRawDataToSend.remove(0,n);
+ }
}
+
+
void QiPipe_Private::onResponseReadReady(){
QMutexLocker locker(&mutex);
QByteArray ba = responseSocket->readAll();
- responseRawData.append(ba);
- if(responseState == Connected){
- responseState = BodyParsing;
- }
- //qDebug()<<ba;
- //write back to request
- //TODO check if the socket opening..
requestSocket->write(ba);
requestSocket->flush();
@@ -226,37 +255,43 @@ void QiPipe_Private::onResponseReadReady(){
//qDebug()<<ba;
//qDebug()<<"***========response========"<<responseSocket->peerName()<<connectionData->path;
+ responseBuffer.append(ba);
if(parseResponse(ba)){
// package got end
- responseState = Initial;
- emit completed(connectionData);
-
+ if(bufferConnectionArray.size()>0){
+ currentSendingConnectionData = bufferConnectionArray.at(0);
+ bufferConnectionArray.remove(0);
+ }
+ emit finishSuccess(currentConnectionData);
}
- locker.unlock();
}
+
void QiPipe_Private::onResponseError(QAbstractSocket::SocketError e){
QMutexLocker locker(&mutex);
Q_UNUSED(locker);
- emit(error(connectionData));
- emit finished();
+ emit(finishedWithError(currentConnectionData));
}
+
+
void QiPipe_Private::onRequestClose(){
QMutexLocker locker(&mutex);
Q_UNUSED(locker);
- emit error(connectionData);
- emit finished();
+ emit finishSuccess(currentConnectionData);
}
+
+
void QiPipe_Private::onResponseClose(){
qDebug()<<"response close";
QMutexLocker locker(&mutex);
Q_UNUSED(locker);
requestSocket->disconnect();
requestSocket->close();
- emit error(connectionData);
- emit finished();
+ emit finishSuccess(currentConnectionData);
}
+
+
bool QiPipe_Private::parseResponse(const QByteArray &newContent){
// if got response end return true
if(responseState != HeaderFound){
@@ -266,89 +301,53 @@ bool QiPipe_Private::parseResponse(const QByteArray &newContent){
if(responseState != HeaderFound){//check if got end
return false;
}
- return parseResponseBody(newContent);
+ if(parseResponseBody(newContent)){
+ return true;
+ }
+ return false;
}
void QiPipe_Private::parseResponseHeader(const QByteArray &newContent){
Q_UNUSED(newContent)
- responseHeaderSpliterInex = responseRawData.indexOf(QByteArray("\r\n\r\n"));
- if(responseHeaderSpliterInex!=-1){
- responseState = HeaderFound;
+ responseHeaderSpliterIndex = responseBuffer.indexOf(QByteArray("\r\n\r\n"));
+ if(responseHeaderSpliterIndex!=-1){
responseHeaderSpliterSize = 4;
- qDebug()<<"\\r\\n";
- //qDebug()<<responseRawData;
- qDebug()<<responseHeaderSpliterInex;
- connectionData->setResponseHeader(responseRawData.left(responseHeaderSpliterInex));
}else{
- responseHeaderSpliterInex = responseRawData.indexOf(QByteArray("\n\n"));
- if(responseHeaderSpliterInex != -1){
- responseState = HeaderFound;
- qDebug()<<"\\n\\n";
- //qDebug()<<responseRawData;
- qDebug()<<responseHeaderSpliterInex;
- connectionData->setResponseHeader(responseRawData.left(responseHeaderSpliterInex));
+ responseHeaderSpliterIndex = responseBuffer.indexOf(QByteArray("\n\n"));
+ if(responseHeaderSpliterIndex != -1){
+ responseHeaderSpliterSize = 2;
+ }else{
+ return;
}
}
- if(responseState == HeaderFound){
- isResponseChunked = connectionData->getResponseHeader("Transfer-Encoding").toLower() == "chunked";
- responseContentLength = connectionData->getResponseHeader("Content-Length").toInt();
- responseComressType = connectionData->getResponseHeader("Content-Encoding");
- }
+
+ // got header : cut buffer & set state to HeaderFound
+ responseState = HeaderFound;
+ currentConnectionData->setResponseHeader(responseBuffer.left(responseHeaderSpliterIndex));
+ responseBuffer.remove(0,responseHeaderSpliterIndex+responseHeaderSpliterSize);
+
+ // 需要在pipe这里保存一份吗?
+ isResponseChunked = currentConnectionData->getResponseHeader("Transfer-Encoding").toLower() == "chunked";
+ responseContentLength = currentConnectionData->getResponseHeader("Content-Length").toInt();
+ responseComressType = currentConnectionData->getResponseHeader("Content-Encoding");
}
-bool QiPipe_Private::parseResponseBody(const QByteArray &newContent){
- if(connectionData->returnCode == 302
- || connectionData->returnCode == 301
- || connectionData->returnCode == 307
- || connectionData->returnCode == 204){//todo
+bool QiPipe_Private::parseResponseBody(QByteArray newContent){
+ /*
+ if(currentConnectionData->returnCode == 302
+ || currentConnectionData->returnCode == 301
+ || currentConnectionData->returnCode == 307
+ || currentConnectionData->returnCode == 204){//todo
+
+ responseState = PackageFound;
return true;
}
- Q_UNUSED(newContent)
+ */
//根据http协议,需由header及body共同判断请求是否结束。
- if(isResponseChunked){//is chuncked
- QByteArray theBody = responseRawData.mid(responseHeaderSpliterSize+responseHeaderSpliterInex);
- //theBody.replace("\r\n","\n");
- long i=0;
- long l=theBody.length();
- while(i<=l){//need to valid chunk here?
- qDebug()<<"chunked:"<<i<<" "<<l;
- int beginOfLength=theBody.indexOf('\n',i);
- if(beginOfLength == -1){
- beginOfLength = theBody.indexOf('\r\n',i);
- }
- if(beginOfLength==-1){
- return false;
- }
- int endOfLength = theBody.indexOf('\n',beginOfLength);
- if(endOfLength==-1){
- endOfLength = theBody.indexOf('\r\n',beginOfLength);
- if(endOfLength == -1){
- return false;
- }
- }
- bool isChunkValid;
- int chunkSize = theBody.mid(beginOfLength,endOfLength-beginOfLength).toInt(&isChunkValid,16);
- if(chunkSize==0){
- return true;
- }
- // don't do this until comfirm reponse done
- /*
- if(chunkSize+endOfLength+1<=l){
- connectionData->unChunkResponse.append(theBody.mid(endOfLength+1,chunkSize));
- }
- */
- if(!isChunkValid){
- return false;
- }
- i = chunkSize+endOfLength+1;
- if(i>l){
- return false;
- }
- }
- }else{
- if(responseContentLength<=responseRawData.length()-(responseHeaderSpliterSize+responseHeaderSpliterInex)){
- return true;
- }
+ responseBuffer.clear();
+ if(currentSendingConnectionData->appendResponseBody(QByteArray(newContent))){
+ responseState = PackageFound;
+ return true;
}
return false;
28 qipipe.h
View
@@ -53,10 +53,10 @@ class QiPipe_Private:public QObject{
~QiPipe_Private();
signals:
- void completed(ConnectionData_ptr);
- void error(ConnectionData_ptr);
void connected(ConnectionData_ptr);
- void finished();// error or completed
+
+ void finishedWithError(ConnectionData_ptr);
+ void finishSuccess(ConnectionData_ptr);
public slots:
void onRequestReadReady();
@@ -72,13 +72,10 @@ public slots:
void parseRequestHeader(const QByteArray & header);
bool parseResponse(const QByteArray &responseBa);
void parseResponseHeader(const QByteArray &header);
- bool parseResponseBody(const QByteArray &body);//根据http协议,需由header及body共同判断请求是否结束
+ bool parseResponseBody(QByteArray body);//根据http协议,需由header及body共同判断请求是否结束
void finishConnectionSuccess();
void finishConnectionWithError(int errno);
- QByteArray requestRawData;
- QByteArray requestRawDataHeader;
- QByteArray requestRawDataBody;
bool requestHeaderFound;
int requestHeaderSpliterSize;
@@ -88,21 +85,26 @@ public slots:
bool responseHeaderFound;
int responseHeaderSpliterSize;
- int responseHeaderSpliterInex;
+ int responseHeaderSpliterIndex;
int responseContentLength;
int responseBodyRemain;
bool isResponseChunked;
QByteArray responseComressType;
- QByteArray responseRawData;
- QByteArray responseBodyRawData;
+ QByteArray requestBuffer;
+ QByteArray responseBuffer;
+
QTcpSocket* requestSocket;
QTcpSocket* responseSocket;
- QSharedPointer<QiConnectionData> connectionData;
+ //当前正在发送的http request data
+ ConnectionData_ptr currentSendingConnectionData;
+ //当前http request data
+ ConnectionData_ptr currentConnectionData;
- QVector<ConnectionData_ptr> connectionArray;
+ // 此队列为request buffer
+ QVector<ConnectionData_ptr> bufferConnectionArray;
RequestInfo requestInfo;
QMutex mutex;
@@ -110,7 +112,7 @@ public slots:
enum State {
Connected, // response only
- BodyParsing, // response only
+ Connecting, // response only
Initial, // both
HeaderFound, // both
PackageFound // both
7 qiproxyserver.cpp
View
@@ -2,7 +2,8 @@
#include "qipipe.h"
#include <QThreadPool>
-int QiProxyServer::connectionId = 0;
+long QiProxyServer::connectionId = 0;
+QMutex QiProxyServer::connectionIdMutex;
QiProxyServer::QiProxyServer(QObject *parent) :
QTcpServer(parent){
@@ -27,10 +28,10 @@ void QiProxyServer::onPipeConnected(ConnectionData_ptr p){
Q_UNUSED(p);
}
void QiProxyServer::onPipeComplete(ConnectionData_ptr p){
- removePipe(p->socketId);
+ removePipe(p->id);
}
void QiProxyServer::onPipeError(ConnectionData_ptr p){
- removePipe(p->socketId);
+ removePipe(p->id);
}
QiPipe* QiProxyServer::addPipe(int socketDescriptor){
4 qiproxyserver.h
View
@@ -36,9 +36,9 @@ class QiProxyServer : public QTcpServer{
QMutex mutex;
static QMutex connectionIdMutex;
- static int connectionId;
+ static long connectionId;
public:
- static int nextConnectionId(){
+ static long nextConnectionId(){
QMutexLocker locker(&connectionIdMutex);
Q_UNUSED(locker)
connectionId++;
Please sign in to comment.
Something went wrong with that request. Please try again.