-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathhttpclient.cpp
More file actions
222 lines (187 loc) · 6.83 KB
/
httpclient.cpp
File metadata and controls
222 lines (187 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
HTTP Client External Object library for Extendscript.
(Supported Adobe Illustrator, Photoshop, Bridge and Indesign)
Extendscript用Extenrnal Object。 ESTKに付属するSampleLibプロジェクトを参考に導入して下さい。
Extendscript側からは
alert(getHTTP("http://chuwa.iobb.net"));
の様な形でURLを引数として与えてコールします。
*/
#include "HttpClient.h"
#include "SoSharedLibDefs.h"
#include "SoCClient.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <unistd.h>
#if defined (_WINDOWS)
#pragma warning( push )
#pragma warning(disable : 4996) // Security warning about strcpy on win
#define strdup _strdup
#endif
#define BUF_LEN 256
#define MAX_MSGSIZE 65535
#define MSGSIZE 32
struct URL //URLを扱うための構造体 charは256文字以内
{
char host[BUF_LEN];
char path[BUF_LEN];
char query[BUF_LEN];
char fragment[BUF_LEN];
unsigned short port;
};
void parseURL(const char *urlStr, struct URL *url, char **error); //URLパーサー関数定義(本体は後ろ)
static long libraryVersionNumber = 1; //ライブラリバージョン
static char* signatures = //標準のsignature
"setVersion_d," // setVersion (int)
"createObject_ss," // createObject (string, string)
"createArray," // createArray()
"paramAny_a," // paramAny (any)
"paramString_s," // paramString (string)
"paramBool_b," // paramBool (bool)
"paramUInt32_u," // paramUInt (unsigned int)
"paramInt32_d," // paramInt (signed int)
"paramFloat64_f" // paramFloat64 (double)
"built" // built() -> string
;
#if MAC
#define unused(a) (void*) a ;
#else
void* unused(void* x){ return x;} ;
#endif
extern "C" HTTPCLIENT long ESGetVersion()
{
return libraryVersionNumber;
}
extern "C" HTTPCLIENT char* ESInitialize (TaggedData* argv, long argc) //Extendscript側から利用するイニシャライザ
{
unused(&argv);
unused(&argc);
return signatures;
}
extern "C" HTTPCLIENT void ESTerminate()
{
}
extern "C" HTTPCLIENT long setVersion (TaggedData* argv, long argc, TaggedData* result)
{
/* to keep compiler warnings from popping up */
result = NULL;
if (argc >= 1) libraryVersionNumber = argv [0].data.intval;
return kESErrOK;
}
/*
引数はURL("http://www.chuwa.iobb.net/test.php?data=10024")の様な形で与えられる。
TaggedData構造体はint・long・string・array等の各種型が含まれるため、どういった形の引数でも受け取ることが出来る。
longで受けるargcは引数の数。retvalは返り値でTaggedData構造体を指定している為返す形式は後で決める。
*/
extern "C" HTTPCLIENT long getHTTP (TaggedData* argv, long argc, TaggedData* retval) //HTTPクライアント用
{
int s; //ソケット用 descripter
struct addrinfo hints, *res; //struct in_addr addr;
int err;
char *urlstrng;
char send_buf[BUF_LEN]; //送信クエリの為のバッファ
struct URL url = { "chuwa-print.co.jp", "/", 80 };
if (argc == 1)
{
char *error = NULL;
urlstrng = argv[0].data.string;
parseURL(urlstrng, &url, &error);
if (error) return kESErrBadURI; //kESErrBadURI は整数で31と定義されている。Extendscript側では対応するエラーメッセージを受け取ることになる。
}
//ソケットの構成
memset(&hints, 0, sizeof(hints));// clear to 0
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;
char *serviceType = "http";
if ((err = getaddrinfo(url.host, serviceType, &hints, &res)) != 0)
{
return kESErrBadURI;
}
if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
{
return kESErrIO; //エラー定義はSoSharedLibDef.hにある。エラーメッセージは受け取るアプリケーションよってはローカライズされる。
}
if (connect(s, res->ai_addr, res->ai_addrlen) != 0)
{
return kESErrNoResponse;
}
sprintf(send_buf, "GET %s%s HTTP/1.0\r\n", url.path, url.query); //送信用クエリを組み立てて送信用バッファに格納
write(s, send_buf, strlen(send_buf)); //バッファに格納されたクエリを送信。プロトコル仕様に関してはW3Cの資料を参照のこと
sprintf(send_buf, "Host: %s:%d\r\n", url.host, url.port); //以下バッファ上にクエリを組み立て順次送信する
write(s, send_buf, strlen(send_buf));
sprintf(send_buf, "\r\n");
write(s, send_buf, strlen(send_buf)); //空改行で送信終了となる
/*送信終了後サーバレスポンスはソケットのバッファに蓄積されるのでこれを取出していく必要がある*/
int read_size;
char tmp[MAX_MSGSIZE]; //受信用テンポラリ
int ctr;
ctr = 0;
while (ctr<MAX_MSGSIZE)
{
char buf[BUF_LEN];//読み込みバッファの定義
read_size = read(s, buf, BUF_LEN); //ソケットから読み込みバッファに受信データを取り込む
if (read_size > 0) //取り出したデータがある場合
{
sprintf(tmp,"%s", buf);//テンポラリに読み込みバッファの内容を結合
}
else
{
break; //ソケット側が空なら受信終了
}
}
close(s); //ソケットをクローズする。
retval->type = kTypeString; //返り値の型はstring
retval->data.string = tmp; //retvalの構造体のstringにテンポラリ(char)をそのまま渡す。
return kESErrOK; //kESErrOKは0を返す。正常終了した場合、返り値のtypeがチェックされ構造体内の適切な値がExtendscript側に返される
}
/*
URLパーサー
「http://」や「/」、「#」、「?」を目印に引数で与えられた文字列をパスやクエリに分解する。
ポートは80番で決め打ち
*/
void parseURL(const char *urlStr, struct URL *url, char **error)
{
char host_path[BUF_LEN];
if (strlen(urlStr) > BUF_LEN - 1)
{
return;
}
if (strstr(urlStr, "http://") && sscanf(urlStr, "http://%s", host_path) && strcmp(urlStr, "http://"))
{
char *p = NULL;
p = strchr(host_path, '#');
if (p != NULL)
{
strcpy(url->fragment, p);
*p = '\0';
}
p = strchr(host_path, '?');
if (p != NULL)
{
strcpy(url->query, p);
*p = '\0';
}
else
{
strcpy(url->query, "");
}
p = strchr(host_path, '/');
if (p != NULL)
{
strcpy(url->path, p);
*p = '\0';
}
strcpy(url->host, host_path);
url->port = 80;
}
else
{
return;
}
}
#if defined (_WINDOWS)
#pragma warning( pop )
#endif