Commit 0046dd11a27c6519f732c0d995f483b3af7e64d7

Authored by 张宗朋
1 parent 08199d34

comm

.classpath
... ... @@ -12,7 +12,11 @@
12 12 <attribute name="maven.pomderived" value="true"/>
13 13 </attributes>
14 14 </classpathentry>
15   - <classpathentry including="**/*.java" kind="src" path="src/main/resources"/>
  15 + <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
  16 + <attributes>
  17 + <attribute name="maven.pomderived" value="true"/>
  18 + </attributes>
  19 + </classpathentry>
16 20 <classpathentry kind="src" path="src/main/resources/i18n"/>
17 21 <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
18 22 <attributes>
... ... @@ -25,5 +29,6 @@
25 29 <attribute name="maven.pomderived" value="true"/>
26 30 </attributes>
27 31 </classpathentry>
  32 + <classpathentry kind="lib" path="C:/Program Files/Java/jre7/lib/rt.jar"/>
28 33 <classpathentry kind="output" path="target/classes"/>
29 34 </classpath>
... ...
.settings/org.eclipse.wst.common.component
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project-modules id="moduleCoreId" project-version="1.5.0">
  1 +<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
3 2 <wb-module deploy-name="cnlive_live_web">
4 3 <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
5 4 <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
... ... @@ -9,9 +8,6 @@
9 8 <dependent-module archiveName="cnlive_live_model-0.0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_live_model/cnlive_live_model">
10 9 <dependency-type>uses</dependency-type>
11 10 </dependent-module>
12   - <dependent-module archiveName="cnlive_ks3-1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/cnlive_ks3/cnlive_ks3">
13   - <dependency-type>uses</dependency-type>
14   - </dependent-module>
15 11 <dependent-module archiveName="smart-framework-4.0.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/smart-framework/smart-framework">
16 12 <dependency-type>uses</dependency-type>
17 13 </dependent-module>
... ...
... ... @@ -24,9 +24,11 @@
24 24 <artifactId>maven-compiler-plugin</artifactId>
25 25 <version>2.5.1</version>
26 26 <configuration>
  27 + <failOnMissingWebXml>false</failOnMissingWebXml>
27 28 <source>1.6</source>
28 29 <target>1.6</target>
29 30 </configuration>
  31 +
30 32 </plugin>
31 33 </plugins>
32 34 </build>
... ... @@ -53,10 +55,12 @@
53 55 <artifactId>cnlive_live_model</artifactId>
54 56 <version>0.0.1-SNAPSHOT</version>
55 57 </dependency>
  58 +
  59 + <!-- -->
56 60 <dependency>
57   - <groupId>com.cnlive</groupId>
58   - <artifactId>cnlive_media_tools</artifactId>
59   - <version>1.0.0</version>
  61 + <groupId>commons-codec</groupId>
  62 + <artifactId>commons-codec</artifactId>
  63 + <version>1.6</version>
60 64 </dependency>
61 65 </dependencies>
62 66 <packaging>war</packaging>
... ...
src/main/java/com/cnlive/mz/live/action/ActivityAction.java
... ... @@ -136,7 +136,7 @@ public class ActivityAction {
136 136 int user_id = CastUtil.castInt(DataContext.getRequest().getSession().getAttribute(LiveUtils.SESSION_KEY_ID));
137 137 TActivity tActivity = tActivityService.getTActivityById(id);
138 138 List<TChannel> tChannels = tChannelService.getTChannels(user_id, 1);
139   - View view = new View("activity/activity_add.jsp");
  139 + View view = new View("live/live_edit.jsp");
140 140 List<TDefaultVideo> tDefaultVideos = tActivityService.getTDefaultVideos();
141 141 view.data("tChannels", tChannels);
142 142 view.data("tActivity", tActivity);
... ...
src/main/java/com/cnlive/mz/live/action/CheckAction.java
... ... @@ -50,15 +50,17 @@ public class CheckAction {
50 50 public Result coseLive(int id,Params params) throws UnsupportedEncodingException{
51 51 String userId = params.getString("user_id");
52 52 String streamName = userId+"_"+id;
53   - //String streamName = "498122_57";
54   - String accesskey = "I3TC8a4xboPUMe5xlp22";
55   - //accesskey = java.net.URLEncoder.encode(accesskey,"utf-8");
  53 + String accesskey = BaseUtil.getAccessKey();
  54 + accesskey = java.net.URLEncoder.encode(accesskey,"utf-8");
56 55 String signature = BaseUtil.signature(streamName);
  56 + String del = "del";
  57 + String delsignature = BaseUtil.signature(del,streamName);
57 58 String expire = BaseUtil.getTimestamp();
58 59 System.out.println(expire+"---expire---");
59 60 //添加到黑名单。。
60 61 try {
61 62 addBlackList(signature,accesskey,expire,streamName);
  63 + delBlackList(delsignature,accesskey,expire,streamName);
62 64 } catch (UnsupportedEncodingException e) {
63 65 e.printStackTrace();
64 66 }
... ... @@ -75,7 +77,7 @@ public class CheckAction {
75 77 * @throws UnsupportedEncodingException
76 78 */
77 79 public String addBlackList(String signature, String accesskey, String expire,String streamName) throws UnsupportedEncodingException {
78   - String url = "http://cnlive.dashboard.ks-cdn.com/blacklist?signature="+signature+"&accesskey="+accesskey+"&expire="+expire+"&method=add&app=live&name="+streamName;
  80 + String url = "http://cnlive.dashboard.ks-cdn.com/blacklist?signature="+signature+"&accesskey="+accesskey+"&expire="+expire+"&app=live&method=add&name=" + streamName;
79 81 System.out.println(url);
80 82 String jsonArrStr = HttpReq.getRequestWidthResult(url);
81 83 int status = HttpReq.getRequest(url);
... ... @@ -94,9 +96,10 @@ public class CheckAction {
94 96 * @throws UnsupportedEncodingException
95 97 */
96 98 public Object delBlackList(String signature, String accesskey, String expire,String streamName) throws UnsupportedEncodingException {
97   - String url = "http://cnlive.uplive.ks-cdn.com/blacklist?signature="+signature+"&accesskey="+accesskey+"&expire="+expire+"&method=del&app=live&name="+streamName;
  99 + String url = "http://cnlive.dashboard.ks-cdn.com/blacklist?signature="+signature+"&accesskey="+accesskey+"&expire="+expire+"&app=live&method=del&name=" + streamName;
  100 + System.out.println("..url.."+url);
98 101 String jsonArrStr = HttpReq.getRequestWidthResult(url);
99   - System.out.println();
  102 + System.out.println("..jsonArrStr.."+jsonArrStr);
100 103 /*Map map = JsonUtil.getMapFromJsonObjStr(jsonArrStr);
101 104 String chatRoomid = (String) map.get("Content-Length");*/
102 105 return jsonArrStr;
... ...
src/main/java/com/cnlive/mz/live/rest/BaseUtil.java
... ... @@ -21,14 +21,16 @@ import javax.crypto.spec.SecretKeySpec;
21 21  
22 22 import org.apache.commons.codec.binary.Base64;
23 23  
  24 +import com.cnlive.mz.commons.net.HttpReq;
  25 +
24 26 import sun.misc.BASE64Encoder;
25 27  
26 28 public class BaseUtil {
27 29  
28 30 private static final String ENCODING = "UTF-8";
29 31 // AccessKey、SecretKey
30   - private static final String SECRET_KEY = "7SxVU5lFpqCEQIqxLprQat9BWoyZNKlKfSScTuIk";
31   - private static final String ACCESS_KEY = "I3TC8a4xboPUMe5xlp22";
  32 + private static final String SECRET_KEY = "iqljE4WxQaSMeSd1QP+PPYSpvtK0uWyH0/r6tgi7";
  33 + private static final String ACCESS_KEY = "I3TC8a4xboN9kSJnUIQh";
32 34  
33 35 /*
34 36 * 计算MD5+BASE64
... ... @@ -88,7 +90,9 @@ public class BaseUtil {
88 90 Calendar cal = Calendar.getInstance();
89 91 cal.setTime(date);
90 92 long timestamp = cal.getTimeInMillis();
91   - return String.valueOf(timestamp).substring(0, 10);
  93 + System.out.println("------timestamp-----"+timestamp);
  94 + //return String.valueOf(timestamp).substring(0, 10);
  95 + return "1483200000";
92 96 }
93 97  
94 98 /**
... ... @@ -101,24 +105,54 @@ public class BaseUtil {
101 105 public static String signature(String streamName) throws UnsupportedEncodingException {
102 106  
103 107 String method = "GET";
104   - String Expire = BaseUtil.getTimestamp();
105   - String nonce = getUUid();
106   - System.out.println(Expire + "---expire----");
107   - String Resource = "app=live&method=add&nonce=" + nonce + "&public=0&vdoid=12345&stream=" + streamName;
108   - Resource = java.net.URLEncoder.encode(Resource, "utf-8");
109   - String stringToSign = method + "\n" + Expire + "\n" + Resource;
  108 + String expire = BaseUtil.getTimestamp();
  109 + String app = "live";
  110 + String methodadd = "add";
  111 + String name = streamName;
  112 + app = java.net.URLEncoder.encode(app, "utf-8");
  113 + methodadd = java.net.URLEncoder.encode(methodadd, "utf-8");
  114 + name = java.net.URLEncoder.encode(name, "utf-8");
  115 + System.out.println(expire + "---expire----");
  116 + String Resource = "app="+app+"&method="+methodadd+"&name=" + name;
  117 + //Resource = java.net.URLEncoder.encode(Resource, "utf-8");
  118 + String stringToSign = method + "\n" + expire + "\n" + Resource;
  119 + System.out.println("--stringToSign--"+stringToSign);
110 120 // 2.计算 HMAC-SHA1
111 121 String signature = HMACSha1(stringToSign, SECRET_KEY);
112   - System.out.println(signature + "---signature---");
  122 + System.out.println( "---signature---"+signature );
113 123 signature = java.net.URLEncoder.encode(signature, "utf-8");
114 124 return signature;
115 125 }
  126 + public static String signature(String methodNname,String streamName) throws UnsupportedEncodingException {
116 127  
  128 + String method = "GET";
  129 + String expire = BaseUtil.getTimestamp();
  130 + String app = "live";
  131 + //String methodadd = methodNname;
  132 + //String name = streamName;
  133 + app = java.net.URLEncoder.encode(app, "utf-8");
  134 + methodNname = java.net.URLEncoder.encode(methodNname, "utf-8");
  135 + streamName = java.net.URLEncoder.encode(streamName, "utf-8");
  136 + System.out.println(expire + "---expire----");
  137 + String Resource = "app="+app+"&method="+methodNname+"&name=" + streamName;
  138 + //Resource = java.net.URLEncoder.encode(Resource, "utf-8");
  139 + String stringToSign = method + "\n" + expire + "\n" + Resource;
  140 + System.out.println("--stringToSign--"+stringToSign);
  141 + // 2.计算 HMAC-SHA1
  142 + String signature = HMACSha1(stringToSign, SECRET_KEY);
  143 + System.out.println( "---signature---"+signature );
  144 + signature = java.net.URLEncoder.encode(signature, "utf-8");
  145 + return signature;
  146 + }
  147 +
117 148 public static String getUUid() {
118 149 String uuid = UUID.randomUUID().toString();
119 150 uuid = uuid.replaceAll("-", "");
120 151 return uuid;
121 152 }
  153 + public static String getAccessKey() {
  154 + return ACCESS_KEY;
  155 + }
122 156  
123 157 public static int random_7(int number) {
124 158 int x = (int) (Math.random() * 10);
... ... @@ -218,26 +252,26 @@ public class BaseUtil {
218 252 /*
219 253 * http header 参数
220 254 */
221   - String method = "GET";
222   - String Expire = "1436976000";
223   - String Resource = "nonce=4e1f2519c626cbfbab1520c255830c26&public=0&vdoid=12345";
224   - String content_type = "application/json";
225   - String path = realUrl.getFile();
226   - String date = toGMTString(new Date());
227   - // 1.对body做MD5+BASE64加密
228   - // String bodyMd5 = MD5Base64(body);
229   - String stringToSign = method + "\n" + Expire + "\n" + Resource;
230   - // 2.计算 HMAC-SHA1
231   - String signature = HMACSha1(stringToSign, ak_secret);
232   - // 3.得到 authorization header
233   - String authHeader = "Dataplus " + ak_id + ":" + signature;
  255 +// String method = "GET";
  256 +// String Expire = "1436976000";
  257 +// String Resource = "nonce=4e1f2519c626cbfbab1520c255830c26&public=0&vdoid=12345";
  258 +// String content_type = "application/json";
  259 +// String path = realUrl.getFile();
  260 +// String date = toGMTString(new Date());
  261 +// // 1.对body做MD5+BASE64加密
  262 +// // String bodyMd5 = MD5Base64(body);
  263 +// String stringToSign = method + "\n" + Expire + "\n" + Resource;
  264 +// // 2.计算 HMAC-SHA1
  265 +// String signature = HMACSha1(stringToSign, ak_secret);
  266 +// // 3.得到 authorization header
  267 +// String authHeader = "Dataplus " + ak_id + ":" + signature;
234 268 // 打开和URL之间的连接
235 269 URLConnection connection = realUrl.openConnection();
236 270 // 设置通用的请求属性
237   - connection.setRequestProperty("accept", "json");
238   - connection.setRequestProperty("content-type", content_type);
239   - connection.setRequestProperty("date", date);
240   - connection.setRequestProperty("Authorization", authHeader);
  271 +// connection.setRequestProperty("accept", "json");
  272 +// connection.setRequestProperty("content-type", content_type);
  273 +// connection.setRequestProperty("date", date);
  274 +// connection.setRequestProperty("Authorization", authHeader);
241 275 // 建立实际的连接
242 276 connection.connect();
243 277 // 定义 BufferedReader输入流来读取URL的响应
... ... @@ -283,14 +317,11 @@ public class BaseUtil {
283 317 System.out.println("..............");
284 318 // String str = signature();
285 319 // System.out.println(str);//L2muBoImPzyvwyzfBtGXEu+wRNE=
286   - /*
287   - * // 发送GET请求 String ak_id1 = "fWUN8KDtJZJGo0ArQ4qo"; //用户ak String
288   - * ak_secret1 = "UIWPYVeaV8kq2vWImDkLBvWs/pwmTJVF9MCNHDsC"; //
289   - * 用户ak_secret String url1 =
290   - * "http://cnlive.uplive.ks-cdn.com?signature=L2muBoImPzyvwyzfBtGXEu+wRNE=&accesskey=fWUN8KDtJZJGo0ArQ4qo&expire=1436976000&method=add&app=live&name=498122_57";
291   - * System.out.println("response body:" +sendGet(url1, ak_id1,
292   - * ak_secret1));
293   - */
  320 +
  321 + // 发送GET请求
  322 + String url1 = "http://cnlive.dashboard.ks-cdn.com/blacklist?signature=iDPKaesXXW3A26CScNyjpNkzxZs%3D&accesskey=I3TC8a4xboPUMe5xlp22&expire=1483200000&app=live&method=add&stream=310166_863";
  323 + System.out.println("response body:" +sendGet(url1, ACCESS_KEY, SECRET_KEY));
  324 +
294 325 // long d = getTimestamp();
295 326 // System.out.println(d);
296 327 }
... ...
src/main/resources/smart.properties
... ... @@ -25,7 +25,7 @@ sample.upload_path=/www/upload/
25 25  
26 26 mail.template_path=D:/apache-tomcat-7.0.61/webapps/cnlive_live_web/pages/mail.html
27 27 website.url=http://localhost:8080/cnlive_live_web/
28   -auth.enable=true
  28 +auth.enable=false
29 29 auth.login.url=http://sso.staff.cnlive.com/CnliveSSO/login?from=mam-live&callbackUrl=
30 30 auth.logout.url=http://sso.staff.cnlive.com/CnliveSSO/logOut?from=mam-live&callbackUrl=
31 31 auth.userinfo.url=http://sso.staff.cnlive.com/CnliveSSO/getUserInfo?username=
... ...
src/main/webapp/pages/check/check_management.jsp
... ... @@ -162,13 +162,14 @@ body {
162 162 <div id="a1_${item.id}" class="a1_class"
163 163 style="height: 150px">
164 164 <input type="hidden" value='${item.id}' name="liveid"
165   - id="liveid"> <input type="hidden"
166   - value='${item.title}' name="title" id="title"> <input
167   - type="hidden" value='${item.live_url}' name="live_url"
168   - id="live_url_${item.id}"> <input type="hidden"
169   - value='${item.start_time}' name="start_time"
170   - id="start_time"> <input type="hidden"
171   - value='${item.end_time}' name="end_time" id="end_time">
  165 + id="liveid">
  166 + <input type="hidden"value='${item.title}' name="title" id="title">
  167 + <input type="hidden" value='${item.live_url}' name="live_url"
  168 + id="live_url_${item.id}">
  169 + <input type="hidden"value='${item.start_time}' name="start_time"
  170 + id="start_time">
  171 + <input type="hidden"value='${item.end_time}' name="end_time" id="end_time">
  172 + <input type="hidden"value='${item.t_user_id}' name="t_user_id" id="t_user_${item.id}">
172 173 <%-- <h4 class="blue smaller">
173 174 <i class="icon-picture orange"></i>视频源 : ${item.title}
174 175 </h4> --%>
... ... @@ -211,7 +212,9 @@ body {
211 212  
212 213 $(".a1_class #liveid").each(function() {
213 214 var id = $(this).val();
214   - var live_url = $('#live_url_' + id).val();
  215 + var live_url = $('#live_url_' + id).val();
  216 + var t_user_id = $('#t_user_'+id).val();
  217 +
215 218 var flashvars = {
216 219 p : 1,
217 220 e : 1,
... ... @@ -220,29 +223,28 @@ body {
220 223 };
221 224 var video = [live_url ];
222 225 var support = [ 'all' ];
223   - CKobject.embedHTML5('a1_' + id, 'ckplayer_' + id,
224   - 250, 153, video, flashvars, support);
225   -
  226 + CKobject.embedHTML5('a1_' + id, 'ckplayer_' + id,250, 153, video, flashvars, support);
  227 +
226 228 //m3u8 文件播放
227   - /* var flashvars={
  229 + /* var flashvars={
228 230 f:'http://localhost:8080/cnlive_live_web/static/assets/ckplayer/m3u8.swf',
229   - a:'http://wideo01.cnlive.com/video/data1/2016/0524/124235/1500/b148a555a7984a539b56d7e17cb360f7_124235_1500.m3u8',
  231 + a:live_url,
230 232 s:4,
231 233 c:0,
232 234 p:1
233 235 };
234 236 var params={bgcolor:'#FFF',allowFullScreen:true,allowScriptAccess:'always',wmode:'transparent'};
235   - var video=['http://wideo01.cnlive.com/video/data1/2016/0524/124235/1500/b148a555a7984a539b56d7e17cb360f7_124235_1500.m3u8'];
236   - CKobject.embed('http://localhost:8080/cnlive_live_web/static/assets/ckplayer/ckplayer.swf', 'a1_' + id, 'ckplayer_' + id, 250, 153,false,flashvars,video,params); */
  237 + var video=[live_url];
  238 + CKobject.embed('http://localhost:8080/cnlive_live_web/static/assets/ckplayer/ckplayer.swf', 'a1_' + id, 'ckplayer_' + id, 250, 153,false,flashvars,video,params); */
237 239 // rtmp 直播流播放。
238   - /* var flashvars = {
  240 + /* var flashvars = {
239 241 // f:'rtmp://localhost/live/livestreame',
240   - f : 'rtmp://cnlive.uplive.ks-cdn.com/live/LIVEVJ154A34CF536',
  242 + f :'http://cnlive.uplive.ks-cdn.com/live/'+t_user_id+'_'+id,
241 243 c : 0
242 244 };
243   - var video = [ 'http://cnlive.hlslive.ks-cdn.com/live/LIVEVJ154A34CF536/index.m3u8'];
  245 + var video = [ 'http://cnlive.hlslive.ks-cdn.com/live/'+t_user_id+'_'+id+'/index.m3u8'];
244 246 CKobject.embed('../../static/assets/ckplayer/ckplayer.swf','a1_' + id, 'ckplayer_' + id, 250,
245   - 153, false, flashvars, video); */
  247 + 153, false, flashvars, video); */
246 248  
247 249 });
248 250  
... ...
src/main/webapp/pages/check/m3u8.swf deleted 100644 → 0
No preview for this file type
target/classes/com/cnlive/mz/live/LiveUtils.class deleted 100644 → 0
No preview for this file type
target/classes/com/cnlive/mz/live/action/ActivityAction.class
No preview for this file type
target/classes/com/cnlive/mz/live/action/ChannelAction.class
No preview for this file type
target/classes/com/cnlive/mz/live/action/IndexAction.class
No preview for this file type
target/classes/com/cnlive/mz/live/aspect/ActionAspect.class
No preview for this file type
target/classes/com/cnlive/mz/live/aspect/AuthFilter.class
No preview for this file type
target/classes/smart.properties
... ... @@ -25,7 +25,7 @@ sample.upload_path=/www/upload/
25 25  
26 26 mail.template_path=D:/apache-tomcat-7.0.61/webapps/cnlive_live_web/pages/mail.html
27 27 website.url=http://localhost:8080/cnlive_live_web/
28   -auth.enable=true
  28 +auth.enable=false
29 29 auth.login.url=http://sso.staff.cnlive.com/CnliveSSO/login?from=mam-live&callbackUrl=
30 30 auth.logout.url=http://sso.staff.cnlive.com/CnliveSSO/logOut?from=mam-live&callbackUrl=
31 31 auth.userinfo.url=http://sso.staff.cnlive.com/CnliveSSO/getUserInfo?username=
... ...
target/m2e-wtp/web-resources/META-INF/MANIFEST.MF
1 1 Manifest-Version: 1.0
2   -Build-Jdk: 1.6.0_45
3   -Built-By: liujicheng
  2 +Build-Jdk: 1.7.0_13
  3 +Built-By: Administrator
4 4 Created-By: Maven Integration for Eclipse
5 5  
... ...
target/m2e-wtp/web-resources/META-INF/maven/com.cnlive.mz.live.web/cnlive_live_web/pom.properties
1 1 #Generated by Maven Integration for Eclipse
2   -#Tue May 17 10:41:12 CST 2016
  2 +#Sun Jun 12 09:17:59 CST 2016
3 3 version=0.0.1-SNAPSHOT
4 4 groupId=com.cnlive.mz.live.web
5 5 m2e.projectName=cnlive_live_web
6   -m2e.projectLocation=D\:\\1_CNLIVE_JAVA_CODE\\cnlive_live_web
  6 +m2e.projectLocation=C\:\\Users\\Administrator\\git\\cnlive_live_web
7 7 artifactId=cnlive_live_web
... ...
target/m2e-wtp/web-resources/META-INF/maven/com.cnlive.mz.live.web/cnlive_live_web/pom.xml
... ... @@ -24,9 +24,11 @@
24 24 <artifactId>maven-compiler-plugin</artifactId>
25 25 <version>2.5.1</version>
26 26 <configuration>
  27 + <failOnMissingWebXml>false</failOnMissingWebXml>
27 28 <source>1.6</source>
28 29 <target>1.6</target>
29 30 </configuration>
  31 +
30 32 </plugin>
31 33 </plugins>
32 34 </build>
... ... @@ -53,10 +55,12 @@
53 55 <artifactId>cnlive_live_model</artifactId>
54 56 <version>0.0.1-SNAPSHOT</version>
55 57 </dependency>
  58 +
  59 + <!-- -->
56 60 <dependency>
57   - <groupId>com.cnlive</groupId>
58   - <artifactId>cnlive_media_tools</artifactId>
59   - <version>1.0.0</version>
  61 + <groupId>commons-codec</groupId>
  62 + <artifactId>commons-codec</artifactId>
  63 + <version>1.6</version>
60 64 </dependency>
61 65 </dependencies>
62 66 <packaging>war</packaging>
... ...
target/test-classes/com/cnlive/live/web/AppTest.class deleted 100644 → 0
No preview for this file type